有哪些方法可以不使用csrf token就能使用token防御csrff

中国领先的IT技术网站
51CTO旗下网站
跨站请求伪造CSRF防护方法
CSRF(Cross-site request forgery跨站请求伪造,也被称成为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。
作者:褪色的黑来源:FreebuF| 10:59
CSRF(Cross-site request forgery跨站请求伪造,也被称成为&one click attack&或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。
一、CSRF攻击原理
CSRF攻击原理比较简单,如图1所示。其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。
图1 CSRF攻击原理
1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
4. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
5. 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
二、CSRF漏洞防御
CSRF漏洞防御主要可以从三个层面进行,即服务端的防御、用户端的防御和安全设备的防御。
1、&服务端的防御
.1.1 验证HTTP Referer字段
根据HTTP协议,在HTTP头中有一个字段叫Referer,它记录了该HTTP请求的来源地址。在通常情况下,访问一个安全受限页面的请求必须来自于同一个网站。比如某银行的转账是通过用户访问http://bank.test/test?page=10&userID=101&money=10000页面完成,用户必须先登录bank.test,然后通过点击页面上的按钮来触发转账事件。当用户提交请求时,该转账请求的Referer值就会是转账按钮所在页面的URL(本例中,通常是以bank. test域名开头的地址)。而如果攻击者要对银行网站实施CSRF攻击,他只能在自己的网站构造请求,当用户通过攻击者的网站发送请求到银行时,该请求的Referer是指向攻击者的网站。因此,要防御CSRF攻击,银行网站只需要对于每一个转账请求验证其Referer值,如果是以bank. test开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果Referer是其他网站的话,就有可能是CSRF攻击,则拒绝该请求。
1.2 在请求地址中添加token并验证
CSRF攻击之所以能够成功,是因为攻击者可以伪造用户的请求,该请求中所有的用户验证信息都存在于Cookie中,因此攻击者可以在不知道这些验证信息的情况下直接利用用户自己的Cookie来通过安全验证。由此可知,抵御CSRF攻击的关键在于:在请求中放入攻击者所不能伪造的信息,并且该信息不存在于Cookie之中。鉴于此,系统开发者可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器端建立一个拦截器来验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。
1.3 在HTTP头中自定义属性并验证
自定义属性的方法也是使用token并进行验证,和前一种方法不同的是,这里并不是把token以参数的形式置于HTTP请求之中,而是把它放到HTTP头中自定义的属性里。通过XMLHttpRequest这个类,可以一次性给所有该类请求加上csrftoken这个HTTP头属性,并把token值放入其中。这样解决了前一种方法在请求中加入token的不便,同时,通过这个类请求的地址不会被记录到浏览器的地址栏,也不用担心token会通过Referer泄露到其他网站。
2、 其他防御方法
1. CSRF攻击是有条件的,当用户访问恶意链接时,认证的cookie仍然有效,所以当用户关闭页面时要及时清除认证cookie,对支持TAB模式(新标签打开网页)的浏览器尤为重要。
2. 尽量少用或不要用request()类变量,获取参数指定request.form()还是request. querystring (),这样有利于阻止CSRF漏洞攻击,此方法只不能完全防御CSRF攻击,只是一定程度上增加了攻击的难度。
代码示例:
Java 代码示例
下文将以 Java 为例,对上述三种方法分别用代码进行示例。无论使用何种方法,在服务器端的拦截器必不可少,它将负责检查到来的请求是否符合要求,然后视结果而决定是否继续请求或者丢弃。在 Java 中,拦截器是由 Filter 来实现的。我们可以编写一个 Filter,并在 web.xml 中对其进行配置,使其对于访问所有需要 CSRF 保护的资源的请求进行拦截。
在 filter 中对请求的 Referer 验证代码如下
清单 1. 在 Filter 中验证 Referer
// 从 HTTP 头中取得 Referer 值
String referer=request.getHeader(&Referer&);
// 判断 Referer 是否以 bank.example 开头
if((referer!=null) &&(referer.trim().startsWith(&bank.example&))){
chain.doFilter(request, response);
request.getRequestDispatcher(&error.jsp&).forward(request,response);
以上代码先取得 Referer 值,然后进行判断,当其非空并以 bank.example 开头时,则继续请求,否则的话可能是 CSRF 攻击,转到 error.jsp 页面。
如果要进一步验证请求中的 token 值,代码如下
清单 2. 在 filter 中验证请求中的 token
HttpServletRequest req = (HttpServletRequest)request;
HttpSession s = req.getSession();
// 从 session 中得到 csrftoken 属性
String sToken = (String)s.getAttribute(&csrftoken&);
if(sToken == null){
// 产生新的 token 放入 session 中
sToken = generateToken();
s.setAttribute(&csrftoken&,sToken);
chain.doFilter(request, response);
// 从 HTTP 头中取得 csrftoken
String xhrToken = req.getHeader(&csrftoken&);
// 从请求参数中取得 csrftoken
String pToken = req.getParameter(&csrftoken&);
if(sToken != null && xhrToken != null && sToken.equals(xhrToken)){
chain.doFilter(request, response);
}else if(sToken != null && pToken != null && sToken.equals(pToken)){
chain.doFilter(request, response);
request.getRequestDispatcher(&error.jsp&).forward(request,response);
首先判断 session 中有没有 csrftoken,如果没有,则认为是第一次访问,session 是新建立的,这时生成一个新的 token,放于 session 之中,并继续执行请求。如果 session 中已经有 csrftoken,则说明用户已经与服务器之间建立了一个活跃的 session,这时要看这个请求中有没有同时附带这个 token,由于请求可能来自于常规的访问或是 XMLHttpRequest 异步访问,我们分别尝试从请求中获取 csrftoken 参数以及从 HTTP 头中获取 csrftoken 自定义属性并与 session 中的值进行比较,只要有一个地方带有有效 token,就判定请求合法,可以继续执行,否则就转到错误页面。生成 token 有很多种方法,任何的随机算法都可以使用,Java 的 UUID 类也是一个不错的选择。
除了在服务器端利用 filter 来验证 token 的值以外,我们还需要在客户端给每个请求附加上这个 token,这是利用 js 来给 html 中的链接和表单请求地址附加 csrftoken 代码,其中已定义 token 为全局变量,其值可以从 session 中得到。
清单 3. 在客户端对于请求附加 token
function appendToken(){
updateForms();
updateTags();
function updateForms() {
// 得到页面中所有的 form 元素
var forms = document.getElementsByTagName('form');
for(i=0; i&forms.length; i++) {
var url = forms[i].action;
// 如果这个 form 的 action 值为空,则不附加 csrftoken
if(url == null || url == && ) continue;
// 动态生成 input 元素,加入到 form 之后
var e = document.createElement(&input&);
e.name = &csrftoken&;
e.value = token;
e.type=&hidden&;
forms[i].appendChild(e);
function updateTags() {
var all = document.getElementsByTagName('a');
var len = all.length;
// 遍历所有 a 元素
for(var i=0; i&len; i++) {
var e = all[i];
updateTag(e, 'href', token);
function updateTag(element, attr, token) {
var location = element.getAttribute(attr);
if(location != null && location != '' '' ) {
var fragmentIndex = location.indexOf('#');
var fragment = null;
if(fragmentIndex != -1){
//url 中含有只相当页的锚标记
fragment = location.substring(fragmentIndex);
location = location.substring(0,fragmentIndex);
var index = location.indexOf('?');
if(index != -1) {
//url 中已含有其他参数
location = location + '&csrftoken=' + token;
//url 中没有其他参数
location = location + '?csrftoken=' + token;
if(fragment != null){
location += fragment;
element.setAttribute(attr, location);
在客户端 html 中,主要是有两个地方需要加上 token,一个是表单 form,另一个就是链接 a。这段代码首先遍历所有的 form,在 form 最后添加一隐藏字段,把 csrftoken 放入其中。然后,代码遍历所有的链接标记 a,在其 href 属性中加入 csrftoken 参数。注意对于 a.href 来说,可能该属性已经有参数,或者有锚标记。因此需要分情况讨论,以不同的格式把 csrftoken 加入其中。
如果你的网站使用 XMLHttpRequest,那么还需要在 HTTP 头中自定义 csrftoken 属性,利用 dojo.xhr 给 XMLHttpRequest 加上自定义属性代码如下:
清单 4. 在 HTTP 头中自定义属性
var plainXhr = dojo.xhr;// 重写 dojo.xhr 方法
dojo.xhr = function(method,args,hasBody) {
// 确保 header 对象存在
args.headers = args.header || {};
tokenValue = '&%=request.getSession(false).getAttribute(&csrftoken&)%&';
var token = dojo.getObject(&tokenValue&);
// 把 csrftoken 属性放到头中
args.headers[&csrftoken&] = (token) ? token : &
return plainXhr(method,args,hasBody);
这里改写了 dojo.xhr 的方法,首先确保 dojo.xhr 中存在 HTTP 头,然后在 args.headers 中添加 csrftoken 字段,并把 token 值从 session 里拿出放入字段中。
PHP代码示例:
请看下面一个简单的应用,它允许用户购买钢笔或铅笔。界面上包含下面的表单:
action=&buy.php& method=&POST&
name=&item&
name=&pen&pen
name=&pencil&pencil
type=&text& name=&quantity&
type=&submit& value=&Buy&
下面的buy.php程序处理表单的提交信息:
session_start();
$clean = array();
if (isset($_REQUEST['item'] && isset($_REQUEST['quantity']))
/* Filter Input ($_REQUEST['item'], $_REQUEST['quantity']) */
if (buy_item($clean['item'], $clean['quantity']))
echo '&p&Thanks for your purchase.&/p&';
echo '&p&There was a problem with your order.&/p&';
攻击者会首先使用这个表单来观察它的动作。例如,在购买了一支铅笔后,攻击者知道了在购买成功后会出现感谢信息。注意到这一点后,攻击者会尝试通过访问下面的URL以用GET方式提交数据是否能达到同样的目的:
http://store.example.org/buy.php?item=pen&quantity=1
如果能成功的话,攻击者现在就取得了当合法用户访问时,可以引发购买的URL格式。在这种情况下,进行跨站请求伪造攻击非常容易,因为攻击者只要引发受害者访问该URL即可。
请看下面对前例应用更改后的代码:
session_start();
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();?&
action=&buy.php& method=&POST&
&input type=&hidden& name=&token& value=&&?php echo $token; ?&& /&
name=&item&
name=&pen&pen
name=&pencil&pencil
type=&text& name=&quantity&
type=&submit& value=&Buy&
通过这些简单的修改,一个跨站请求伪造攻击就必须包括一个合法的验证码以完全模仿表单提交。由于验证码的保存在用户的session中的,攻击者必须对每个受害者使用不同的验证码。这样就有效的限制了对一个用户的任何攻击,它要求攻击者获取另外一个用户的合法验证码。使用你自己的验证码来伪造另外一个用户的请求是无效的。
该验证码可以简单地通过一个条件表达式来进行检查:
if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token'])
/* Valid Token */
你还能对验证码加上一个有效时间限制,如5分钟:
$token_age = time() - $_SESSION['token_time'];
if ($token_age &= 300)
/* Less than five minutes has passed. */
通过在你的表单中包括验证码,你事实上已经消除了跨站请求伪造攻击的风险。可以在任何需要执行操作的任何表单中使用这个流程。【编辑推荐】【责任编辑: TEL:(010)】
大家都在看猜你喜欢
热点头条头条热点关注
24H热文一周话题本月最赞
讲师:110745人学习过
讲师:10458人学习过
讲师:24856人学习过
精选博文论坛热帖下载排行
本书全面、深入地介绍了网络应用技术,主要内容包括:RMS权限管理服务、Exchange邮件服务、LCS即时消息服务、WSUS系统更新服务、Symantec网...
订阅51CTO邮刊& & & &上文我转载了两篇关于ThinkPHP令牌验证的文章()。其中提及到了 &token ,这里针对 token 的作用,转载了另外两篇文章。
web安全之token
参考:http://blog.csdn.net/sum_rain/article/details/&
Token,就是令牌,最大的特点就是随机性,不可预测。一般黑客或软件无法猜测出来。&
那么,Token有什么作用?又是什么原理呢?&
Token一般用在两个地方:&
1)防止表单重复提交、&2)anti&csrf攻击(跨站点请求伪造)。&
两者在原理上都是通过session&token来实现的。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,然后将Token发给客户端(一般通过构造hidden表单)。下次客户端提交请求时,Token会随着表单一起提交到服务器端。&
然后,如果应用于&anti&csrf攻击&,则服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则可以证明请求有效,不是伪造的。&
不过,如果应用于&防止表单重复提交&,服务器端第一次验证相同过后,会将session中的Token值更新下,若用户重复提交,第二次的验证判断将失败,因为用户提交的表单中的Token没变,但服务器端session中Token已经改变了。&
上面的session应用相对安全,但也叫繁琐,同时当多页面多请求时,必须采用多Token同时生成的方法,这样占用更多资源,执行效率会降低。因此,也可用cookie存储验证信息的方法来代替session&Token。比如,应对&重复提交&时,当第一次提交后便把已经提交的信息写到cookie中,当第二次提交时,由于cookie已经有提交记录,因此第二次提交会失败。&
不过,cookie存储有个致命弱点,如果cookie被劫持(xss攻击很容易得到用户cookie),那么又一次gameover。黑客将直接实现csrf攻击。&
所以,安全和高效相对的。具体问题具体对待吧。&
此外,要避免&加token但不进行校验&的情况,在session中增加了token,但服务端没有对token进行验证,根本起不到防范的作用。&
还需注意的是,对数据库有改动的增删改操作,需要加token验证,对于查询操作,一定不要加token,防止攻击者通过查询操作获取token进行csrf攻击。但并不是这样攻击者就无法获得token,只是增大攻击成本而已。&
Web安全之CSRF攻击
CSRF是什么?&
CSRF(Cross&Site&Request&Forgery),中文是跨站点请求伪造。CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份在攻击页面对目标网站发起伪造用户操作的请求,达到攻击目的。&
举个例子&简单版:&
假如博客园有个加关注的GET接口,blogUserGuid参数很明显是关注人Id,如下:&
那我只需要在我的一篇博文内容里面写一个img标签:&
那么只要有人打开我这篇博文,那就会自动关注我。&
假如博客园还是有个加关注的接口,不过已经限制了只获取POST请求的数据。这个时候就做一个第三方的页面,但里面包含form提交代码,然后通过QQ、邮箱等社交工具传播,诱惑用户去打开,那打开过博客园的用户就中招了。&
在说例子之前要纠正一个iframe问题,有人会直接在第三方页面这样写。如下:&
&!DOCTYPE HTML&
&html lang=&en-US&&
&title&CSRF SHOW&/title&
&!--不嵌iframe会跳转--&
&iframe style=&display:&&
name=&form1& action=&/mvc/Follow/FollowBlogger.aspx& method=&post&&
&input type=&hidden& name=&blogUserGuid& value=&4e8c33d0-77fe-df11-ac81-842b2b196315&/&
&input type=&submit& value&
  document.forms.form1.submit();
这样是用问题的,由于同源策略的原因,iframe内容根本加载不出来,所以里面form提交当然不会执行。&
PS:我尝试了chrome、IE11、Firefox,情况都是这样。&
所以可以用嵌多一层页面方式解决,如下:&
第一个展示页面(test):&
&!DOCTYPE HTML&
&html lang=&en-US&&
&title&CSRF SHOW&/title&
&iframe style=&display:& src=&test2.html&&&/iframe&
第二个隐藏页面(test2):&
&!DOCTYPE HTML&
&html lang=&en-US&&
&title&CSRF GET&/title&
name=&form1& action=&/mvc/Follow/FollowBlogger.aspx& method=&post&&
&input type=&hidden& name=&blogUserGuid& value=&4e8c33d0-77fe-df11-ac81-842b2b196315&/&
&input type=&submit& value&
  document.forms.form1.submit();
这样就可以解决了,有人会问为什么要加多一层iframe,因为不嵌iframe页面会重定向,这样就降低了攻击的隐蔽性。另外我们test页面不使用XMLHTTPRequest发送POST请求,是因为有跨域的问题,而form可以跨域post数据。&
假如博客园还是有个加关注的接口,已经限制POST,但博文内容是直接贴进HTML(未过滤),那就遭受XSS攻击。那么就可以直接把上面代码嵌入博文,那么只要有人打开我这篇博文,还是会自动关注我,这组合攻击方式称为XSRF。&
CSRF攻击的本质原因&
CSRF攻击是源于Web的隐式身份验证机制!Web的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。CSRF攻击的一般是由服务端解决。&
CSRF工具的防御手段&
1.&尽量使用POST,限制GET&
GET接口太容易被拿来做CSRF攻击,看第一个示例就知道,只要构造一个img标签,而img标签又是不能过滤的数据。接口最好限制为POST使用,GET则无效,降低攻击风险。&
当然POST并不是万无一失,攻击者只要构造一个form就可以,但需要在第三方页面做,这样就增加暴露的可能性。&
2.&浏览器Cookie策略&
IE6、7、8、Safari会默认拦截第三方本地Cookie(Third-party&Cookie)的发送。但是Firefox2、3、Opera、Chrome、Android等不会拦截,所以通过浏览器Cookie策略来防御CSRF攻击不靠谱,只能说是降低了风险。&
PS:Cookie分为两种,Session&Cookie(在浏览器关闭后,就会失效,保存到内存里),Third-party&Cookie(即只有到了Exprie时间后才会失效的Cookie,这种Cookie会保存到本地)。&
PS:另外如果网站返回HTTP头包含P3P&Header,那么将允许浏览器发送第三方Cookie。&
3.&加验证码&
验证码,强制用户必须与应用进行交互,才能完成最终请求。在通常情况下,验证码能很好遏制CSRF攻击。但是出于用户体验考虑,网站不能给所有的操作都加上验证码。因此验证码只能作为一种辅助手段,不能作为主要解决方案。&
4.&Referer&Check&
Referer&Check在Web最常见的应用就是&防止图片盗链&。同理,Referer&Check也可以被用于检查请求是否来自合法的&源&(Referer值是否是指定页面,或者网站的域),如果都不是,那么就极可能是CSRF攻击。&
但是因为服务器并不是什么时候都能取到Referer,所以也无法作为CSRF防御的主要手段。但是用Referer&Check来监控CSRF攻击的发生,倒是一种可行的方法。&
5.&Anti&CSRF&Token&
现在业界对CSRF的防御,一致的做法是使用一个Token(Anti&CSRF&Token)。&
1.&用户访问某个表单页面。&
2.&服务端生成一个Token,放在用户的Session中,或者浏览器的Cookie中。&
3.&在页面表单附带上Token参数。&
4.&用户提交请求后,&服务端验证表单中的Token是否与用户Session(或Cookies)中的Token一致,一致为合法请求,不是则非法请求。&
这个Token的值必须是随机的,不可预测的。由于Token的存在,攻击者无法再构造一个带有合法Token的请求实施CSRF攻击。另外使用Token时应注意Token的保密性,尽量把敏感操作由GET改为POST,以form或AJAX形式提交,避免Token泄露。&
CSRF的Token仅仅用于对抗CSRF攻击。当网站同时存在XSS漏洞时候,那这个方案也是空谈。所以XSS带来的问题,应该使用XSS的防御方案予以解决。&
CSRF攻击是攻击者利用用户的身份操作用户帐户的一种攻击方式,通常使用Anti&CSRF&Token来防御CSRF攻击,同时要注意Token的保密性和随机性。&
参考文献:&
2.&《白帽子讲Web安全》&
本文为原创文章,转载请保留原出处,方便溯源,如有错误地方,谢谢指正。&
本文地址:
本文已收录于以下专栏:
相关文章推荐
原文地址:点击打开链接
最近模拟登陆,发现CsrfToken是个很麻烦的问题,所以看了一下CsrfToken的一些介绍。发现这篇文章写得很不错,所以转载过来。
CSRF 背景与介绍
图是由定点的非空有限集合V与变得集合E组成的,其形式化定义为:G = (V, E),若图中的每一条边是没有方向的则称G为无向图,否则称为有向图。图的表示方法有邻接矩阵和邻接表表示法。图的常见算法有深度...
同事在做数据抓取的时候,发现该提交的参数都提交了,但是返回的数据总是提醒“非法的请求或者超时”;我拿过来检查了半天也没见查出问题,无奈对比了下这个页面和另外一个页面的http头信息,端倪出来了,这页面...
1.利用iframe进行跨域post提交
2.csrf的攻击和防御措施
3.使用token保护请求
4.关于webapp跨域提交的问题
问题前因如果用户已经登录了我们的a.com网站,用户又打开了一个恶意网站 ,那么可以向a.com发送http请求,比如发送ajax,并且在发送时,可以通过设置ajax的...
/architecture/18661.html
XSRF全称是 cross-site request forgery(跨站点请求伪造),也称...
转载地址:/reprint/csrf.html
       CSRF概念:CSRF跨站点请求伪造(Cross—Site Request Forgery...
本文介绍什么是CSRF攻击,及如何在ASP.NET MVC网站应用程序中阻止CSRF攻击。
【名词解释】
跨域:https://developer.mozilla.org/en-US/docs/JavaScript/Same_origin_policy_for_JavaScript
同源策略...
三、PHP网络编程
[!!!]1.禁用COOKIE后SEESION还能用吗?(51.com笔试题)
可以,COOKIE和SESSION都是用来实现会话机制的,由于http协议是无状态的,所...
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)跨域post 及 使用token防止csrf 攻击
时间: 17:10:05
&&&& 阅读:313
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
后台使用的python - flask
前台使用angular框架
1.一个跨域post的样例:
跨域post有多种实现方式:
2.利用iframe
3.server proxy:
样例使用的为iframe,想要证明,在没有进行csrf防御时,随意攻击者能够利用javascript发送 post 请求。从而简单的提交或获取数据资料;
1.本地test.html页面
type="text/javascript" src="jquery-2.1.4.min.js"&&
type="button" onclick="test();" value="test"/&
type="text/javascript"&
function test() {
crossDomainPost({
url: ‘http://localhost:5000/test‘,
param: {a: ‘1‘, b: ‘2‘},
onSubmit: function (e) {
console.log(e);
function crossDomainPost(config) {
var def = {
: function (i) {}
= $.extend({}, def, config);
if (!config.url) {
config.onSubmit({error: ‘URL is Empty!‘});
var createGuid
= function () {
var guid = "";
for (var i = 1; i &= 10; i++) {
guid += Math.floor(Math.random() * 16.0).toString(16);
removeElement = function (_element) {
var _parentElement = _element.parentN
if (_parentElement) {
_parentElement.removeChild(_element);
var iframe
= document.createElement("iframe");
var uniqueString
= createGuid();
document.body.appendChild(iframe);
iframe.style.display
iframe.contentWindow.name = uniqueS
= document.createElement("form");
form.target = uniqueS
form.action = config.
form.method = "POST";
for (var item in config.param) {
= document.createElement("input");
input.type
= "hidden";
input.name
input.value = config.param[ item ];
form.appendChild(input);
document.body.appendChild(form);
form.submit();
}catch(e){
console.log(‘error‘);
consoel.log(e);
setTimeout(function () {
config.onSubmit(iframe);
removeElement(form);
}, config.delay);
2.后台接收代码
这里仅接收POST的请求
@app.route(‘/test‘ ,methods=[‘POST‘])
def test():
print ‘param is :‘;
print request.form
return jsonify(data=‘2222‘)
3.控制台输出:
服务端处理了非站内的请求
4.浏览器输出:
本地test.html获取到返回信息
跨站请求攻击。简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去訪问一个自己以前认证过的站点并运行一些操作(如发邮件,发消息,甚至財产操作如转账和购买商品)。因为浏览器以前认证过。所以被訪问的站点会觉得是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证仅仅能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
你这能够这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包含:以你名义发送邮件。发消息,盗取你的账号。甚至于购买商品,虚拟货币转账……造成的问题包含:个人隐私泄露以及財产安全。
从上图能够看出,要完毕一次CSRF攻击,受害者必须依次完毕两个步骤:
登录受信任站点A,并在本地生成Cookie。
在不登出A的情况下,訪问危急站点B。
看到这里。你或许会说:“假设我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此。但你不能保证下面情况不会发生:
1.你不能保证你登录了一个站点后,不再打开一个tab页面并訪问另外的站点。
2.你不能保证你关闭浏览器了后,你本地的Cookie立马过期,你上次的会话已经结束。
3.上图中所谓的攻击站点。可能是一个存在其它漏洞的可信任的常常被人訪问的站点。
原理具体:
2.常见的攻击类型:
1.GET类型的CSRF
仅仅须要一个HTTP请求。就能够构造一次简单的CSRF。
银行站点A:它以GET请求来完毕银行转账的操作,如:
危急站点B:它里面有一段HTML的代码例如以下:
src=http:///Transfer.php?toBankId=11&money=1000&
首先。你登录了银行站点A,然后訪问危急站点B,噢,这时你会发现你的银行账户少了1000块
为什么会这样呢?原因是银行站点A违反了HTTP规范,使用GET请求更新资源。在訪问危急站点B的之前。你已经登录了银行站点A,而B中的以GET的方式请求第三方资源(这里的第三方就是指银行站点了,原本这是一个合法的请求,但这里被不法分子利用了)。所以你的浏览器会带上你的银行站点A的Cookie发出Get请求,去获取资源/Transfer.php?toBankId=11&money=1000 ,结果银行站点服务器收到请求后,觉得这是一个更新资源操作(转账操作),所以就立马进行转账操作
2.POST类型的CSRF
如上边的跨域POST样例
3.怎样防御CSRF
1.提交验证码
在表单中添加一个随机的数字或字母验证码。通过强制用户和应用进行交互。来有效地遏制CSRF攻击。
2.Referer Check
检查假设是非正常页面过来的请求,则极有可能是CSRF攻击。
3.token验证
在 HTTP 请求中以參数的形式添加一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,假设请求中没有
token 或者 token 内容不对,则觉得可能是 CSRF 攻击而拒绝该请求。
token须要足够随机
敏感的操作应该使用POST。而不是GET,以form表单的形式提交。能够避免token泄露。
4.在 HTTP 头中自己定义属性并验证
这样的方法也是使用 token 并进行验证。这里并非把 token 以參数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自己定义的属性里。通过 XMLHttpRequest 这个类,能够一次性给全部该类请求加上 csrftoken 这个 HTTP 头属性。并把 token 值放入当中。这样攻克了上种方法在请求中添加 token 的不便。同一时候,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用操心 token 会透过 Referer 泄露到其它站点中去。
4.关于token
Token 应该被保存起来(放到 )
Tokens 除了像 cookie 一样有有效期。而且你能够有很多其它的操作方法。一旦 token 过期,仅仅须要又一次获取一个。你能够使用一个接口去刷新 token。你甚至能够把 token 原来的公布时间也保存起来。而且强制在两星期后又一次登录什么的。假设你须要撤回 tokens(当 token 的生存期比較长的时候这非常有必要)那么你须要一个 token 的生成管理器去作检查。
Local / session storage 不会跨域工作,请使用一个标记 cookie
有须要的话,要加密而且签名 token
将 JSON Web Tokens 应用到 OAuth 2
1.引入csrf
from flask_wtf.csrf import CsrfProtect
csrf = CsrfProtect()
app = Flask(__name__)
csrf.init_app(app)
app.config[‘SECRET_KEY‘]=‘myblog‘
2.在站内页面上head中,添加token
name="csrf-token" content="{{ csrf_token() }}&
3.配置angular提交表头
app.config(function ($httpProvider) {
$httpProvider.mon[‘X-CSRF-Token‘] = $(‘meta[name=csrf-token]‘).attr(‘content‘);
4.再次測试跨域post
后台输出:
前台输出:
关于webapp跨域Post使用token思路:
移动端登录时,服务端验证表单信息。登陆成功,生成token,返回给client;
client将token存在localstorage/sessionstorage中。每次提交表单。都须要携带token;
服务端获取请求。假设没有token,则忽略请求;
出现的问题:
服务端须要限制登陆次数
解决方法:
client添加登陆间隔。请求一次后,等待x秒才干再次请求
服务端做cas验证
服务端须要保存用户的token,及过期时间;
解决方法:
能够将token 保存在Memcache,数据库中,redis
client存token时。须要对token加密
解决方法:
在存储的时候把token进行对称加密存储,用时解开
将请求URL、时间戳、token三者进行合并加盐签名。服务端校验有效性
当然。以上仅仅防君子,不防小人
跨域post请求:
跨站请求伪造:
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&国之画&&&& &&&&chrome插件&&
版权所有 京ICP备号-2
迷上了代码!}

我要回帖

更多关于 csrf防御token生成 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信