DVWA-1.9系列一共分为10个功能模块:
之前两篇文章分别是介绍了DVWA和第一个功能模块Brute Force(暴力破解)以及第二个功能模块Command Injection(命令行注入)。
这一篇我们继续介绍第三个功能模块:CSRF(跨站请求伪造)
CSRF(跨站请求伪造),全称Cross-site request forgery,翻译过来就是跨站请求伪造,是指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。CSRF与XSS最大的区别就在于,CSRF并没有盗取cookie而是直接利用。在2013年发布的新版OWASP Top 10中,CSRF排名第8。
该模块主要实现的是一个修改密码的操作,两次输入想要修改的密码点击提交修改密码。
首先我们把安全级别设置为Low级别。查看源代码:
Low
' . mysql_error() . '
' );
// Feedback for the user
echo "Password Changed."; } else { // Issue with passwords matching echo "
Passwords did not match."; } mysql_close(); } ?>
通过对源代码进行分析,我们可以看到源代码中只对两次输入的密码是否相同进行了判断,其他操作都没有进行防御,所以我们只需要用户在cookie还有效的时间内在相同的浏览器访问我们给定的url(该操作是服务器对请求的发送者进行了身份验证,检查cookie),就可以实现CSRF攻击,修改用户密码。
漏洞利用:
由于源代码中没有做过任何验证,所以我们只需要诱导用户点击http://192.168.197.136/dvwa/vulnerabilities/csrf/?password_new=111111&password_conf=111111&Change=Change#
该url即可实现密码修改。但是一定要注意,我们需要服务器验证cookie,所以我们必须让该url和DVWA系统打开的浏览器一致,这样才可以验证成功。
但是这个url的意图太明显了,很容易就能看出来这是修改密码的链接,所以怎样才能诱导用户点击这个url呢?
当用户访问这个页面时,会以为访问的页面丢失了,但是当他打开这个页面时,用户的密码已经被修改了。
首先我们把安全级别设置为Medium级别。查看源代码:
Medium
' . mysql_error() . '
' );
// Feedback for the user
echo "Password Changed."; } else { // Issue with passwords matching echo "
Passwords did not match."; } } else { // Didn't come from a trusted source echo "
That request didn't look correct."; } mysql_close(); } ?>
通过对源代码进行分析,我们可以知道Medium端主要的防御措施是通过if( eregi( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ] ) )
ersgi这个函数来检查 HTTP_REFERER(http包头的Referer参数的值,表示来源地址)中是否包含SERVER_NAME(http包头的Host参数,及要访问的主机名,这里是192.168.197.136),希望通过这种机制抵御CSRF攻击。
漏洞利用:
我们想要通过验证,就必须保证在http请求中Referer字段中必须包含Host,所以我们只需要把我们的文件名改成他的Host的name就可以完美的通过验证。
把安全级别设置为High级别。查看源代码:
High
' . mysql_error() . '
' );
// Feedback for the user
echo "Password Changed."; } else { // Issue with passwords matching echo "
Passwords did not match."; } mysql_close(); } // Generate Anti-CSRF token generateSessionToken(); ?>
通过源代码分析我们可以看到:该模块中加入了Anti-CSRF token来防范CSRF攻击,同时每次随机生成了一个token,当用户提交的时候,在服务器端比对一下token值是否正确,不正确就丢弃掉,正确就验证通过。
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
这个安全等级,自己主要是利用了DVWA的XSS漏洞和CSRF漏洞共同完成的:
把安全级别设置为Impossible级别。查看源代码:
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 = mysql_real_escape_string( $pass_new );
$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
echo "Password Changed.
";
}
else {
// Issue with passwords matching
echo "Passwords did not match or current password incorrect.
";
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
通过源代码分析我们可以看到:Impossiable端代码添加了一个输入原来密码的操作,这样我们一开始不知道密码的情况下是不可能修改密码的,所以有效的防御了CSRF攻击。