CSRF
CSRF(跨站请求伪造)概述
Cross-site request forgery 简称为“CSRF”,在CSRF的攻击场景中攻击者会伪造一个请求(这个请求一般是一个链接),然后欺骗目标用户进行点击,用户一旦点击了这个请求,整个攻击就完成了。所以CSRF攻击也成为"one click"攻击。 很多人搞不清楚CSRF的概念,甚至有时候会将其和XSS混淆,更有甚者会将其和越权问题混为一谈,这都是对原理没搞清楚导致的。
这里列举一个场景解释一下,希望能够帮助你理解。
场景需求:
小黑想要修改大白在购物网站tianxiewww.xx.com上填写的会员地址。
先看下大白是如何修改自己的密码的:
登录—修改会员信息,提交请求—修改成功。
所以小黑想要修改大白的信息,他需要拥有:1,登录权限 2,修改个人信息的请求。
但是大白又不会把自己xxx网站的账号密码告诉小黑,那小黑怎么办?
于是他自己跑到www.xx.com上注册了一个自己的账号,然后修改了一下自己的个人信息(比如:E-mail地址),他发现修改的请求是:【http://www.xxx.com/edit.php?email=xiaohei@88.com&Change=Change】
于是,他实施了这样一个操作:把这个链接伪装一下,在小白登录xxx网站后,欺骗他进行点击,小白点击这个链接后,个人信息就被修改了,小黑就完成了攻击目的。
为啥小黑的操作能够实现呢。有如下几个关键点:
1.www.xxx.com这个网站在用户修改个人的信息时没有过多的校验,导致这个请求容易被伪造;
---因此,我们判断一个网站是否存在CSRF漏洞,其实就是判断其对关键信息(比如密码等敏感信息)的操作(增删改)是否容易被伪造。
2.小白点击了小黑发给的链接,并且这个时候小白刚好登录在购物网上;
---如果小白安全意识高,不点击不明链接,则攻击不会成功,又或者即使小白点击了链接,但小白此时并没有登录购物网站,也不会成功。
---因此,要成功实施一次CSRF攻击,需要“天时,地利,人和”的条件。
当然,如果小黑事先在xxx网的首页如果发现了一个XSS漏洞,则小黑可能会这样做: 欺骗小白访问埋伏了XSS脚本(盗取cookie的脚本)的页面,小白中招,小黑拿到小白的cookie,然后小黑顺利登录到小白的后台,小黑自己修改小白的相关信息。
---所以跟上面比一下,就可以看出CSRF与XSS的区别:CSRF是借用户的权限完成攻击,攻击者并没有拿到用户的权限,而XSS是直接盗取到了用户的权限,然后实施破坏。
因此,网站如果要防止CSRF攻击,则需要对敏感信息的操作实施对应的安全措施,防止这些操作出现被伪造的情况,从而导致CSRF。比如:
--对敏感信息的操作增加安全的token;
--对敏感信息的操作增加安全的验证码;
--对敏感信息的操作实施安全的逻辑流程,比如修改密码时,需要先校验旧密码等。
这样就可以分辨出来CSRF和XSS的区别,如果不懂就多看几遍。
以pikachu为靶场
以get方式提交的,我们可以直接在url里看到信息。
并且后台没有做任何的保护。
我们可以构造payload:csrf_get_edit.php?sex=girl&phonenum=12345678922&add=usa&email=lucy%40pikachu.com&submit=submit
在他还在这个页面的时候,将我们构造的恶意payload诱使其点一下,将其住址改为usa
成功了。
以post方式提交
在下面也是可以看到信息的。
下面我们构造一个类似的PHP文件
<html>
<body>
<form name="px" method="post" action="http://localhost/pikachu/vul/csrf/csrfpost/csrf_post_edit.php">
<input type="hidden" name="sex" value="girl">
<input type="hidden" name="phonenum" value="12345678922">
<input type="hidden" name="add" value="nab77">
<input type="hidden" name="email" value="lucy@pikachu.com">
<input type="submit" name="submit" value="submit">
</form>
<!-- <script>
document.px.submit();
</script> -->
</body>
</html>
构造我们的恶意链接:http://localhost/pikachu/vul/csrf/1.php
发现信息已经被修改了。
现在的url和HTML页面没有经过伪装,所以一眼就能看出来。
但是真正的实战伪装度极高。
源码:
if(isset($_POST['submit'])){
if($_POST['sex']!=null && $_POST['phonenum']!=null && $_POST['add']!=null && $_POST['email']!=null){
$getdata=escape($link, $_POST);
$query="update member set sex='{$getdata['sex']}',phonenum='{$getdata['phonenum']}',address='{$getdata['add']}',email='{$getdata['email']}' where username='{$_SESSION['csrf']['username']}'";
$result=execute($link, $query);
if(mysqli_affected_rows($link)==1 || mysqli_affected_rows($link)==0){
header("location:csrf_post.php");
}else {
$html1.='修改失败,请重试';
}
}
}
emmm,分析一下发现并没有token,没有refer。
CSRF(token)
加了token之后的提交方式
因为token是随机的,所以我们无法伪造url。
源码
$html='';
if(isset($_GET['submit'])){
if($_GET['username']!=null && $_GET['password']!=null){
//转义,防注入
$username=escape($link, $_GET['username']);
$password=escape($link, $_GET['password']);
$query="select * from member where username='$username' and pw=md5('$password')";
$result=execute($link, $query);
if(mysqli_num_rows($result)==1){
$data=mysqli_fetch_assoc($result);
$_SESSION['csrf']['username']=$username;
$_SESSION['csrf']['password']=sha1(md5($password));
header("location:token_get.php");
}else{
$html.="<p>登录失败,请重新登录</p>";
}
}
}
<div id="per_info">
<form method="get">
<h1 class="per_title">hello,{$name},欢迎来到个人会员中心 | <a style="color:bule;" href="token_get.php?logout=1">退出登录</a></h1>
<p class="per_name">姓名:{$name}</p>
<p class="per_sex">性别:<input type="text" name="sex" value="{$sex}"/></p>
<p class="per_phone">手机:<input class="phonenum" type="text" name="phonenum" value="{$phonenum}"/></p>
<p class="per_add">住址:<input class="add" type="text" name="add" value="{$add}"/></p>
<p class="per_email">邮箱:<input class="email" type="text" name="email" value="{$email}"/></p>
<input type="hidden" name="token" value="{$_SESSION['token']}" />
<input class="sub" type="submit" name="submit" value="submit"/>
</form>
</div>
修改信息时只有token正确才可以修改。
即修改信息时需验证$ _GET[‘token’]==$ _SESSION[‘token’]
如何防御?
1.关键操作只接受POST请求
2.验证码
csrf攻击往往是在用户不知情的情况下构造网络请求,在关键地方设置验证码,增加与用户的互动,可以在一定程度上防止csrf。
3.验证referer
HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。通过验证referer的值,设置referer必须来自同域的网址等,可以判断请求是合法还是不合法的。但是,由于浏览器和服务器的一些问题,这个方法也不是万无一失的,referer值用户可以设置成空,由于一些漏洞,referer值可以被篡改。Refere Check 一般用于监控CSRF攻击的发生,而不用来抵御攻击
4.token
可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token。token要足够随机,不可预测,每次请求成功要更新token,并且最好不要出现在URL中。
SSRF(Server-Side Request Forgery:服务器端请求伪造)
其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制
导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据
数据流:攻击者----->服务器---->目标地址
根据后台使用的函数的不同,对应的影响和利用方法又有不一样
SSRF漏洞的寻找(漏洞常见出没位置):
1)分享:通过URL地址分享网页内容
2)转码服务
3)在线翻译
4)图片加载与下载:通过URL地址加载或下载图片
5)图片、文章收藏功能
6)未公开的api实现以及其他调用URL的功能
7)从URL关键字中寻找
share
wap
url
link
src
source
target
u
3g
display
sourceURl
imageURL
domain
PHP中下面函数的使用不当会导致SSRF:
file_get_contents()
fsockopen()
curl_exec()
如果一定要通过后台服务器远程去对用户指定(“或者预埋在前端的请求”)的地址进行资源请求,则请做好目标地址的过滤。
同样以pikachu为靶场
看一下url:http://localhost/pikachu/vul/ssrf/ssrf_curl.php?url=http://127.0.0.1/pikachu/vul/ssrf/ssrf_info/info1.php
我们构造url:http://localhost/pikachu/vul/ssrf/ssrf_curl.php?url=http://baidu.com
直接跳转到了。
我们可以利用url探测服务器内网主机IP开放的端口等等操作。
SSRF(file_get_content )
file_get_content 可以对本地和远程的文件进行读取
该url:http://localhost/pikachu/vul/ssrf/ssrf_fgc.php?file=http://127.0.0.1/pikachu/vul/ssrf/ssrf_info/info2.php
使用文件读取。
怎么用呢?
以下为大师傅做的测试(我测试没成功),便于理解便引用过来。
http://127.0.0.1/pikachu-master/vul/ssrf/ssrf_fgc.php?file=http://10.2.7.24/ceshi.php
通过url的跳转,可以直接访问其他服务器里的文件。
这就很bug了。
还有读取phpinfo.php代码内容显示为base64的形式
http://127.0.0.1/pikachu-master/vul/ssrf/ssrf_fgc.php?file=php://filter/read=convert.base64-encode/resource=…/…/…/phpinfo.php
base64解密就能得到想要的信息。
这次就先记录吧,以后碰到实战会详解的。