DVWA

  • Brute Force(暴力破解)
    • Low
    • Medium
    • High
    • Impossible
  • Command Injection(命令行注入)
    • Low
    • Medium
    • High
    • Impossible
  • CSRF(跨站请求伪造)
    • Low
    • Medium
    • High
    • Impossible
  • File Inclusion(文件包含)
    • Low
    • Medium
    • High
    • Impossible
  • File Upload(文件上传)
    • Low
    • Medium
    • High
    • Impossible
  • Insecure CAPTCHA (不安全的验证码)
    • Low
    • Medium
    • High
    • Impossible
  • SQL Injection(SQL注入)
    • Low
    • Medium
    • High
    • Impossible
  • SQL Injection(Blind)(SQL盲注)
    • Low
    • Medium
    • High
    • Impossible
  • Weak Session IDs (弱会话ID)
    • Low
    • Medium
    • High
    • Impossible
  • XSS (DOM) (DOM型跨站脚本)
    • Low
    • Medium
    • High
    • Impossible
  • XSS(Reflected)(反射型跨站脚本)
    • Low
    • Medium
    • High
    • Impossible
  • XSS(Stored)(存储型跨站脚本)
    • Low
    • Medium
    • High
    • Impossible
  • CSP Bypass (CSP绕过)
    • Low
    • Medium
    • High
    • Impossible
  • JavaScript
    • Low
    • Medium
    • High
    • Impossible
  • 完结撒花

截至2022.11.24,DVWA共有十四个模块,分别是:

Brute Force(暴力破解)
Command Injection(命令行注入)
CSRF(跨站请求伪造)
File Inclusion(文件包含)
File Upload(文件上传)
Insecure CAPTCHA (不安全的验证码)
SQL Injection(SQL注入)
SQL Injection(Blind)(SQL盲注)
Weak Session IDs (弱会话ID)
XSS (DOM) (DOM型跨站脚本)
XSS(Reflected)(反射型跨站脚本)
XSS(Stored)(存储型跨站脚本)
CSP Bypass (CSP绕过)
JavaScript

按我的思路就是,Low、Media、High是拿来攻击的,Impossible是来教你防御的
然后就是缩减了一下目录,本来攻击方式、源码审计、漏洞原理都加了标题,但是那样目录就太长太丑了,想想还是删了算了
直接开冲!

Brute Force(暴力破解)

暴力破解,又叫撞库、穷举,使用大量的字典逐个在认证接口尝试登录,理论上,只要字典足够强大,破解总是会成功的。
阻止暴力破解的最有效方式是设置复杂度高的密码(英文字母大小写、数字、符号混合)。

而如果你的字典是从某网站泄露出来的,你使用它试图登陆其他网站,就便是撞库。撞库攻击的成功率高于暴力破解,因为你在A网站的用户名、密码通常和B网站的用户名、密码一致。

Low

DVWA Security界面将难度设置为Low

先看登录界面,填写账号密码后抓包

bp抓包后转到intruder模块,给username和password加上tag§
type选择Cluster bomb

对应位置插入字典后,点击右边的attack开始攻击

也可以更改OptionsNumber of threads修改进程数,增加爆破效率

根据响应包的大小以及响应体的内容判断是否成功,可以看到成功爆出一个用户admin/password,也是平台登录的默认账号

马上停止爆破,点到为止,一千四百万条顶不住啊。

源码审计

<?php
if( isset( $_GET[ 'Login' ] ) ) {// Get username$user = $_GET[ 'username' ];// Get password$pass = $_GET[ 'password' ];$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 successful$html .= "<p>Welcome to the password protected area {$user}</p>";$html .= "<img src=\"{$avatar}\" />";}else {// Login failed$html .= "<pre><br />Username and/or password incorrect.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}?>

username未过滤password只有一个md5加密,但是对实际的爆破过程毫无影响
首先很直观的就是一个万能密码(
由于限制了结果只能有一条,要加上limit 1
admin' or 1=1 limit 1#

Medium

爆破过程同上,但是可以明显感觉到,爆破的速度慢了很多
为了方便演示,直接把admin/password放在前几条了,反正多跑无益,还浪费时间

源码审计

<?phpif( 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 successful$html .= "<p>Welcome to the password protected area {$user}</p>";$html .= "<img src=\"{$avatar}\" />";}else {// Login failedsleep( 2 );$html .= "<pre><br />Username and/or password incorrect.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>

用了mysqli_real_escape_string()函数转义输入的用户名密码,但是没有设置编码,在gbk编码的数据库上可以进行sql注入
登录失败后sleep(2)延迟两秒

High

抓包发现url栏多了一项user_token
bp抓包后发现,只有在token正确的情况下才能尝试登录,其他情况均为302重定向

bp也是有带token爆破的功能的,首先转到intruder模块,选择Pitchfork模式

payload1是密码位,正常插入密码字典
payload2是token位,选择Recursive grep

然后去option里设置Grep-Extract

设置Start和End,将数据留在中间,也可以直接用鼠标在下方拖动选取文字
PS:设置grep时建议刷新一次浏览器,填入最新的token,避免访问失效,下面框里没东西
设置完成后回到payload界面选中

因为token不能复用,将option的线程设置为一,重定向选择always


开始爆破后即可根据响应包大小判断是否成功

源码审计

<?phpif( isset( $_GET[ 'Login' ] ) ) {// Check Anti-CSRF tokencheckToken( $_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 successful$html .= "<p>Welcome to the password protected area {$user}</p>";$html .= "<img src=\"{$avatar}\" />";}else {// Login failedsleep( rand( 0, 3 ) );$html .= "<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();?>

开始后先校验tokencheckToken(),若token不匹配则重定向到登陆界面,不再进行判断
结束前生成新的tokengenerateSessionToken()
账号密码多用了一个stripslashes()函数删除反斜杠

Impossible

失败三次,锁定15分钟,没辙了,摆烂了

源码审计

<?phpif( 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!//$html .= "<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 successful$html .= "<p>Welcome to the password protected area <em>{$user}</em></p>";$html .= "<img src=\"{$avatar}\" />";// Had the account been locked out since last login?if( $failed_login >= $total_failed_login ) {$html .= "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";$html .= "<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 feedback$html .= "<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();?>

代码行数直接比High多了一倍多,虽然注释挺多的
提交方式由GET改为POST
失败次数是写入数据库的,sql语句也改为参数化查询
不好说了,立体机动防御了

Command Injection(命令行注入)

命令注入,是指在某些需要输入数据的位置,构造恶意代码破环原有的语句结构,而系统缺少有效的过滤,许多内容管理cms存在命令注入漏洞。

Low

简洁的界面

象征性的ping一下,编码问题就不管了,影响不大
先来一个经典的ping
命令执行常用的方式为||&&管道符
更多的可以看看这个命令执行
还有一些过滤技巧CTF—命令执行总结
||当前项执行失败后执行后项
&&前项成功后执行后项
源码审计

<?phpif( isset( $_POST[ 'Submit' ]  ) ) {// Get input$target = $_REQUEST[ 'ip' ];// 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$html .= "<pre>{$cmd}</pre>";
}?>

没有过滤,简单判断一下操作系统就拼接执行了

Medium

再次尝试时发现&&被过滤了
||可以正常执行

源码审计

<?phpif( 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$html .= "<pre>{$cmd}</pre>";
}?>

还多过滤了一个分号,其他没啥了

High

过滤了&||,但是剩了个|还在
源码审计

<?phpif( isset( $_POST[ 'Submit' ]  ) ) {// Get input$target = trim($_REQUEST[ 'ip' ]);// Set blacklist$substitutions = array('&'  => '',';'  => '','| ' => '','-'  => '','$'  => '','('  => '',')'  => '','`'  => '','||' => '',);// Remove any of the characters 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$html .= "<pre>{$cmd}</pre>";
}?>

还真就剩了个|,不知道为什么过滤'| ' => '','||' => '',
l后面是空格说明仅仅过滤了l+空格 没过滤单独的l,他好温柔,我哭死

Impossible

打都不打,直接看源码
源码审计

<?phpif( isset( $_POST[ 'Submit' ]  ) ) {// Check Anti-CSRF 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 integerif( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {// If all 4 octets are int's put the IP back together.$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows$cmd = shell_exec( 'ping  ' . $target );}else {// *nix$cmd = shell_exec( 'ping  -c 4 ' . $target );}// Feedback for the end user$html .= "<pre>{$cmd}</pre>";}else {// Ops. Let the user name theres a mistake$html .= '<pre>ERROR: You have entered an invalid IP.</pre>';}
}// Generate Anti-CSRF token
generateSessionToken();?>

还是先checkToken()
然后$octet = explode( ".", $target );is_numeric()
硬性规定只能输入ip了

CSRF(跨站请求伪造)

一种可以被攻击者用来通过用户浏览器冒充用户身份向服务器发送伪造请求并被目标服务器成功执行的漏洞被称之为CSRF漏洞。
特点:

用户浏览器:表示的受信任的用户
冒充身份:恶意程序冒充受信任用户(浏览器)身份
伪造请求:借助于受信任用户浏览器发起的访问

由于CSRF攻击的特殊性,还是以钓鱼和源码解析为主好了

Low

源码审计

<?phpif( 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 user$html .= "<pre>Password Changed.</pre>";}else {// Issue with passwords matching$html .= "<pre>Passwords did not match.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}?>

没有安全防护措施,简单判断一下输入的新旧密码是否相同,然后修改当前用户的密码

渗透测试
先看一眼界面,下面是平平无奇的更改密码用的表格,上面是一个测试登陆用的弹窗,直接改密码!

可以看到是GET方法修改密码

点击Test,登录成功

此时就可以bp抓包生成CSRF Poc了

保存到本地文件然后将密码改为111111,点击发送

密码修改成功

Medium

源码审计

<?phpif( 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)) ? "" : ""));$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 user$html .= "<pre>Password Changed.</pre>";}else {// Issue with passwords matching$html .= "<pre>Passwords did not match.</pre>";}}else {// Didn't come from a trusted source$html .= "<pre>That request didn't look correct.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}?>

增加了$_SERVER[ 'HTTP_REFERER' ]头验证

渗透测试
题目的过滤方式为stripos(),可以利用命名文件夹的方式绕过Referer头的检测

High

源码审计

<?php
$change = false;
$request_type = "html";
$return_message = "Request Failed";if ($_SERVER['REQUEST_METHOD'] == "POST" && array_key_exists ("CONTENT_TYPE", $_SERVER) && $_SERVER['CONTENT_TYPE'] == "application/json") {$data = json_decode(file_get_contents('php://input'), true);$request_type = "json";if (array_key_exists("HTTP_USER_TOKEN", $_SERVER) &&array_key_exists("password_new", $data) &&array_key_exists("password_conf", $data) &&array_key_exists("Change", $data)) {$token = $_SERVER['HTTP_USER_TOKEN'];$pass_new = $data["password_new"];$pass_conf = $data["password_conf"];$change = true;}
} else {if (array_key_exists("user_token", $_REQUEST) &&array_key_exists("password_new", $_REQUEST) &&array_key_exists("password_conf", $_REQUEST) &&array_key_exists("Change", $_REQUEST)) {$token = $_REQUEST["user_token"];$pass_new = $_REQUEST["password_new"];$pass_conf = $_REQUEST["password_conf"];$change = true;}
}if ($change) {// Check Anti-CSRF tokencheckToken( $token, $_SESSION[ 'session_token' ], 'index.php' );// Do the passwords match?if( $pass_new == $pass_conf ) {// They do!$pass_new = mysqli_real_escape_string ($GLOBALS["___mysqli_ston"], $pass_new);$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 );// Feedback for the user$return_message = "Password Changed.";}else {// Issue with passwords matching$return_message = "Passwords did not match.";}mysqli_close($GLOBALS["___mysqli_ston"]);if ($request_type == "json") {generateSessionToken();header ("Content-Type: application/json");print json_encode (array("Message" =>$return_message));exit;} else {$html .= "<pre>" . $return_message . "</pre>";}
}// Generate Anti-CSRF token
generateSessionToken();?>

先验证token是否存在,再验证token值是否正确。要绕过High级别的反CSRF机制,关键是要获取用户当前token。

渗透测试
还是先抓个包
由于加了token,这里的token就要通过其他方法获取了,比如先弹一个xss什么的(

Impossible

标准答案来咯

<?phpif( 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 user$html .= "<pre>Password Changed.</pre>";}else {// Issue with passwords matching$html .= "<pre>Passwords did not match or current password incorrect.</pre>";}
}// Generate Anti-CSRF token
generateSessionToken();?>


旧密码+新密码+token+数据库参数化查询,强无敌!

File Inclusion(文件包含)

程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某个函数的时候,直接调用此文件,无需再次编写,这种调用文件的过程通常称为包含。
文件包含函数加载的参数没有经过过滤或严格定义,可以被用户控制,包含其他非预期文件,导致了文件信息泄露或执行非预期代码。

Low

点开界面是三个文件包含

点击后是三个文件包含,URL为?page=file3.php

甚至XSS

回到正题,有1、2、3那可以试试4

目录穿越,绝对路径,远程文件包含都是没问题的


源码审计
还真是,简洁明了啊

<?php// The page we wish to display
$file = $_GET[ 'page' ];?>

来者不拒,下一位!

Medium

先包含file4.php,没有问题
然后测试我们的phpinfo,可以发现目录穿越和远程包含失效了,准确的说../和http协议被替换为空了




源码审计

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

如图所示,润

High

file4依旧没问题

剩下的都是问题

不过可以用file协议绕过?page=file:///D:/phpstudy_pro/rua/DVWA-master/phpinfo.php

看下源码好了
代码审计

<?php// The page we wish to display
$file = $_GET[ 'page' ];// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {// This isn't the page we want!echo "ERROR: File not found!";exit;
}?>

匹配$file必须为file开头的字符串或include.php
因为只匹配了开头,那么file协议刚刚好满足此条件
linux系统就可以尝试去包含一些日志啊、/etc/shadow、/etc/passwd之类的了

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(文件上传)

File Upload,即文件上传漏洞,指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。通常是由于对上传文件的类型、内容没有进行严格的过滤、检查,使得攻击者可以通过上传木马获取服务器的webshell权限。

Low

没过滤,传个

DVWA靶场通关实战相关推荐

  1. DVWA靶场通关笔记

    文章目录 Brute Force 暴力破解 Low Medium High Impossible 防护总结: Command Injection 命令注入 危害: Low Medium High Im ...

  2. DVWA靶场通关教程

    目录 Burt Force(爆破) (low) (medium) ​(high) (impossible) Command Injection(命令执行) (low) (medium) (high) ...

  3. DVWA靶场通关(SQL注入)

    SQL Injection(SQL注入)概念 就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具体来说,它是利用现有应用程序,将(恶意 ...

  4. DVWA靶场通关-已完结

    目录 1.Brute Force(暴力破解) Low Medium High Impossible 2.Command Injection(命令执行) Low Medium High Impassib ...

  5. dvwa靶场通关(二)

    第二关:Command Injection(命令注入) 什么是命令注入: 命令注入就是在需要输入数据的地方输入了恶意代码,而且系统并没有对其进行过滤或者其他处理导致恶意代码也被执行,最终导致数据泄露或 ...

  6. dvwa靶场通关(一)

    第一关:Brute force low 账号是admin,密码随便输入 用burp suite抓包 爆破得出密码为password 登录成功 Medium 中级跟low级别基本一致,分析源代码我们发现 ...

  7. dvwa靶场通关(五)

    第五关 File Upload(文件上传漏洞) File Upload,即文件上传漏洞,通常是由于对上传文件的类型.内容没有进行严格的过滤.检查,使得攻击者可以通过上传木马获取服务器的webshell ...

  8. upload-labs靶场通关指南(16-17关)

    今天继续给大家介绍渗透测试相关知识,本文主要内容是upload-labs靶场通关指南(16-17关). 免责声明: 本文所介绍的内容仅做学习交流使用,严禁利用文中技术进行非法行为,否则造成一切严重后果 ...

  9. 【CSRF02】跨站请求伪造——DVWA靶场实操(含CSRF+XSS协同攻击实验)

    目录 1 实验简介 1.1 实验目的 1.2 实验环境 2 Low难度 2.1 前戏 2.2 实验步骤 2.3 代码审计 3 Medium难度 3.1 前戏 3.2 实验思路 3.3 方法一:诱导点击 ...

最新文章

  1. RocketMQ几种搭建模式说明
  2. 基于云的SD-WAN骨干接入服务
  3. Maven本地库在哪?
  4. android 之Dialog的多种Dialog对话框(以及反射在自定义对话框的运用)
  5. 局部变量和常量的性能分析
  6. 某少儿不宜网站图片拍摄位置分析,Python批量读取图片GPS位置!
  7. C语言求一个数的平方根倒数的近似值-一战封神的代码
  8. php如何获取li标签中的值,多个 (li) 标签如何获取获取选中的里面的某个特定值??...
  9. springboot问题记录
  10. Bat批处理脚本--常用命令
  11. iconfont图标
  12. PS 超简单抠头发丝
  13. 夜神模拟器——最好用的安卓模拟器
  14. react之redux全局状态管理
  15. Faster R-CNN文章详细解读
  16. 计算机的过去和现在作文英语怎么说,自己过去和现在英语作文带翻译
  17. android feature开关,Modem如何修改一个SBP feature的值
  18. js逆向JSVMP篇新版某乎_x-zes-96算法还原
  19. 小程序用vue开发可以吗,vue直接开发小程序
  20. java中无效字符串,在java中从字符串中删除无效的XML字符

热门文章

  1. 越过HG255D……
  2. charles设置:抓取小程序的请求包
  3. 亚马逊运营培训自动型广告如何做高排名
  4. VS2013/MFC 自绘控件获取系统CPU和物理内存使用率
  5. dmt、lmt、mssm,assm 总结
  6. Google浏览器搜索技巧(提高效率)
  7. crc32函数python,python求crc32值的方法
  8. 用C语言开发一个BT下载软件 (三) ------ 系统结构设计
  9. 项目开发一般流程、入职流程、尚学堂OA项目01_基础环境搭建、人事管理模块搭建、Servlet的高级封装
  10. python少年_python简单入门