跨站请求伪造
概述
跨站请求伪造(Cross-site request forgery:CSRF)是一种攻击:它强制终端用户在当前对其进行身份验证后的web应用程序上执行非本意的操作。发生在客户端!
CSRF攻击的着重点在伪造更改状态的请求,而不是盗取数据,因为攻击者无法查看对伪造请求的响应。
借助社工的一些帮助(例如通过电子邮件或聊天发送链接),攻击者可以诱骗用户执行攻击者选择的操作。如果受害者是普通用户,则成功的CSRF攻击可以强制用户执行状态更改的请求,例如转移资金,更改其电子邮件地址等。如果受害者是管理帐户,CSRF可能会危及整个web应用程序。
关键点
CSRF是一种欺骗受害者提交恶意请求的攻击。它继承了受害者的身份和特权,代表受害者执行非本意、恶意的操作。
对于大多数站点,浏览器请求自动发送与站点关联的所有凭据,例如用户的会话cookie,IP地址,windows域凭据等。
因此,如果用户当前已对该站点进行了身份验证,则该站点将无法区分受害者发送的伪造请求和受害者发送的合法请求。
目标
CSRF攻击目标是能够更改服务器状态或数据的业务或功能,例如更改受害者的电子邮件地址、密码或购买商品。强制受害者查询数据,对于攻击者来说没什么用,因为无法获得服务器响应。因此,CSRF攻击针对引起状态变化的请求。
有时可以将CSRF攻击存储在易受攻击的站点上。这些漏洞被称为“存储的CSRF漏洞”。这可以通过简单地在接受HTML的字段中存储<img>
或<iframe>
标记,或通过更复杂的跨站点脚本攻击来实现。如果攻击可以在站点中存储CSRF攻击,则攻击的严重性会被放大。特别是,受到攻击的可能性增加,因为受害者比互联网上的某个随机页面更有可能查看包含攻击的页面。
例如:更改密码
以DVWA为例:当然这容易被看出来,我们可以自己写一个精美的html页面,将url放进去诱使用户点击
我们拿到修改密码的url来伪造CSRF请求:http://192.168.35.129/DVWA-master/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#
诱使用户在已经登陆的的情况下访问这个url:
密码就被更改了:
利用
GET型CSRF
GET型的CSRF利用很简单,只需要一个HTTP请求:
自动加载:<img src="http://IP/路径?参数1=...&参数2=..."/>
需要点击:<a href="http://IP/路径?参数1=...&参数2=...">快点鸡窝</a>
自动加载:<iframe src="http://IP/路径?参数1=...&参数2=..." style="display:none"></iframe>
自动加载:
body{
background:#00FF00 url('http://IP/路径?参数1=...&参数2=...');
}
或者使用嵌入式:
<h1 style="background:#00FF00 url('http://IP/路径?参数1=...&参数2=...');">csrf</h1>
可以将这些写入html页面中
POST型CSRF
需要构造一个表单:
<form action="http://IP/路径" method="post">
<input type="hidden" name="参数" value="值">
</form>
<script>document.form[0].submit();</script>//设置自动提交
防御
- 验证Referer字段
验证HTTP Referer中记录的请求来源地址是否为合法用户地址
缺陷:服务器并非任何时候都可以取到Referer。例如HTTPS跳转到HTTP。
<?php
if(stripos($_SERVER['HTTP_REFERER'],'xx.com')!=false){
//判断成功
}else{
//判断失败
}
?>
如果服务端只判断当前的Referer中是否具有域名,那么可以使用新建文件夹(文件夹名字为原来正常访问的域名)进行绕过
- 二次验证
重要功能点使用动态验证码或者提供当前用户密码进行CSRF防护,因为从用户体验来讲,不能每个操作都加上验证码啥的 - 添加token验证
- 可以将token值放在session中,在服务器端对比POST提交的参数的token与session中绑定的token是否一致。在form表单中一般将token字段写入隐藏域中。
<?php
session.start();//开启session
function token_generate(){
$sum="dadasd".date("h:i:s");//生成随机token
$token=md5($sum);//进行md5加密
return $token;
}
$token = token_generate();
$_SESSION['user_token'] = $token;
?>
<html>
<head>
<meta charset="utf8">
</head>
<body>
<h1>CSRF_TOKEN</h1>
<form action="check.php" method="post">
<input type="text">
<input type="hidden" name="user_token" value="<?php echo $token;?>">
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
check.php:对比token是否一致
<?php
session.start();
if($_SESSION['user_token'] == $_POST['user_token']){
echo "successful";
}else{
echo "fail";
}
?>
- 可以在HTTP请求中以参数的形式加入一个随机产生的token(随机字符串),并在服务器端建立一个拦截器来验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。
- 用户养成良好的习惯
对于普通用户来说,都学习并具备网络安全知识以防御网络攻击是不现实的。但若用户养成良好的上网习惯,则能够很大程度上减少CSRF攻击的危害。例如,用户上网时,不要轻易点击网络论坛、聊天室、即时通讯工具或电子邮件中出现的链接或者图片﹔及时退出长时间不使用的已登录账户,尤其是系统管理员,应尽量在登出系统的情况下点击未知链接和图片。除此之外,用户还需要在连接互联网的计算机上安装合适的安全防护软件,并及时更新软件厂商发布的特征库,以保持安全软件对最新攻击的实时跟踪。
CSRF的探测
手动探测
原理:手动探测原理在于探测web应用程序是否具有防止CSRF的措施。
如果Web 应用的HTTP 请求中没有对应的预防措施,那么很大程度上就确定存在CSRF漏洞。
自动化探测
CSRFTester是一款CSRF漏洞的测试工具。
CSRFTester工具的测试原理大概是这样的:使用代理抓取我们在浏览器中访问过的所有的连接以及所有的表单等信息,通过在CSRFTester中修改相应的表单等信息,重新提交,相当于一次伪造客户端请求,如果修测试的请求成功被网站服务器按受,则说明存在CSRF漏洞,当然此款工具也可以被用来进行CSRF攻击。