ctfshow Web入门[文件上传] Writeup
常见的上传漏洞
web151
“前台校验不可靠”
前端 js 验证, 同时对图片内容进行了验证
上传抓包改后缀
web152
之前的图片马抓包改后缀上传直接就成功了
看了 wp 才发现是在验证 MIME Type (Content-Type)
web153
一开始试了好几个后缀都不成功 (应该是黑名单验证)
网上查了一下考察的是 .user.ini
https://www.cnblogs.com/NineOne/p/14033391.html
我的理解是用户层面的 php.ini
(类似于 dll 查找优先级), 一部分配置 (除了 PHP_INI_SYSTEM 以外) 可以优先于 php.ini
生效
其中的两个配置 auto_append_file
auto_prepend_file
能用来制造后门
auto_append_file
在该目录下的所有文件尾部包含某个文件的内容, auto_prepend_file
则是在文件头部包含某个文件的内容
注意这个是不能跨目录的, .user.ini
的作用范围被限制在了上传后所在的文件夹, 但这里碰巧的是 /upload/ 目录下存在一个 index.php
根据黑名单机制, 我们先上传图片马, 然后上传 .user.ini
, 内容如下
|
|
注意修改 Content-Type, 而且文件名要加引号
访问 index.php
web154
图片不能正常上传
测试了一下发现是检测了文件内容中的 php
字符串
将 php 改成 =
即可绕过 (或者 php
修改为大写)
|
|
加 =
的效果类似 echo
之后配合 .user.ini
或者是利用 PHP 短标签, 将一句话改为 <? eval($_REQUEST['a']);?>
.user.ini
改为如下内容
|
|
上传即可
使用 <script>
标签也可以, 未测试
web155
过滤了 PHP
, 忽略大小写
利用 <?=
<?
短标签依然可以绕过
web156
自己的图片马有点问题, 把代码删掉还是传不了
看了师傅的 wp 发现是过滤了 []
用 {}
绕过
|
|
web157
[]
{}
, ;
都被过滤了
考虑到机器是 Linux, 使用 system()
执行文件查看 flag.php
php
被过滤了, 但是可以用通配符 *
|
|
最后一个分号可以省略 (一句话的情况下)
之后访问 /upload/index.php 右键查看 flag
web158
同上
web159
又过滤了 ()
用反引号绕过
|
|
web160
反引号和空格也被过滤了, 没想出来
网上 wp 的思路是通过文件包含
nginx 默认日志地址为 /var/log/nginx/access.log
默认格式
|
|
include
注意 log 被过滤了, 需要拼接字符串
|
|
更改 User-Agent 为 PHP 一句话, 再访问一次网站即可
也可以用伪协议, 字符串拼接绕过过滤
|
|
web161
增加了对文件头的验证
Content-Type, filename 文件头都是 gif 格式的竟然上传不了
把前两个改成 png 就能上传了
使用 GIF89a 的原因是他是 jpg png gif bmp 中唯一一个可以以字符串表示的文件头
获取 flag 方法同上
后来查了一下发现是利用 getimagesize()
验证文件头的
web162
.
flag
被过滤了
看了 wp 才知道考察的是 session 文件包含 + 条件竞争
https://www.php.net/manual/zh/session.upload-progress.php
php.ini 相关配置
|
|
在相关选项开启的情况下, 我们如果在上传文件的过程中 POST 一个变量 PHP_SESSION_UPLOAD_PROGRESS
, PHP 就会创建一个对应的 session 文件, 文件内包含 PHP_SESSION_UPLOAD_PROGRESS
的值
如果 session.use_strict_mode = Off
时, 我们可以通过在 Cookie 中设置 PHPSESSID=123
(默认 prefix 为 PHPSESSID) 来指定 session 文件名为 sess_123
(否则就是 sess_[32位随机字符串]
)
当 session.upload_progress.cleanup = On
的话比较麻烦, 因为要条件竞争
upload.html
|
|
.user.ini
|
|
header 改 Cookie: PHPSESSID=123
上传即可
测试了好几次都不行, intruder 线程多一点就503, 少一点就竞争不了
b站的视频是非预期解 https://www.bilibili.com/video/BV1Qf4y1u7cU
利用 IP 长地址, 不过访问了一下发现 index 文件已经被改回去了
IP 长地址转换 https://www.bejson.com/convert/ip2int/
手头上没有 vps, 这题先放着…
web163
同上
web164
图片上传后被重命名, 必须上传真实的图片文件, 而且只允许上传 png
http://b16c225d-f117-436b-9f62-11758ba84604.challenge.ctf.show/download.php?image=fb5c81ed3a220004b71069645f112867.png
上传成功后右键查看 PHP 一句话消失了, 估计是二次渲染
download.php 猜测是文件包含
PHP 通过 gd 库实现二次渲染
|
|
https://www.php.net/manual/zh/ref.image.php
注意 gif png jpeg 绕过二次渲染的方法并不相同
参考这篇文章 https://xz.aliyun.com/t/2657
这里直接贴 png payload 的代码
|
|
生成的一句话是 <?=$_GET[0]($_POST[1]);?>
上传后传参
web165
上传 png
burp 抓包无数据, 应该是前端验证
上传后发现文件也被重命名了, 估计跟上题一样是二次渲染
jpg payload 用上面文章给出的 payload 生成
jpg 要多试几个, 因为有的文件可能会有特殊字符导致解析失败
或者直接用我这个也行
web166
ext 改成了 zip
http://2cba3dcb-0c03-48ad-9ebf-f13b51325b9c.challenge.ctf.show/upload/download.php?file=f30ecfc1838f32aacb20a1d0d258d4a1.zip
文件类型不合规, 限制了是 zip 后缀
发现直接改一句话上传就行
download.php 读取 zip
web167
hint 是 httpd
404 界面显示 Apache/2.4.25 (Debian) Server
文件名没有改变
明显是考察 .htaccess
https://www.cnblogs.com/ggc-gyx/p/16412236.html
.htaccess
|
|
查看 flag
web168
基础免杀
过滤了 eval assert get post cookie 关键词
用 $_REQUEST
绕过
|
|
这次是 nginx, php 后缀直接就能上传…
eval assert 都不太好使, 用 system 执行命令
web169
高级免杀
nginx 服务器, <
>
都被过滤了, 但是 php 后缀能上传
Content-Type 好像必须是 image/png 才行
upload 目录下没有 index.php, 但因为我们可以自行上传 php
所以配合 .user.ini 包含 nginx 日志
连接 http://1b28bec0-f7f1-48c0-a4a7-1359931ee9ba.challenge.ctf.show/upload/2.php
得到 flag
web170
终极免杀
同上