網絡安全編程:DVWA實例
本文對DVWA進行簡單的演示,在這里將安全級別選擇為“low”(低),且沒有開啟PHPIDS。
1. Brute Force模塊練習
Brute Force 是暴力破解的意思,是指黑客利用窮舉工具并配合合理的密碼字典,來猜解用戶的密碼。這里主要介紹Burp Suite工具,與DVWA的Brute Force模塊。在DVWA中打開Brute Force模塊,如圖1所示。

圖1 Brute Force模塊
在圖1中可以看到有兩個用來接受“Username”和“Password”的輸入控件,還有一個“Login”按鈕。該模塊是用來測試暴力破解的,那么如何才能夠進行暴力破解呢?難道一個滲透平臺也需要自行編程來完成任務嗎?那樣對于沒有編程基礎的Web安全初學者就要求太高了,而且在很多實際的情況下,通常是使用現有的工具來進行檢測。這里選用一款Web安全檢測及攻擊的套件來完成暴力破解的任務,該檢測套件就是著名的Burp Suite。
Burp Suite是一款集合了Web安全檢測及攻擊的套件,它像是一款瑞士軍刀一樣,每一項功能都可以獨立完成特定的功能,而且各個功能還能配合進行使用,從而發揮更強大的作用。Burp Suite界面如圖2所示。

圖2 Burp Suite界面
下面直接演示如何使用Burp Suite來測試DVWA中Brute Force的模塊。
在Burp中選擇“Proxy”頁簽,即代理頁簽,在該頁簽下選擇“Options”子頁簽,來設置一個監聽的IP地址和端口號。Burp的代理功能是專門用于攔截HTTP和HTTPS數據用的,它存在于瀏覽器和目標應用之間,它可以將攔截到的HTTP/HTTPS數據進行修改后再次發送,它是整個Burp套件的核心部分。在設置好代理地址之后,切換到“Proxy”頁簽下的“Intercept”子頁簽,并將“Intercept is on”按鈕激活,即啟動代理攔截功能,開始攔截HTTP/HTTPS的數據。雖然Burp的代理攔截功能設置好了,但是工作只是完成了一半,剩下一半需要設置瀏覽器的代理,通過設置瀏覽器的代理地址為Burp監聽的地址和端口從而將請求的HTTP/HTTPS數據發送給了Burp,這樣Burp就相當于在Web應用與瀏覽器之間了。如圖3所示。

圖3 Burp設置
準備工作已經完成了,接下來在DVWA的Brute Force模塊的“Username”框和“Password”框輸入賬號“admin”和任意一個密碼,單擊“Login”來進行登錄。這時Burp就會攔截住瀏覽器提交的HTTP請求,如圖4所示。

圖4 Burp攔截的HTTP請求
在HTTP的數據上單擊右鍵,在彈出的菜單上選擇“Send to Intruder”,然后切換到“Intruder”頁簽下的“Positions”子頁簽中,如圖5所示。注意觀察其中的數據,有很多值都在兩個“$”符號之間,需要將這些“$”符號清除,單擊“Clear$”即可將所有的“$”清除,然后選中第一行中間的“password=12345”的“12345”,這是剛才在“Password”框中輸入的密碼,選中它以后單擊“Add$”按鈕,將選中的“12345”變成“$12345$”,這樣密碼部分就成為了“變量”,在進行暴力破解的時候,字典會不斷地對它進行替換。

圖5 Burp的Intruder頁簽
接著選擇“Positions”子頁簽右側的“Payloads”子頁簽,如圖6所示。

圖6 Intruder頁簽下的Payloads子頁簽
單擊圖6中的“Add from list”下拉框,在下拉框中選擇“Passwords”,然后在下拉框上面的列表中會出現很多常用的密碼,然后在該子頁簽的右上角單擊“Start attack”按鈕進行暴力破解。這時會在“Intruder attack”窗口中使用密碼字典來逐個替換剛才的“變量”來嘗試暴力破解,但是從列表中沒有給出破解成功的提示,怎么能夠知道哪條才是真正破解成功的密碼呢?其實這就體現出了Burp的強大了,因為它是一個通用的工具,在保證通用的前提下,失去一些具體的提示并不為過,那么如何判斷哪個是暴力破解成功的記錄呢?其實很簡單,只要看一下“Length”列即可。因為破解成功返回的數據的長度肯定和其他數據的長度不一致,這樣就可以判斷出哪條是破解成功的密碼了,如圖7所示。

圖7 Intruder attack列表
為了能夠快速地找到密碼,可以通過單擊“Length”列來進行排序,從圖7中可以看出,爆破成功的密碼是第2590行的記錄,密碼是“password”。
通過上面的測試得出“admin”用戶的密碼是“password”,可以通過輸入這組賬號和密碼進行測試,再輸入錯誤的賬號和密碼進行測試就會發現,返回的結果是不相同的,這就說明可以通過判斷返回包的長度來判斷眾多測試中哪條才是正確的。
在圖7的最上面一條記錄,即測試成功的記錄上單擊右鍵,在彈出的菜單中選擇“Generate CSRF PoC”會打開一個新的窗口,在窗口的下半部分會有一段HTML代碼,代碼如下:
將該段代碼保存成擴展名為“html”的文件,然后直接雙擊即可顯示出登錄成功后的提示。
2. File Upload模塊
文件上傳是很多網站都有的,比如社交網站的上傳頭像,上傳照片,比如資源網站可以上傳一個共享軟件,上傳壓縮包等。那么在這種情況下,如果網站對于上傳過濾不嚴格的話,就可以上傳木馬或惡意程序,這對于服務器危害是非常大的。這里仍然用Burp Suite來演示DVWA中的File Upload模塊(設置為Medium級別,因為Low級別可以直接上傳)是如何被上傳一個木馬的。
單擊“File Upload”打開上傳模塊的部分,看到一個可以選擇上傳文件的文件框和上傳文件的提交按鈕,選擇一個正常的圖片文件上傳,會提示上傳成功,并返回一個上傳的地址,地址為“../../hackable/uploads/test.jpg”,用該返回的地址直接貼到當前URL后面就會打開圖片,打開后的URL地址為“http://localhost/dvwa/hackable/uploads/test.jpg”。然后選擇一個PHP的木馬文件上傳,會提示不是JPEG或PNG的文件,如圖8所示。

圖8 cmd.php上傳失敗
打開Burp啟動攔截,然后設置瀏覽器的代理,然后再次上傳PHP木馬查看Burp中截取到的HTTP數據,如圖9所示。

圖9 Burp對木馬上傳的抓包
在圖9中的“Content-Type”中可以看出,這里提交的類型并不是圖片的類型。那么將如何修改呢?將本地木馬的擴展名修改為“png”或“jpg”的格式,然后再次提交,如圖10所示。

圖10 Burp對修改擴展名的木馬上傳抓包
從圖10中可以看到“Content-Type”的類型已經改變了,但是注意在“filename”處文件名是“cmd.jpg”,這樣上傳后文件就是一個jpg的文件,那么在這里修改jpg的擴展名為php,然后單擊“Forward”讓Burp將數據包提交到Web服務器。返回DVWA中可以看到cmd.php的木馬文件已經上傳成功了,打開地址“http://localhost/dvwa/hackable/uploads/cmd.php”,可以正常打開上傳的木馬文件。
之前寫過一個通過發包來進行暴力破解的程序,在程序中每次發包時會修正包的長度,而Burp Suite會自動修正包的長度,這一個小的功能就非常“貼心”。從第二個實例中可以體會到Burp Suite存在于瀏覽器和服務器的中間,可以對瀏覽器提交的數據包進行截取、修改、發送,因此善于利用Burp Suite的這個功能可以很好地繞過很多Web前端頁面的數據校驗,也可以通過修改數據包達到欺騙后臺的效果,類似于上面的例子,提交的類型是圖片類型,但是實際上卻是一個PHP的文件。
3. SQL Injection模塊
SQL Injection是用來練習SQL注入攻擊的模塊,SQL注入也是常見的Web攻擊方式。SQL是結構化查詢語言,是一種針對數據庫設計的查詢語言,可以完成對數據庫的增、刪、改、查等操作,最主要的還是進行各種各樣的查詢,而且可以通過簡單的語句構造出來復雜的查詢。SQL注入就是通過構造SQL語句從而進行攻擊的一種技術。
在使用SQL Injection模塊進行練習之前,簡單描述什么是SQL注入。在可以交互的Web系統中,通常都會有用來進行輸入的輸入框,比如輸入用戶名和密碼的輸入框,填寫注冊信息的輸入框等都可以向Web系統提交信息。在正常情況下用戶會按照提示進行相應的輸入,但是不懷好意的人會有意地輸入其他有特殊意義的符號,由于特殊符號的作用,就會導致意想不到的情況(不懷好意的人不一定是攻擊者,比如注冊的時候隨便填寫可能導致Web頁面不正常顯示之類,現在這樣的系統比以前大大減少,但并不是說已經不存在了)。對于惡意攻擊者而言,則會有意地使用SQL語法的關鍵字或符號來構造一些輸入,使得構造的輸入在數據庫中被執行,從而獲得更有價值的信息。
經過上面簡單的介紹,大家可能對SQL注入已經有個簡單的了解了,現在來看一下DVWA系統中的SQL Injection模塊(級別為Low),如圖11所示。

圖11 DVWA的SQL Injection模塊
圖11中有一個輸入框,從該輸入框中就要完成SQL注入的聯系。隨便輸入一個“1”(實際輸入沒有引號),會返回ID為1的“First name”和“Surname”,接著輸入一個“2”,同樣會返回ID為2的“First name”和“Surname”。那么再輸入一個“a”,就什么都沒有返回。輸入“1”和“2”有返回結果,而輸入“a”沒有返回結果,那是因為數據庫中并沒有ID為“a”的記錄,而數據庫中存在ID為“1”和“2”的記錄,那這能說明什么問題呢?說明有沒有該ID對應的數據,是需要在數據庫中進行查詢的,那么是怎么查詢的呢?可能是這樣的兩種查詢語句,第一種查詢語句如下:
Select firstname, surname from 表名 where id = '1'
第二種查詢語句如下:
Select firstname, surname from 表名 where id = 1
這兩種語句的寫法如果對于沒有SQL語言基礎的朋友又不仔細看的情況下可能沒有看出差別,第一句和第二句的差別在于第一句的1是被單引號引住的,第二句則直接是1。它們的差別是第一句查的ID是一個字符串類型的,第二句查的ID是一個數值型的。至于是數值型還是字符串型的,對注入攻擊有什么差別呢?是有的。因為那個ID的值是輸入的,那里是一個變量,實際寫程序時可能是進行拼接的,看一下上面的字符串是如何拼接的。
第一種拼接方法:
$sql = "select firstname, surname from 表名 where id = '" . $id . "'";
第二種拼接方法:
$sql = "select firstname, surname from 表名 where id = " . $id;
可以看到,在第一種使用字符串拼接的時候,$id的前后會有引號的存在,而在第二種字符串拼接的時候,$id的前后是沒有使用引號的。
在各種語言中都有邏輯運算符,當然在SQL語句中也有,SQL中的“與”用and表示,或用or表示。如果一條邏輯語句是“××× and 1=1”這樣寫的,是不會影響×××原來邏輯的,因為1=1是永遠為真的。來構造一下輸入的內容,這里輸入“1' and '1' = '1”,如圖12所示。

圖12 構造的AND語句
點提交以后仍然會看到ID為1的信息,那么上面的輸入是如何拼接成SQL語句的呢?大體如下:
$id = "1 and '1'='1"; $sql = "select firstname, surname from 表名 where id = '" . $id . "'";
那么拼接后的語句如下:
select firstname, surname from 表名 where id = '1' and '1'='1';
現在知道and '1'='1'是不改變前面的邏輯值的,也就是對id='1'是否存在是不改變的,也就是id='1'是真,id='1' and '1'='1'就是真,如果id='1'是假,那么id='1' and '1'='1'還是假。在輸入時,第一個1后面有一個單引號,是用來和代碼中的SQL語句中的單引號進行閉合的,而最后一個1的前面有一個單引號,它是用來和SQL語句中的單引號進行配對的。因為在代碼中本身就存在單引號的。如果在代碼中用的不是字符串,而輸入框中構造的有單引號,則會拋出異常。因此,猜測的兩種方法這里使用的是第一種。
那么如何讓這個語句永真呢,還是利用該等式'1'='1',只是邏輯連接符由and改為or。
那么再次在輸入框中提交“1' or '1'='1”,提交后如圖13所示。

圖13 構造的or語句
從圖13中可以看出,由于提交的內容是“1' or '1'='1”,那么構造的SQL語句就成為了如下語句:
Select firstname, surname from 表名 where id = '1' or '1' = '1'
由于查詢條件永真,那么將會把所有的記錄都列出來。那么該語句還適合于在前面的“Brute Forece”模塊中進行測試,在輸入用戶名的地方輸入“admin' or '1'='1”,在輸入密碼的地方也輸入“admin' or '1'='1”,同樣可以得到與輸入正確密碼的一樣的效果。
SQL注入是非常靈活的,下面再隨便輸入幾個測試的語句,如“1' union select user(), '1”和“1' union select database(), '1”,可以顯示出系統登錄數據庫的用戶名和當前系統所使用的庫名,如圖14和圖15所示。

圖14 系統登錄數據的用戶為root

圖15 系統所使用的庫名為dvwa
SQL注入的靈活是因為SQL語句本身的靈活,要想更好地掌握SQL注入那么就一定要先掌握SQL語言的使用。
本文演示了DVWA系統的3個模塊,分別是Brute Force、File Upload和SQL Injection。Web系統的漏洞基本也是因為對用戶提交的數據過濾不嚴格而造成的,一切用戶的輸入都應該視為不安全的,因此安全編碼就是從開發人員層面來杜絕系統產生漏洞,在系統上線之前還會有代碼審計、Web漏洞掃描等上線前的安全檢查,針對Web安全防護的系統有ADS、WAF、網頁防篡改等。當然了,最關鍵的還是從編碼時就考慮安全的問題,從源頭杜絕系統產生漏洞。