DVWA 通關指南:CSP Bypass(CSP 繞過)


CSP Bypass(CSP 繞過)

Content Security Policy (CSP) is used to define where scripts and other resources can be loaded or executed from. This module will walk you through ways to bypass the policy based on common mistakes made by developers.
內容安全策略(CSP)用於定義腳本和其他資源可以從何處加載或執行,本模塊將指導您根據開發人員犯下的常見錯誤來繞過該策略。
None of the vulnerabilities are actual vulnerabilities in CSP, they are vulnerabilities in the way it has been implemented.
這些漏洞都不是 CSP 中的實際漏洞,它們都是實現 CSP 的方式中的漏洞。
Bypass Content Security Policy (CSP) and execute JavaScript in the page.
繞過內容安全策略(CSP),並在頁面中執行JavaScript。

內容安全策略

CSP 指的是內容安全策略,為了緩解很大一部分潛在的跨站腳本(XSS) 問題,瀏覽器的擴展程序系統引入了內容安全策略(CSP)的一般概念。通過引入一些相當嚴格的策略使擴展程序在默認情況下更加安全,開發者可以創建並強制應用一些規則,管理網站允許加載的內容。
CSP 以白名單的機制對網站加載或執行的資源起作用,在網頁中策略通過 HTTP 頭信息或者 meta 元素定義。CSP 雖然提供了強大的安全保護,但是它也令 eval() 及相關函數被禁用、內嵌的 JavaScript 代碼將不會執行、只能通過白名單來加載遠程腳本。如果要使用 CSP 技術保護自己的網站,開發者就不得不花費大量時間分離內嵌的 JavaScript 代碼和做一些調整。

Low Level

Examine the policy to find all the sources that can be used to host external script files.
檢查策略,以查找可用於承載外部腳本文件的所有源。

源碼審計

源碼如下,源碼定義了一個變量 headerCSP 放置了一些 url,使用 script src 指令指向一個外部 JavaScript 文件,header() 函數以原始形式將 HTTP 標頭發送到客戶端或瀏覽器.

<?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>
';

也就是說源碼對 HTTP 頭定義了 CSP 標簽,從而定義了可以接受外部 JavaScript 資源的白名單,通過抓包也可以知道是哪些網站。

攻擊方式

pastebin 是個快速分享文本內容的網站,假如文本的內容是一段 JavaScript 代碼,網頁就會把該代碼包含進來。

所以我們打開 pastebin 寫個 JavaScript 攻擊腳本,再將改文本的 url 注入進去實現攻擊

Medium Level

The CSP policy tries to use a nonce to prevent inline scripts from being added by attackers.
CSP 策略嘗試使用 nonce 來防止攻擊者添加內聯腳本。

源碼審計

源碼如下,HTTP 頭信息中的 script-src 的合法來源發生了變化。script-src 還可以設置一些特殊值,unsafe-inline 允許執行頁面內嵌的 <script> 標簽和事件監聽函數,nonce 值會在每次 HTTP 回應給出一個授權 token。

<?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>
';

攻擊方式

現在就不是從外界導入 JavaScript 資源了,而是直接通過內聯 JavaScript 代碼,注入時直接令 nonce 為設定好的值即可。

<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=" > alert'xss')</script>

High Level

The page makes a JSONP call to source/jsonp.php passing the name of the function to callback to, you need to modify the jsonp.php script to change the callback function.
頁面對 source 進行 JSONP 調用 /jsonp.php 文件傳遞要回調的函數名,需要修改 jsonp.php 文件更改回調函數的腳本。

源碼審計

服務器

源碼如下,雖然此時后端已經沒有設置白名單,但是還是會用 POST 方法傳入 include 參數。

<?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>
';

客戶端

源碼如下,在點擊網頁的按鈕使 js 生成一個 script 標簽,src 指向 source/jsonp.php?callback=solveNum。document 對象使我們可以從腳本中對 HTML 頁面中的所有元素進行訪問,createElement() 方法通過指定名稱創建一個元素,body 屬性提供對 < body > 元素的直接訪問,對於定義了框架集的文檔將引用最外層的 < frameset >。appendChild() 方法可向節點的子節點列表的末尾添加新的子節點,也就是網頁會把 “source/jsonp.php?callback=solveNum” 加入到 DOM 中。
源碼中定義了 solveNum 的函數,函數傳入參數 obj,如果字符串 “answer” 在 obj 中就會執行。getElementById() 方法可返回對擁有指定 ID 的第一個對象的引用,innerHTML 屬性設置或返回表格行的開始和結束標簽之間的 HTML。這里的 script 標簽會把遠程加載的 solveSum({"answer":"15"}) 當作 js 代碼執行, 然后這個函數就會在頁面顯示答案。

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();
    });
}

攻擊方式

注意到需要向 “source/jsonp.php” 傳入 “callback” 參數,這個參數並沒有進行任何過濾,因此我們可以通過這個參數進行注入。

include=<script src="source/jsonp.php?callback=alert('xss');"></script>

Impossible Level

This level is an update of the high level where the JSONP call has its callback function hardcoded and the CSP policy is locked down to only allow external scripts.
這個級別是 high 級別的加強,JSONP 調用的回調函數是硬編碼的,CSP 策略被鎖定為只允許外部腳本。

服務器

<?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>
';

客戶端

 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();
    });
}

參考資料

Content Security Policy 入門教程
DVWA--CSP Bypass


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM