CSRF简介

article/2025/9/24 6:48:26

一.CSRF是什么?

CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。

二.CSRF可以做什么?

你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。

三.CSRF漏洞现状

CSRF这种攻击方式在2000年已经被国外的安全人员提出,但在国内,直到06年才开始被关注,08年,国内外的多个大型社区和交互网站分别爆出CSRF漏洞,如:NYTimes.com(纽约时报)、Metafilter(一个大型的BLOG网站),YouTube和百度HI…而现在,互联网上的许多站点仍对此毫无防备,以至于安全业界称CSRF为“沉睡的巨人”。

四.CSRF的原理

下图简单阐述了CSRF攻击的思想:

从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:

1.登录受信任网站A,并在本地生成Cookie。

2.在不登出A的情况下,访问危险网站B。

看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:

1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。

2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了…)

3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。

上面大概地讲了一下CSRF攻击的思想,下面我将用几个例子详细说说具体的CSRF攻击,这里我以一个银行转账的操作作为例子(仅仅是例子,真实的银行网站没这么傻:>)

示例1

银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000

危险网站B,它里面有一段HTML的代码如下:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块…

为什么会这样呢?原因是银行网站A违反了HTTP规范,使用GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中的 <img> 以GET的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏览器会带上你的银行网站A的Cookie发出Get请求,去获取资源“http://www.mybank.com/Transfer.php?toBankId=11&money=1000”,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账操作),所以就立刻进行转账操作…

示例2

为了杜绝上面的问题,银行决定改用POST请求完成转账操作。

银行网站A的WEB表单如下:

	<form action="Transfer.php" method="POST"><p>ToBankId: <input type="text" name="toBankId" /></p><p>Money: <input type="text" name="money" /></p><p><input type="submit" value="Transfer" /></p></form>

后台处理页面Transfer.php如下:

	<?phpsession_start();if (isset($_REQUEST['toBankId'] && isset($_REQUEST['money'])){buy_stocks($_REQUEST['toBankId'], $_REQUEST['money']);}?>

危险网站B,仍然只是包含那句HTML代码:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

和示例1中的操作一样,你首先登录了银行网站A,然后访问危险网站B,结果…和示例1一样,你再次没了1000块~T_T,这次事故的原因是:银行后台使用了$_REQUEST去获取请求的数据,而 $_REQUEST 既可以获取 GET 请求的数据,也可以获取 POST 请求的数据,这就造成了在后台处理程序无法区分这到底是GET请求的数据还是 POST 请求的数据。在 PHP 中,可以使用 G E T 和 ‘ _GET和 ` GET_POST分别获取GET请求和 POST请求的数据。在JAVA中,用于获取请求数据request一样存在不能区分GET请求数据和POST` 数据的问题。

示例3

经过前面2个惨痛的教训,银行决定把获取请求数据的方法也改了,改用 $_POST,只获取 POST 请求的数据,后台处理页面Transfer.php代码如下:

	<?phpsession_start();if (isset($_POST['toBankId'] && isset($_POST['money'])){buy_stocks($_POST['toBankId'], $_POST['money']);}?>

然而,危险网站B与时俱进,它改了一下代码:

<html><head><script type="text/javascript">function steal(){iframe = document.frames["steal"];iframe.document.Submit("transfer");}</script></head><body οnlοad="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>

如果用户仍是继续上面的操作,很不幸,结果将会是再次不见1000块…因为这里危险网站B暗地里发送了POST请求到银行!

总结一下上面3个例子,CSRF主要的攻击模式基本上是以上的3种,其中以第1,2种最为严重,因为触发条件很简单,一个就可以了,而第3种比较麻烦,需要使用JavaScript,所以使用的机会会比前面的少很多,但无论是哪种情况,只要触发了CSRF攻击,后果都有可能很严重。

理解上面的3种攻击模式,其实可以看出,CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的

五.CSRF的防御

CSRF的防御可以从服务端客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。

1.服务端进行CSRF防御

服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数

(1).Cookie Hashing(所有表单都包含同一个伪随机值):

这可能是最简单的解决方案了,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败了:>

	<?php//构造加密的Cookie信息$value = “DefenseSCRF”;setcookie(”cookie”, $value, time()+3600);?>

在表单里增加Hash值,以认证这确实是用户发送的请求。

	<?php$hash = md5($_COOKIE['cookie']);?><form method=”POST” action=”transfer.php”><input type=”text” name=”toBankId”><input type=”text” name=”money”><input type=”hidden” name=”hash” value=”<?=$hash;?>”><input type=”submit” name=”submit” value=”Submit”></form>

然后在服务器端进行Hash值验证

 	<?phpif(isset($_POST['check'])) {$hash = md5($_COOKIE['cookie']);if($_POST['check'] == $hash) {doJob();} else {//...}} else {//...}?>

这个方法个人觉得已经可以杜绝99%的CSRF攻击了,那还有1%呢…由于用户的Cookie很容易由于网站的XSS漏洞而被盗取,这就另外的1%。一般的攻击者看到有需要算Hash值,基本都会放弃了,某些除外,所以如果需要100%的杜绝,这个不是最好的方法。

(2).验证码

这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,厄…这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,还有听闻是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。

(3).One-Time Tokens(不同的表单包含一个不同的伪随机值)

在实现One-Time Tokens时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。

以下我的实现:

1).先是令牌生成函数(gen_token()):

	<?phpfunction gen_token() {//这里我是贪方便,实际上单使用Rand()得出的随机数作为令牌,也是不安全的。//这个可以参考我写的Findbugs笔记中的《Random object created and used only once》$token = md5(uniqid(rand(), true));return $token;}

2).然后是Session令牌生成函数(gen_stoken()):

	<?phpfunction gen_stoken() {$pToken = "";if($_SESSION[STOKEN_NAME]  == $pToken){//没有值,赋新值$_SESSION[STOKEN_NAME] = gen_token();}   else{//继续使用旧的值}}?>

3).WEB表单生成隐藏输入域的函数:

	<?phpfunction gen_input() {gen_stoken();echo<input type=\”hidden\” name=\”" . FTOKEN_NAME . “\”value=\”" . $_SESSION[STOKEN_NAME] . “\”>;}?>

4).WEB表单结构:

	<?phpsession_start();include(”functions.php”);?><form method=”POST” action=”transfer.php”><input type=”text” name=”toBankId”><input type=”text” name=”money”><? gen_input(); ?><input type=”submit” name=”submit” value=”Submit”></FORM>

5).服务端核对令牌:

这个很简单,这里就不再啰嗦了。

六.参考文献

[1].Preventing CSRF

[2].Security Corner: Cross-Site Request Forgeries

[3].《深入解析跨站请求伪造漏洞:原理剖析》

[4].《Web安全测试之跨站请求伪造(CSRF)》

[5].《深入解析跨站请求伪造漏洞:实例讲解》

[6].http://baike.baidu.com/view/1609487.htm


http://chatgpt.dhexx.cn/article/7sWysXZ8.shtml

相关文章

django种表单post出现CSRF verification failed( CSRF验证失败 ) 的两种解决方案

现象 表单界面如下&#xff1a; 在点击提交之后&#xff0c;出现如下错误页面&#xff1a; HTML的代码如下&#xff1a; contact_form.html <!DOCTYPE HTML PUBLIC ><html> <head><title>Contact us</title> </head><body><h1&…

Django CSRF验证失败. 请求被中断.

项目场景&#xff1a; Python版本&#xff1a;3.7 Django版本&#xff1a;3.1.7 问题描述&#xff1a; 出现了CSRF验证失败. 请求被中断. 原因分析&#xff1a; 在Django中有个设定&#xff0c;防止跨域来请求。比如有爬虫&#xff0c;爬虫不是从网站根目录开始搜寻&#x…

detail: “CSRF Failed: CSRF token missing or incorrect 问题解决方法

如果你尝试了所有方法之后还是没用&#xff0c;那定位你的Ajax方法&#xff1a; 1&#xff0c;var $crf_token $(‘[name“csrfmiddlewaretoken”]’).attr(‘value’) 2&#xff0c;headers:{“X-CSRFToken”: $crf_token} 原因分析&#xff1a; 这是由于你的django,有一个…

CSRF防御之token认证

一、CSRF是什么&#xff1f; CSRF&#xff08;Cross-site request forgery&#xff09;&#xff0c;中文名称&#xff1a;跨站请求伪造。攻击者盗用你的身份&#xff0c;以你的名义发送恶意请求。CSRF能够做的事情包括&#xff1a;以你名义发送邮件&#xff0c;发消息&#xf…

禁止访问 (403)CSRF验证失败. 请求被中断.

出现这个问题是因为django在收到表单提交过来的信息时&#xff0c;会检查提交过来的信息中是否有token,并会对token进行校验&#xff0c;如果校验通过&#xff0c;那就继续执行&#xff0c;反之就会认定这次的数据有伪造的风险。 解决方案&#xff1a; 在项目的settings.py文…

禁止访问 (403) CSRF验证失败. 请求被中断.————错误处理(测试接口时遇到的问题)

问题描述 解决措施 在Header参数中添加Content-Type和X-CSRFToken信息&#xff0c;这样就不会报错了。 运行结果

通过验证Referer解决CSRF安全防御问题

一、背景 JAVAWEB 类项目处于客户验收阶段&#xff0c;在安全扫描处出现 CSRF 问题&#xff0c;通过多个博客中解决思路都无法解决。后来通过同事提醒 可以试试判断 Referer页面来源参数&#xff0c;最终使用该方法解决问题。 二、环境 服务器&#xff1a;Linux 前端&#…

CSRF实战案例—绕过referer值验证

在一个添加管理员的界面引起了我的注意 尝试添加一个管理员&#xff0c;如下添加成功&#xff0c;我们可以观察其请求包中并未存在token字段&#xff0c;可能存在csrf漏洞。但是存在“Referer”和“Origin”字段 我们把referer字段删了只剩origin&#xff0c;查看是否可以请求成…

访问django后台,提示CSRF验证失败. 请求被中断.Referer checking failed - **** does not match any trust

1.非debug模式看到的报错 2.settings打开debug模式&#xff0c;才能把报错信息看的详细 3.去settings.py中&#xff0c;找到CsrfViewMiddleware 中间件&#xff0c;点击进入 4.搜索匹配报错信息 5.往下看看用到这个关键字的地方 6.从源码第一行开始看 7.settings.py&…

安全认证中的CSRF

1、什么叫做CSRF攻击 简单地说&#xff0c;就是说恶意网站&#xff0c;虽然没有盗取你的用户名和密码信息&#xff0c;但是却可以伪装成你&#xff0c;然后登录到银行&#xff0c;或者等危险网站&#xff0c;模拟你进行操作。利用的就是cookies这个特性&#xff0c;即浏览器提供…

csrf验证问题 -- 不同域名下Iframe嵌套Cookie失效导致csrf验证失败

问题原因 Cookie:SameSite Chrome 51 开始&#xff0c;浏览器的 Cookie 新增加了一个SameSite属性&#xff0c;主要用于防止CSRF攻击和用户追踪。 cookie的SameSite属性用来限制第三方Cookie&#xff0c;从而减少安全风险(防止CSRF)。 SameSite可以有下面三种值&#xff1a;…

接口报403,报CSRF验证失败的问题

问题定位&#xff1a;后台两个接口重名&#xff0c;走了优先级更高的接口&#xff0c;接口没有过滤CSRF&#xff1b; 一、csrf是什么 CSRF&#xff08;Cross-site request forgery&#xff09;跨站请求伪造&#xff0c;是一种常见的web安全漏洞&#xff0c;概括地说就是指&…

Django的csrf豁免:解决CSRF验证失败,请求被中断问题

1.CSRF介绍 跨站请求伪造&#xff08;英语&#xff1a;Cross-site request forgery&#xff09;&#xff0c;也被称为 one-click attack 或者 session riding&#xff0c;通常缩写为 CSRF 或者 XSRF&#xff0c; 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的…

解决:禁止访问 (403) CSRF验证失败

在测试Django框架POST请求方式时&#xff0c;程序报错如下 在确保访问安全的情况下有一下两种方式&#xff1a; 1、在相应html文件form代码块中添加如下代码&#xff1a; <form method"post" action"/method_show/">{% csrf_token %} <!-- 改行…

Ubiquant LGBM Baseline 九坤量化大赛 版本44

数据描述&#xff1a; 该数据集包含来自数千项投资的真实历史数据的特征。你的挑战是预测与做出交易决策相关的模糊指标的价值。 Your challenge is to predict the value of an obfuscated metric relevant for making trading decisions. 这是一个代码竞赛&#xff0c;它依…

lgbm的roc曲线,auc计算

lgbm模型画ROC曲线 1、得到分类的概率 import numpy as npimport pandas as pdimport lightgbm as lgbfrom sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test \train_test_split(data.iloc[:, 0:-1], # featuredata.iloc[:, -1], # label…

LightGBM C++使用问题

~~~~~~~~~~~~~~~~~~~~串行single sample predict~~~~~~~~~~~~~~~~~~~~~~~~~ python下已测试通过&#xff0c;无问题&#xff1a; 然而C下问题是&#xff1a; 1&#xff0c;首先是与python下概率不一致&#xff1b; 2&#xff0c;然后是所有输入的结果都一样 初步怀疑版本问题…

kaggle学习笔记-otto-baseline5-LGBM的使用

数据处理 import polars as pltrain pl.read_parquet(../input/otto-train-and-test-data-for-local-validation/test.parquet) train_labels pl.read_parquet(../input/otto-train-and-test-data-for-local-validation/test_labels.parquet)def add_action_num_reverse_chr…

LightGBM(LGB)

转载自littlemichelle LightGBM&#xff08;Light Gradient Boosting Machine&#xff09;是一个实现GBDT算法的框架&#xff0c;支持高效率的并行训练&#xff0c;并且具有更快的训练速度、更低的内存消耗、更好的准确率、支持分布式可以快速处理海量数据等优点。 背景 常用…

lgbm参数分析及回归超参数寻找

参考&#xff1a;lgbm的github: https://github.com/Microsoft/LightGBM/blob/master/docs/Parameters.rst 代码来源参见我另一篇博客&#xff1a; https://blog.csdn.net/ssswill/article/details/85217702 网格搜索寻找超参数&#xff1a; from sklearn.model_selection imp…