• PHP代码审计入门-DVWA靶场CSRF篇


    0x00  写在前面

    从零学习php,最终目的实现代码审计入门,软件采用sublime text,环境使用phpstudy搭建,数据库是navicat,需要有基本的前端基础、简单的php+mysql后端基础、渗透知识和漏洞原理,文章跟随流沙前辈学习记录,看看曾经遥不可及的代码审计能不能慢慢啃下来。

    本章为代码审计入门第七篇-DVWA靶场篇,对DVWA靶场漏洞进行代码审计。

    0x01 CSRF

    CSRF模块,注释写在代码里,尽量用详细的语言描述代码含义。

    level-low

    1. low.php
    2. if( isset( $_GET[ 'Change' ] ) ) {
    3. // Get input
    4. //设置并非空,GET型传参
    5. $pass_new = $_GET[ 'password_new' ];
    6. $pass_conf = $_GET[ 'password_conf' ];
    7. //接收用户输入
    8. // Do the passwords match?
    9. if( $pass_new == $pass_conf ) {
    10. // They do!
    11. //两次值相同
    12. $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)) ? "" : ""));
    13. $pass_new = md5( $pass_new );
    14. // 用mysqli_real_escape_string做一次简单过滤,给新密码进行一次加密
    15. // Update the database
    16. $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
    17. //更新数据库密码
    18. $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '
      ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
      '
      );
    19. // Feedback for the user
    20. $html .= "
      Password Changed.
      "
      ;
    21. }
    22. else {
    23. // Issue with passwords matching
    24. $html .= "
      Passwords did not match.
      "
      ;
    25. }
    26. ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    27. }
    28. ?>

    更新数据库代码部分有一个函数dvwaCurrentUser,跟进看代码逻辑。

    又发现一个 &dvwaSessionGrab,继续跟进

    然后产生疑惑, &dvwaSessionGrab函数为什么要加& ,百度一番没看懂,吐槽一下:他喵的就不能用朴实无华的语言写出来,非得装杯。。。。。

    好的,文章内容代码不是重点,重点是逻辑和漏洞。总结其方法的代码逻辑是判断用户是否登陆,如果用户已登陆把登陆的username返回来,然后修改其数据库对应的password。

    为什么会产生漏洞?因为什么限制也没做。

    level-medium

    相比于low增加一个验证功能,作用简单讲就是检验referer和host值能否匹配上,也就是判断该头的主机地址是否来自DVWA,是继续不是拜拜。

    1. medium.php
    2. if( isset( $_GET[ 'Change' ] ) ) {
    3. // Checks to see where the request came from
    4. if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
    5. // Get input
    6. //stripos函数检测[ 'SERVER_NAME' ]在[ 'HTTP_REFERER' ]出没出现,出现下一步没出现false
    7. $pass_new = $_GET[ 'password_new' ];
    8. $pass_conf = $_GET[ 'password_conf' ];
    9. // Do the passwords match?
    10. if( $pass_new == $pass_conf ) {
    11. // They do!
    12. $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)) ? "" : ""));
    13. $pass_new = md5( $pass_new );
    14. // Update the database
    15. $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
    16. $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '
      ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
      '
      );
    17. // Feedback for the user
    18. $html .= "
      Password Changed.
      "
      ;
    19. }
    20. else {
    21. // Issue with passwords matching
    22. $html .= "
      Passwords did not match.
      "
      ;
    23. }
    24. }
    25. else {
    26. // Didn't come from a trusted source
    27. $html .= "
      That request didn't look correct.
      "
      ;
    28. }
    29. ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    30. }
    31. ?>

    为什么有漏洞,因为burp抓包修改referer和host值就可以

    level-high

    相比于之前增加token认证,校验浏览器随机产生的token和用户提交修改密码时的token是否一致。其实感觉正常情况,基本有token机制就已经很难实现csrf了。

    1. high.php
    2. if( isset( $_GET[ 'Change' ] ) ) {
    3. // Check Anti-CSRF token
    4. checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    5. // token验证
    6. // Get input
    7. $pass_new = $_GET[ 'password_new' ];
    8. $pass_conf = $_GET[ 'password_conf' ];
    9. // Do the passwords match?
    10. if( $pass_new == $pass_conf ) {
    11. // They do!
    12. $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)) ? "" : ""));
    13. $pass_new = md5( $pass_new );
    14. // Update the database
    15. $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
    16. $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '
      ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
      '
      );
    17. // Feedback for the user
    18. $html .= "
      Password Changed.
      "
      ;
    19. }
    20. else {
    21. // Issue with passwords matching
    22. $html .= "
      Passwords did not match.
      "
      ;
    23. }
    24. ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    25. }
    26. // Generate Anti-CSRF token
    27. generateSessionToken();
    28. ?>

    但是这里结合XSS还是存在风险的

    漏洞组合拳之XSS+CSRF记录 - FreeBuf网络安全行业门户

    level-impossible

    既然是impossibale,那以咱水平肯定绕不过去,直接看代码。

    代码做了PDO防注入,对于防csrf来讲,最大的区别在于代码要求用户输入原密码,不知道原密码也就不能进行csrf攻击了。

    1. impossible.php
    2. if( isset( $_GET[ 'Change' ] ) ) {
    3. // Check Anti-CSRF token
    4. checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    5. // Get input
    6. $pass_curr = $_GET[ 'password_current' ];
    7. $pass_new = $_GET[ 'password_new' ];
    8. $pass_conf = $_GET[ 'password_conf' ];
    9. // Sanitise current password input
    10. $pass_curr = stripslashes( $pass_curr );
    11. $pass_curr = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    12. $pass_curr = md5( $pass_curr );
    13. // Check that the current password is correct
    14. $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
    15. $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
    16. $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
    17. $data->execute();
    18. // Do both new passwords match and does the current password match the user?
    19. if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {
    20. // It does!
    21. $pass_new = stripslashes( $pass_new );
    22. $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)) ? "" : ""));
    23. $pass_new = md5( $pass_new );
    24. // Update database with new password
    25. $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
    26. $data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
    27. $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
    28. $data->execute();
    29. // Feedback for the user
    30. $html .= "
      Password Changed.
      "
      ;
    31. }
    32. else {
    33. // Issue with passwords matching
    34. $html .= "
      Passwords did not match or current password incorrect.
      "
      ;
    35. }
    36. }
    37. // Generate Anti-CSRF token
    38. generateSessionToken();
    39. ?>

     

  • 相关阅读:
    mongodb的基本知识点
    策略模式和模板模式
    物联网组件
    【数据结构】手撕双向链表
    PP-YOLOE详解
    mysql-5:多表关系
    文件包含漏洞总结
    深度学习100例——卷积神经网络(CNN)实现服装图像分类
    如何获取一个会议的 transcripts
    国密sm2的Vue、Python、Java互通使用
  • 原文地址:https://blog.csdn.net/m0_60988110/article/details/127893389