跨站请求伪造漏洞

article/2025/9/23 3:36:14

首先说明一下什么是CSRF(Cross Site Request Forgery)?

跨站请求伪造是指攻击者可以在第三方站点制造HTTP请求并以用户在目标站点的登录态发送到目标站点,而目标站点未校验请求来源使第三方成功伪造请求。

为什么会有CSRF?

JS控制浏览器发送请求的时候,浏览器是根据目标站点,而不是来源站点,来发送cookie的,如果当前会话中有目标站点的cookie,就发送出去。核心问题是浏览器的会话机制,是跨站请求伪造漏洞的根源。

 

CSRF(Cross-site request forgery跨站请求伪造,也被称成为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。

 

解决方法有三种:

1 使用token

2 限制refer

3 使用验证码技术

 

 

一、CSRF攻击原理

 

CSRF攻击原理比较简单,如图1所示。其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。

 

跨站请求伪造CSRF防护方法

 

图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& amp;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);}else{
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);} else{// 从 HTTP 头中取得 csrftokenString xhrToken = req.getHeader(“csrftoken”);// 从请求参数中取得 csrftokenString 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);}else{
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 值为空,则不附加 csrftokenif(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;} else {//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代码示例:

 

请看下面一个简单的应用,它允许用户购买钢笔或铅笔。界面上包含下面的表单:

 

<form action="buy.php" method="POST"><p>Item:<select name="item"><option name="pen">pen</option><option name="pencil">pencil</option></select><br />Quantity: <input type="text" name="quantity" /><br /><input type="submit" value="Buy" /></p></form>

 

下面的buy.php程序处理表单的提交信息:

 

<?phpsession_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>';}else{echo '<p>There was a problem with your order.</p>';}}?>

 

攻击者会首先使用这个表单来观察它的动作。例如,在购买了一支铅笔后,攻击者知道了在购买成功后会出现感谢信息。注意到这一点后,攻击者会尝试通过访问下面的URL以用GET方式提交数据是否能达到同样的目的:

 

http://store.example.org/buy.php?item=pen&quantity=1

 

如果能成功的话,攻击者现在就取得了当合法用户访问时,可以引发购买的URL格式。在这种情况下,进行跨站请求伪造攻击非常容易,因为攻击者只要引发受害者访问该URL即可。

 

请看下面对前例应用更改后的代码:

 

phpsession_start();$token = md5(uniqid(rand(), TRUE));$_SESSION['token'] = $token;$_SESSION['token_time'] = time();?>

 

表单:

 

<form action="buy.php" method="POST"><input type="hidden" name="token" value="<?php echo $token; ?>" /><p>Item:<select name="item"><option name="pen">pen</option><option name="pencil">pencil</option></select><br />Quantity: <input type="text" name="quantity" /><br /><input type="submit" value="Buy" /></p></form>

 

通过这些简单的修改,一个跨站请求伪造攻击就必须包括一个合法的验证码以完全模仿表单提交。由于验证码的保存在用户的session中的,攻击者必 须对每个受害者使用不同的验证码。这样就有效的限制了对一个用户的任何攻击,它要求攻击者获取另外一个用户的合法验证码。使用你自己的验证码来伪造另外一 个用户的请求是无效的。

 

该验证码可以简单地通过一个条件表达式来进行检查:

 

<?phpif (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token']){/* Valid Token */}?>

 

你还能对验证码加上一个有效时间限制,如5分钟:

 

<?php$token_age = time() - $_SESSION['token_time'];if ($token_age <= 300){/* Less than five minutes has passed. */}?>

 

通过在你的表单中包括验证码,你事实上已经消除了跨站请求伪造攻击的风险。可以在任何需要执行操作的任何表单中使用这个流程。

 

 

http://netsecurity.51cto.com/art/201308/407554.htm

http://netsecurity.51cto.com/art/201104/256035.htm


http://chatgpt.dhexx.cn/article/sEaVxpaX.shtml

相关文章

DVWA---跨站请求伪造CSRF

CSRF&#xff0c;全称Cross-site request forgery&#xff0c;翻译过来就是跨站请求伪造&#xff0c;是指利用受害者尚未失效的身份认证信息&#xff08;cookie、会话等&#xff09;&#xff0c;诱骗其点击恶意链接或者访问包含攻击代码的页面&#xff0c;在受害人不知情的情况…

CSRF 跨站请求伪造攻击

1.概念 全称是CSRF 跨站请求伪造攻击&#xff0c;攻击者利用用户已登陆的账号&#xff0c;诱导用户访问已构造好的恶意链接或页面&#xff0c;在用户不之情的情况下&#xff0c;做一些违反用户本意的一些违法操作。 同源策略&#xff1a;协议相同&#xff0c;域名相同&#xf…

CSRF-跨站请求伪造的原理与修复方式

CSRF: Cross site Request Forgery 跨站请求伪造 原理&#xff1a; 利用xss方式注入一段脚本&#xff0c;通过伪装来自受信任用户的请求来利用受信任的网站&#xff0c;当受害者在浏览器中运行该脚本时&#xff0c;脚本仿冒受害者&#xff0c;向合法的web系统发送一个请求&…

web基础漏洞之CSRF(跨站请求伪造漏洞)

cookie session token 我觉得在开始学习CSRF之前应该先学会区分这三种东西&#xff1a;cookie session token cookie: Cookie&#xff0c;有时也用其复数形式 Cookies。类型为“小型文本文件”&#xff0c;是某些网站为了辨别用户身份&#xff0c;进行Session跟踪而储存在用户…

Laravel框架之CSRF跨站请求伪造

一、CSRF攻击 1、什么是CSRF攻击 CSRF是跨站请求伪造&#xff08;Cross-site request forgery&#xff09;的英文缩写&#xff0c; 原理图示&#xff1a; csrf在laravel框架中的使用&#xff0c;就是在客户端form表单中设置一个_token表单域 同时把该表单域的值记录给sessi…

什么是CSRF(跨站请求伪造)?

文章目录 1. CSRF是什么&#xff1f;1.1 CSRF攻击细节CSRF攻击原理及过程如下&#xff1a; 2. CSRF漏洞检测3. 防御CSRF攻击&#xff1a;3.1 验证 HTTP Referer 字段3.1.1 优点&#xff1a;3.1.2 缺点: 3.2 在请求地址中添加 token 并验证3.3 在 HTTP 头中自定义属性并验证 1. …

WordPress 跨站请求伪造漏洞

WordPress 跨站请求伪造漏洞 漏洞ID2500593漏洞类型跨站请求伪造发布时间2021-07-08更新时间2021-07-09 CVE编号CVE-2021-20781 CNNVD-IDCNNVD-202107-420漏洞平台N/ACVSS评分N/A 漏洞简介 WordPress是Wordpress基金会的一套使用PHP语言开发的博客平台。该平台支持在PHP和My…

056 CSRF跨站请求伪造

文章目录 一&#xff1a; 概述二&#xff1a;关键点三&#xff1a;目标四&#xff1a;CSRF攻击如何触发&#xff1f;五&#xff1a;实战&#xff1a;CSRF场景复现六&#xff1a;CSRF防御6.1 无效的防御6.2 有效的防御 一&#xff1a; 概述 跨站请求伪造&#xff08;cross site…

CSRF - 跨站请求伪造

什么是CSRF? CSRF&#xff08;Cross-site request forgery&#xff09;跨站请求伪造&#xff1a;也被称为“One Click Attack”或者Session Riding&#xff0c;通常缩写为CSRF或者XSRF&#xff0c;是一种对网站的恶意利用。尽管听起来像跨站脚本&#xff08;XSS&#xff09;&a…

CSRF(跨站请求伪造)

目录 CSRF 原理及过程 概述 关键点 pikachu靶场之CSRF GET型 POST型 Token 防御 如何挖掘CSRF漏洞 使用burp验证csrf 总结 CSRF (Cross-Site Request Forgery) CSRF是一种欺骗受害者提交恶意请求的攻击&#xff0c;攻击者盗用你的身份&#xff0c;向服务器发送请求…

Spring Boot项目CSRF (跨站请求伪造)攻击演示与防御

CSRF ,Cross-site request forgery,跨站请求伪造。是常见的网络攻击的方式之一,2007年曾被列为互联网20大安全隐患之一。攻击过程是攻击者伪造用户的浏览器请求,访问一个用户曾经访问过的网站, 使目标网站误以为是用户的操作而执行命令。 本篇j基于Spring Boot创建项目,…

每日漏洞 | 跨站请求伪造

01 漏洞描述 HTTP的无状态性&#xff0c;导致Web应用程序必须使用会话机制来识别用户。一旦与Web站点建立连接(访问、登录)&#xff0c;用户通常会分配到一个Cookie&#xff0c;随后的请求&#xff0c;都会带上这个Cookie&#xff0c;这样Web站点就很容易分辨请求来自哪个用户&…

CSRF跨站请求伪造

CSRF介绍&#xff1a; CSRF中文名称&#xff1a;跨站请求伪造&#xff0c;是一种“ 挟持用户”在当前已登陆的Web应用程序上执行“ 非本意操作”的攻击方法。 一、CSRF回放攻击流程 套用老师所给的一张攻击原理图 从这张流程图里我们总结一下CSRF攻击生效所需要的两个必要条件 …

【CSRF-01】跨站请求伪造漏洞基础原理及攻防

目录 1 CSRF概述2 CSRF攻击过程及原理2.1 CSRF场景例子2.2 攻击过程2.3 原理2.4 攻击成功的条件&#xff1a; 3 CSRF攻击方式/如何触发5 CSRF的防御5.1 一些无效的防御手段5.2 有效的防御手段 6 总结参考文章 1 CSRF概述 定义&#xff1a;CSRF&#xff08;Cross-site request …

一文带你学习跨站点请求伪造(CSRF)

一文带你学习跨站点请求伪造&#xff08;CSRF&#xff09; 1.何为CSRF2.浏览器的Cookie策略3.P3P头的副作用4.CSRF攻击流程5.CSRF的分类GET型POST-表单型POST-JSON型 6.CSRF的快速验证7.CSRF的防御验证码Referer CheckAnti CSRF Token 1.何为CSRF CSRF的全名是Cross Site Requ…

flask中的csrf防御机制

csrf概念 CSRF&#xff08;Cross-site request forgery&#xff09;跨站请求伪造&#xff0c;也被称为“One Click Attack”或者Session Riding&#xff0c;通常缩写为CSRF或者XSRF&#xff0c;是一种对网站的恶意利用。尽管听起来像跨站脚本&#xff08;XSS&#xff09;&…

跨站请求伪造(csrf)

1、csrf介绍 CSRF (Cross-site request forgery&#xff0c;跨站请求伪造)也被称为One Click Attack或者Session Riding&#xff0c;通常缩写为CSRF或者XSRF&#xff0c;是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS)&#xff0c;但它与XSS非常不同&#xff0c;XSS利用站…

跨站请求伪造

1. 什么是跨站请求伪造&#xff08;CSRF&#xff09; CSRF&#xff08;Cross-site request forgery跨站请求伪造&#xff0c;也被称为“One Click Attack”或者Session Riding&#xff0c;通常缩写为CSRF或者XSRF&#xff0c;是一种对网站的恶意利用。尽管听起来像跨站脚本&…

压缩包破解

压缩包破解 文章目录 压缩包破解伪加密压缩包格式压缩源文件数据区压缩源文件目录区压缩源文件目录结束标志真加密字节对比伪加密字节对比伪加密 工具 ZipCenOp.jarjoin 破解fcrackzip 或者 ziperello 暴力破解伪加密 压缩包格式 一个 ZIP 文件由三个部分组成: 压缩源文

android apk解包和打包

最近项目开发&#xff0c;我的jar包和资源文件给别的同事打包&#xff0c;这样我自己测试很麻烦&#xff0c;每次改一点东西都要找人打包测试&#xff0c;很麻烦&#xff0c;就想着能够解包&#xff0c;更新一下自己的部分代码&#xff0c;再打包apk直接测试。后来找了一些网上…