CSRF漏洞

CSRF漏洞

/温馨提示,学习漏洞最重要的是学会如何防护,而不是仅仅停留于攻击/

什么是csrf

CSRF,全称Cross-site request forgery,是指跨站请求伪造,通常缩写为CSRF或者是XSRF。这个漏洞的实现就是通过伪装利用受信任用户的访问权限,来进行篡改,盗取用户数据,并且可以利用被攻击用户的账号进行蠕虫的传播等危险操作。虽然他和xss跨站脚本攻击听起来很像,但他和xss非常不同,xss是,想办法去窃取用户Cookie,如果用户Cookie被窃取,攻击者可以不通过密码,而直接登录用户账户,然后csrf是想办法利用用户的cookie进行攻击。----网上有一句话说,如果把xss比作一头在外狩猎猛虎,那么csrf就是一条隐藏起来的蛇,让人防不胜防。

csrf成因

CSRF漏洞的成因就是网站的cookie在浏览器中不会过期,只要不关闭浏览器或者退出登录,那以后只要是访问这个都网站,会默认你已经登录的状态。而在这个期间,攻击者发送了构造好的CSRF脚本或包含CSRF脚本的链接,可能会执行一些用户不想做的功能(比如是添加账号、ajax异步传输【通过JS去发送请求,然后获取信息】。与钓鱼网站不同,钓鱼网站需要输入账号和密码,而CSRF只需要访问链接或者网页即可。

 

csrf原理

图解过程以及漏洞利用的点

 

 

1.用户使用浏览器正常访问了网站A,并且成功输入账号密码进行登录;

2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;

3.用户在未关闭网站A,直接浏览器中访问网站B

4.网站B页面中存在一些攻击性的代码,返回给用户C,并发送一个请求访问网站A

5.浏览器接收到请求之后,根据攻击网站B的请求,在用户不知情的情况下,携带未过期的cookie值直接访问网站A。但是网站A并不知情是用户还是网站B的请求,所以会根据用户C的cookie权限执行这个请求,最后导致网站B中的恶意代码被执行。

分析:在整个攻击过程中,需要满足三点才能造成csrf攻击的实现

1.用户登录了网站A并且产生了本地cookie

2.在用户没有退出站点 A 的情况下(也就是 cookie 生效的情况下),访问了恶意网站B(B)

3.网站A做的防护不能够抵御攻击者的请求

 

csrf的利用

 

这里就写一些自己在学习过程中的学习的方法,,简单的直接省略,,挑中点的写

csrf分类

  1. get型

    假设以为vince用户的需要修改个人信息,我们用bp拦截看一下请求

     

     

    构造恶意代码,直接进行攻击

<html>
   <a href="http://127.0.0.1/pikachu-master/vul/csrf/csrfget/csrf_get_edit.php?sex=1111111111111&phonenum=333333&add=chain&email=vince%40pikachu.com&submit=submit"></a>
</html>
  1. POST型

post请求和get请求不同的是,我们需要攻击者自己写一个利用漏洞的html的代码,并发给用户请求这个html文件的链接。

比如针对这一关,将包含如下html代码的文件(假设文件名为jiaoben.html)放入攻击者的电脑,比如192.168.1.11;

然后在攻击者电脑上起http服务,比如python3 -m http.server 80

再将链接http://192.168.1.11/pikachu-master/vul/scrf/jiaoben.html发送给登录状态的用户

用户点击链接之后,就可以修改信息(用户点击连接后就会执行攻击者事先准备好的恶意代码)

 

<html>
<head>
<script>
window.onload = function() {
 document.getElementById("postsubmit").click();
}
</script>
</head>
<body>
<form method="post" action="http://127.0.0.1/pikachu-master/vul/csrf/csrfpost/csrf_post_edit.php">
   <input id="sex" type="text" name="sex" value="girl" />
   <input id="phonenum" type="text" name="phonenum" value="12345678922" />
   <input id="add" type="text" name="add" value="hacker" />
   <input id="email" type="text" name="email" value="lucy@pikachu.com" />
   <input id="postsubmit" type="submit" name="submit" value="submit" />
</form>
</body>
</html>

 

csrf后台源码分析学习

$link=connect();
// 判断是否登录,没有登录不能访问
if(!check_csrf_login($link)){
//   echo "<script>alert('登录后才能进入会员中心哦')</script>";
   header("location:csrf_post_login.php");
}

代码段会检查用户是否登录,如果用户没有登录的前提下就进行攻击,那就会返回登录界面.

 

 

<?php
/*
修改用户信息的代码
*/
if(isset($_GET['submit'])){
   if($_GET['sex']!=null && $_GET['phonenum']!=null && $_GET['add']!=null && $_GET['email']!=null && $_GET['token']==$_SESSION['token']){ //这里对token进行验证
       //转义
       $getdata=escape($link, $_GET);
       
       $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:token_get.php");
      }else {
           $html1.="<p>修改失败,请重新登录</p>";

      }
  }
}
//生成token
set_token();

?>

看一下代码,修改用户信息时,服务器会比较url中的token字段和session中的token字段,如果相同才能修改用户信息

mysqli_affected_rows() 函数返回前一次 MySQL 操作(SELECT、INSERT、UPDATE、REPLACE、DELETE)所影响的记录行数。

 

//生成一个随机的token值
function set_token(){
   if(isset($_SESSION['token'])){
   unset($_SEESSION['token']);} // 销毁一个seession变量
   
   $_SESSION['token']=str_replace('.','',uniqid(mt_rand(10000,9999),true));
}

 

set_token()函数对在生成新的token之前会销毁先前token

uniqid(prefix,more_entropy)函数基于以微秒计的当前时间,生成一个唯一的 ID。 当prefix为空则返回的字符串有 13 个字符串长。如果 more_entropy 参数设置为 true,则是 23 个字符串长。

 

csrf的防护

根据csrf的利用,我们知道csrf 的防护可以从浏览器、服务器端进行改进。

 

1、验证HTTP Referer字段; 根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。

这种方法的显而易见的好处就是简单易行,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。

方法的弊端

然而,这种方法并非万无一失。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 网站支持IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。 即便是使用最新的浏览器,黑客无法篡改 Referer 值,这种方法仍然有问题。因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。

 

2.在请求地址中添加 token 并验证

CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。 ​ 这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来说,要在 form 的最后加上 <input type="hidden" name="csrftoken" value="tokenvalue"/>,这样就把 token 以参数的形式加入请求了。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。

方法弊端:

该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。

3.在 HTTP 头中自定义属性并验证

4.输旧密码,我们修改密码有时候需要输入旧密码,这种情况下打不出CSRF漏洞。

5.如果存在xss漏洞,token防御将无效

posted @ 2022-10-14 21:36  柳~  阅读(68)  评论(0编辑  收藏  举报