CSRF

1、挖洞经验:

(1)黑盒:CSRF主要是用于越权操作,管理后台、会员中心、论坛帖子以及交易管理等,这几个场景里面,管理后台又是最高危的地方。我们在挖掘CSRF的时候可以先搭建好环境,打开几个有非静态操作的页面,抓包看看有没有token,如果没有token的话,再直接请求这个页面,不带referer。如果返回的数据还是一样的话,那说明很有可能有CSRF漏洞了。
(2)白盒:只要读代码的时候看看几个核心文件里面有没有验证token和referer相关的代码,这里的核心文件指的是被大量文件引用的基础文件,或者直接搜”token”这个关键字也能找,如果在核心文件没有,再去看看你比较关心的功能点的代码有没有验证。
可以看YzmCMS v5.7审计的那个CSRF漏洞,那个cms虽然做了CSRF处理,但可以绕过,用哪个场景更能理解,天目MVC v1.381中的CSRF如下面的场景一般,跟本没有检测referer和token。虽可以复现但做完也可能让人摸不着头脑。

2、搜索关键词

token,referer,common
前端

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>login</title>
  6. </head>
  7. <body>
  8. <form action="./login.php" method="post">
  9. 账号:<input type="text" name="username"><br >
  10. 密码:<input type="password" name="passwd"> <br >
  11. <input type="submit" value="提交" name="login">
  12. </form>
  13. </body>
  14. </html>

后端登录验证

  1. <?php
  2. header("content-type:text/html;charset=utf-8");
  3. if (!isset($_POST['login'])){
  4. echo '<script>';
  5. echo 'window.location.href="login.html"';
  6. echo '</script>';
  7. exit("非法访问");
  8. }else{
  9. $username = $_POST['username'];
  10. $passwd = $_POST['passwd'];
  11. $connect = mysql_connect("127.0.0.1","root","123456");
  12. mysql_select_db("admin",$connect);
  13. $sql = "SELECT * FROM user WHERE username = '$username' and passwd = '$passwd'";
  14. $result = mysql_query($sql);
  15. mysql_close();
  16. if($row = mysql_fetch_array($result)){
  17. session_start();
  18. $_SESSION['username'] = $row['username'];
  19. echo $_SESSION['username'].'欢迎登录';
  20. echo "<a href = 'reg.php'>添加用户</a>";
  21. }else{
  22. echo "fale!";
  23. }
  24. }

后端注册

<?php
session_start();
header("content-type:text/html;charset=utf-8");
if(!isset($_SESSION['username'])){
    echo '<script>';
    echo 'alert("请登入用户");window.location.href="login.php"';
    echo '</script>';
    exit();
}
if(!empty($_POST['submit'])){
    $username = addslashes($_POST['username']);
    $passwd = addslashes($_POST['passwd']);
    $connect = mysql_connect("127.0.0.1","root","123456");
    mysql_select_db("admin",$connect);
    $sql = "INSERT INTO user (username,passwd) VALUE ('$username','$passwd');";
    $result = mysql_query($sql) or die("执行命令失败".mysql_error());
    mysql_close();
    if($result){
        echo "regist success!";
    }else{
        echo "regist fail!";
    }

}else{
    echo "not POST!";
}
?>
<form action="reg.php" method="POST">
    username: <input type="text" name="username"><br>
    passwd: <input type="password" name="passwd"><br>
    <input type="submit" name="submit" value="提交">
</form>

3、修复方案

• 验证码
• 添加 Referer 验证
• 添加 Token 验证
• 修改密码之类的功能验证原密码
token验证

< ? php
session_start();
function set_token() {
$_SESSION['token'] = md5 (time ()+rand ( 1 , 1000 ));
}
function check_token () {
if (isset ($_POST['token'] ) &&$_POST['token'] === $_SESSION['token'])
{
return true ;
}
else{
return false;
}
}
if (isset ( $_SESSION['token'] ) &&check_token ()) {
echo "success" ;
}
else{
echo "failed";
}
set_token ();? >
<form method="post">
<input type="hidden" name="token" value="< ? =$_SESSION['token'] ? >">
<input type="submit"/>
</form>