一、DVWA介绍
DVWA(Damn Vulnerable Web Application)是randomstorm的一个开源项目。一个
用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自己的专业技能和工具提供合法的环境,帮助web开发者更好的理解web应用安全防范的过程。
DVWA共有十个模块,分别是:
1.Brute Force(密码破解)
2.Command Injection(命令行注入)
3.CSRF(跨站请求伪造)
4.File Inclusion(文件包含)
5.File Upload(文件上传)
6.Insecure CAPTCHA (不安全的验证码)
7.SQL Injection(SQL注入)
8.SQL Injection(Blind)(SQL盲注)
9.XSS(Reflected)(反射型跨站脚本)
10.XSS(Stored)(存储型跨站脚本)
CSRF:
1.漏洞原理:
CSRF(Cross-site request forgery),中文名叫做“跨站请求伪造”,也被称作“one click attack/session riding”,缩写为“CSRF/XSRF”。在场景中,攻击者会伪造一个请求(通常是一个链接),然后欺骗目标用户点击,一但用户点击,攻击也就完成了。
同“XSS”的区别在于,CSRF是借助用户权限完成攻击,攻击者并没有拿到权限;而XSS是直接盗取用户甚至管理员的权限进行攻击,从而造成破坏。
CSRF攻击可以利用用户已经登录或已经授权的状态,伪造合法用户发出请求给受信的网点,从而实现在未授权的情况下执行一些特权操作。
2.漏洞分类:
(1)GET型:
GET型是CSRF攻击最常发生的情形。只要一个http请求就可以了。
本质上,这样的逻辑代码设计本身就不合理,HTTP协议设计的初衷中,GET型请求就需要保证“幂等性”,即无论发出了多少次GET请求,和仅发出一次请求所产生的效果应该是相同的。这就保证了GET型操作仅能进行类似“查询”和“获取资源”资源这样的操作。
(2)POST型:
POST请求是要把参数放在http的请求body里发送给服务器,所以POST类型的CSRF攻击仅需要用POST的方式发送请求。通常的方法就是创建(静态创建或动态创建)一个自动提交的表单。当用户点击或浏览有这样的表单的网页就会自动发生攻击。
3.漏洞危害:
修改用户信息,如用户的头像、发货地址等。更有甚者,可能执行恶意操作,比如修 改密码、添加/删除好友或者点赞/转发/评论/私信。
4.检测和防护:
检测
(1)手动检测
应首先确定Web应用程序对哪些操作是敏感的,在确认敏感操作后,拦截相应的HTTP请求消息,分析是否存在CSRF漏洞。
(2)半自动检测
常用工具有OWASP的CSRFTester、BurpSuite的Scanner功能。
防护
●增加二次验证机制
在敏感操作时候,不再直接通过某个请求执行,而是再次验证用户口令或者再次验证类似验证码等随机数。如:转账时,要求用户二次输入密码。
●校验HTTP Referer字段
校验HTTP Referer字段可以保证相关敏感操作来自授权站点的跳转。在HTTP协议中,定义了一个访问来源的字段,即HTTP_REFERER。站点可以在后端校验Referer是否来自于正常的站内跳转。如果攻击者诱导用户点击跳转链接,则Referer就为攻击者的主机,与网站内部内部跳转情况下的Referer字段不同。
●增加Token参数进行校验
在敏感操作的参数中,增加完全随机的Token参数进行校验。这是目前业内防止CSRF攻击最常用的方法。因为CSRF产生的根本原因是,进行敏感操作时用户每次发送的请求都完全相同。因此,攻击者就可以把这样的请求进行封装包裹,诱导用户点击链接并发出请求。而如果在进行敏感操作时,增加完全随机的Token参数,每次进行敏感操作时发送的请求都不完全相同,攻击者也就没有办法伪造出一个合法的敏感操作请求,也就无法实施CSRF攻击。
5.实战:
(1)Low:
代码分析:<?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"])