最新消息:图 床

前端防禦從入門到棄坑–CSP變遷

COOL IAM 308浏览 0评论

作者:LoRexxar’@知道創宇404實驗室
英文版本:https://paper.seebug.org/939/

0x01 前端防禦的開始

對於一個基本的XSS漏洞頁面,它發生的原因往往是從用戶輸入的數據到輸出沒有有效的過濾,就比如下面的這個範例代碼。

<?php
$a = $_GET['a'];
echo $a;

對於這樣毫無過濾的頁面,我們可以使用各種方式來構造一個xss漏洞利用。

a=<script>alert(1)</script>
a=<img/src=1/onerror=alert(1)>
a=<svg/onload=alert(1)>

對於這樣的漏洞點來說,我們通常會使用htmlspecialchars函數來過濾輸入,這個函數會處理5種符號。

& (AND) => &amp;
" (雙引號) => &quot; (當ENT_NOQUOTES沒有設置的時候) 
' (單引號) => &#039; (當ENT_QUOTES設置) 
< (小於號) => &lt; 
> (大於號) => &gt; 

一般意義來說,對於上面的頁面來說,這樣的過濾可能已經足夠了,但是很多時候場景永遠比想象的更多。

<a href="{輸入點}">

<div style="{輸入點}">

<img src="{輸入點}">

<img src={輸入點}>(沒有引號)

<script>{輸入點}</script>

對於這樣的場景來說,上面的過濾已經沒有意義了,尤其輸入點在script標籤里的情況,剛才的防禦方式可以說是毫無意義。

一般來說,為了能夠應對這樣的xss點,我們會使用更多的過濾方式。

首先是肯定對於符號的過濾,為了能夠應對各種情況,我們可能需要過濾下面這麼多符號

% * + , – / ; < = > ^ | `

但事實上過度的過濾符號嚴重影響了用戶正常的輸入,這也是這種過濾使用非常少的原因。

大部分人都會選擇使用htmlspecialchars+黑名單的過濾方法

on/w+=
script
svg
iframe
link
…

這樣的過濾方式如果做的足夠好,看上去也沒什麼問題,但回憶一下我們曾見過的那麼多XSS漏洞,大多數漏洞的產生點,都是過濾函數忽略的地方。

那麼,是不是有一種更底層的防禦方式,可以從瀏覽器的層面來防禦漏洞呢?

CSP就這樣誕生了…

0x02 CSP(Content Security Policy)

Content Security Policy (CSP)內容安全策略,是一個附加的安全層,有助於檢測並緩解某些類型的攻擊,包括跨站腳本(XSS)和數據注入攻擊。

CSP的特點就是他是在瀏覽器層面做的防護,是和同源策略同一級別,除非瀏覽器本身出現漏洞,否則不可能從機制上繞過。

CSP只允許被認可的JS塊、JS文件、CSS等解析,只允許向指定的域發起請求。

一個簡單的CSP規則可能就是下面這樣

header("Content-Security-Policy: default-src 'self'; script-src 'self' https://lorexxar.cn;");

其中的規則指令分很多種,每種指令都分管瀏覽器中請求的一部分。

Google團隊利用他們強大的搜索引擎庫,分析了超過160w台主機的CSP部署方式,他們發現。

加載腳本最常列入白名單的有15個域,其中有14個不安全的站點,因此有75.81%的策略因為使用了了腳本白名單,允許了攻擊者繞過了CSP。總而言之,我們發現嘗試限制腳本執行的策略中有94.68%是無效的,並且99.34%具有CSP的主機制定的CSP策略對xss防禦沒有任何幫助。

在paper中,Google團隊正式提出了兩種以前被提出的CSP種類。

1、nonce script CSP

header("Content-Security-Policy: default-src 'self'; script-src 'nonce-{random-str}' ");

動態的生成nonce字符串,只有包含nonce字段並字符串相等的script塊可以被執行。

<script nonce="{random-str}">alert(1)</script>

這個字符串可以在後端實現,每次請求都重新生成,這樣就可以無視哪個域是可信的,只要保證所加載的任何資源都是可信的就可以了。

<?php

Header("Content-Security-Policy: script-src 'nonce-".$random." '"");
?>
<script nonce="<?php echo $random?>">

2、strict-dynamic

header("Content-Security-Policy: default-src 'self'; script-src 'strict-dynamic' ");

SD意味着可信js生成的js代碼是可信的。

這個CSP規則主要是用來適應各種各樣的現代前端框架,通過這個規則,可以大幅度避免因為適應框架而變得鬆散的CSP規則。

Google團隊提出的這兩種辦法,希望通過這兩種辦法來適應各種因為前端發展而出現的CSP問題。

但攻與防的變遷永遠是交替升級的。

1、nonce script CSP Bypass

2016年12月,在Google團隊提出nonce script CSP可以作為新的CSP趨勢之後,聖誕節Sebastian Lekies提出了nonce CSP的致命缺陷。

Nonce CSP對純靜態的dom xss簡直沒有防範能力

http://sirdarckcat.blogspot.jp/2016/12/how-to-bypass-csp-nonces-with-dom-xss.html

Web2.0時代的到來讓前後台交互的情況越來越多,為了應對這種情況,現代瀏覽器都有緩存機制,但頁面中沒有修改或者不需要再次請求後台的時候,瀏覽器就會從緩存中讀取頁面內容。

location.hash就是一個典型的例子

如果JS中存在操作location.hash導致的xss,那麼這樣的攻擊請求不會經過後台,那麼nonce后的隨機值就不會刷新。

這樣的CSP Bypass方式我曾經出過ctf題目,詳情可以看

https://lorexxar.cn/2017/05/16/nonce-bypass-script/

除了最常見的location.hash,作者還提出了一個新的攻擊方式,通過CSS選擇器來讀取頁面內容。

*[attribute^="a"]{background:url("record?match=a")} 
*[attribute^="b"]{background:url("record?match=b")} 
*[attribute^="c"]{background:url("record?match=c")} [...] 

當匹配到對應的屬性,頁面就會發出相應的請求。

頁面只變化了CSS,純靜態的xss。

CSP無效。

2、strict-dynamic Bypass

2017年7月 Blackhat,Google團隊提出了全新的攻擊方式Script Gadgets。

header("Content-Security-Policy: default-src 'self'; script-src 'strict-dynamic' ");

Strict-dynamic的提出正是為了適應現代框架
但Script Gadgets正是現代框架的特性

转载请注明:IAMCOOL » 前端防禦從入門到棄坑–CSP變遷

0 0 vote
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x