DVWA靶场通关实战
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开始攻击
也可以更改Options
的Number 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靶场通关实战相关推荐
- DVWA靶场通关笔记
文章目录 Brute Force 暴力破解 Low Medium High Impossible 防护总结: Command Injection 命令注入 危害: Low Medium High Im ...
- DVWA靶场通关教程
目录 Burt Force(爆破) (low) (medium) (high) (impossible) Command Injection(命令执行) (low) (medium) (high) ...
- DVWA靶场通关(SQL注入)
SQL Injection(SQL注入)概念 就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具体来说,它是利用现有应用程序,将(恶意 ...
- DVWA靶场通关-已完结
目录 1.Brute Force(暴力破解) Low Medium High Impossible 2.Command Injection(命令执行) Low Medium High Impassib ...
- dvwa靶场通关(二)
第二关:Command Injection(命令注入) 什么是命令注入: 命令注入就是在需要输入数据的地方输入了恶意代码,而且系统并没有对其进行过滤或者其他处理导致恶意代码也被执行,最终导致数据泄露或 ...
- dvwa靶场通关(一)
第一关:Brute force low 账号是admin,密码随便输入 用burp suite抓包 爆破得出密码为password 登录成功 Medium 中级跟low级别基本一致,分析源代码我们发现 ...
- dvwa靶场通关(五)
第五关 File Upload(文件上传漏洞) File Upload,即文件上传漏洞,通常是由于对上传文件的类型.内容没有进行严格的过滤.检查,使得攻击者可以通过上传木马获取服务器的webshell ...
- upload-labs靶场通关指南(16-17关)
今天继续给大家介绍渗透测试相关知识,本文主要内容是upload-labs靶场通关指南(16-17关). 免责声明: 本文所介绍的内容仅做学习交流使用,严禁利用文中技术进行非法行为,否则造成一切严重后果 ...
- 【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 方法一:诱导点击 ...
最新文章
- RocketMQ几种搭建模式说明
- 基于云的SD-WAN骨干接入服务
- Maven本地库在哪?
- android 之Dialog的多种Dialog对话框(以及反射在自定义对话框的运用)
- 局部变量和常量的性能分析
- 某少儿不宜网站图片拍摄位置分析,Python批量读取图片GPS位置!
- C语言求一个数的平方根倒数的近似值-一战封神的代码
- php如何获取li标签中的值,多个 (li) 标签如何获取获取选中的里面的某个特定值??...
- springboot问题记录
- Bat批处理脚本--常用命令
- iconfont图标
- PS 超简单抠头发丝
- 夜神模拟器——最好用的安卓模拟器
- react之redux全局状态管理
- Faster R-CNN文章详细解读
- 计算机的过去和现在作文英语怎么说,自己过去和现在英语作文带翻译
- android feature开关,Modem如何修改一个SBP feature的值
- js逆向JSVMP篇新版某乎_x-zes-96算法还原
- 小程序用vue开发可以吗,vue直接开发小程序
- java中无效字符串,在java中从字符串中删除无效的XML字符