0x01看到標題,是否有點疑惑 CPS 是什么東東。簡單介紹一下就是瀏覽器的安全策略,如果 標簽,或者是服務器中返回 HTTP 頭中有 Content-Security-Policy
標簽 ,瀏覽器會根據標簽里面的內容,判斷哪些資源可以加載或執行
廬山真面目 —— 何為CSP
為了研究CSP(Content Security Policy)對XSS攻擊的防護作用,他們做了對CSP安全模型的首次深入分析,分析了CSP標准中對web缺陷的保護能力,幫助識別常見的CSP策略配置的可能錯誤,並且展示了三類能使CSP無效化的繞過方法。
這次研究所采用的材料基於從Google搜索的索引文件中所提取到的CSP策略,從語料庫中提取了大約1060億頁的頁面,其中39億是受CSP保護的,其中確認了26,011個獨立的策略。他們發現,由於策略配置錯誤和白名單條目不安全,這些策略中至少有94.72%無法緩解XSS攻擊。基於這樣的研究結果,他們建議在實踐中部署CSP時,使用基於nonce的方法而不是傳統的白名單。並且,他們提出了名為“strict dynamic”的新特性,這是當前在Chromium瀏覽器中實現的CSP3規范的一個新特性。以下會詳細講述為何要使用這種策略和特性。
首先,何為CSP?我們知道,內容安全策略(CSP)是一種聲明機制,允許Web開發者在其應用程序上指定多個安全限制,由支持的用戶代理(瀏覽器)來負責強制執行。CSP旨在“作為開發人員可以使用的工具,以各種方式保護其應用程序,減輕內容注入漏洞的風險和減少它們的應用程序執行的特權”。當前,CSP還處在快速的發展期,目前正在進行規范中的版本是CSP3,CSP標准由用戶代理選擇實現。例如,Chromium具有完整的CSP2支持,並且實現了CSP3的大部分工作草案,僅在某些情況下可能會落后於實驗中的某些特性,而MozillaFirefox和基於WebKit的瀏覽器則剛剛獲得了完整的CSP2支持。在實際使用中,CSP策略在Content-Security-Policy HTTP響應頭或元素中提供。
0x02初級篇,如果不看源碼的話。看檢查器(F12),也可以知道一些被信任的網站。
首先我們來查看一下源碼
<?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>
觀察頭信息,羅列允許JavaScript的網站 當然你也可以從這里開發者工具來看到這個頭
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com example.com code.jquery.com ht
此時可以上pastebin網站上自己寫一個javascript代碼alert(“hahaha”),保存后記住鏈接,
https://pastebin.com/raw/zSLDySJn
然后在上面界面中輸入鏈接,結果如下
看到嘛,在pastebin上保存的js代碼被執行了。那就是因為pastebin網站是被信任的。攻擊者可以把惡意代碼保存在收信任的網站上,然后把鏈接發送給用戶點擊,實現注入。
0X03medium級別的
老規矩我們先看一下源碼
<?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=">alert('qisheng')</script>
不用解釋了吧,nonce是設定好的,允許運行。
0X04high級別的CSP
繼續看源碼
vulnerabilities/csp/source/high.php
<?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() { var s = document.createElement("script"); s.src = "source/jsonp.php?callback=solveSum"; 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(); }); }
script-src 'self';
, 看來只允許本界面加載的 javascript 執行. 然后研究了一下這個點擊顯示答案的邏輯(邏輯在
source/high.js
里), 大致如下: 點擊按鈕 -> js 生成一個 script 標簽(src 指向 source/jsonp.php?callback=solveNum), 並把它加入到 DOM 中 -> js 中定義了一個 solveNum 的函數 -> 因此 script 標簽會把遠程加載的
solveSum({"answer":"15"})
當作 js 代碼執行, 而這個形式正好就是調用了 solveSum 函數, 然后這個函數就會在界面適當的位置寫入答案.

<script>alert('hacked')</script>
來搞定的, 誰知道, 這種是屬於 'unsafe-inline' 形式的, 所以被限制執行了. 嗯... 既然如此的話, 那我就利用 src 吧.

<script src="source/jsonp.php?callback=alert('hacked');"></script>
, 並把這個當做 include 參數傳給界面就 注入成功!
0x05Impossible
該級別主要還是修復了 callback 參數可被控制問題(畢竟這是問題根源):
https://content-security-policy.com/ 學習鏈接