迷茫2017-05-16 13:10:53
XSS
(Cross-Site Script) 攻擊又叫跨站腳本攻擊, 本質是一種注入攻擊. 其原理, 簡單的說就是利用各種手段把惡意代碼添加到網頁中, 並讓受害者執行這段腳本. XSS能做用戶使用瀏覽器能做的一切事情. 偉大的同源策略也無法保證不受XSS攻擊,因為此時攻擊者就在同源之內.
從攻擊的方式可以分為
反射型
儲存型
文檔型
這種分類方式有些過時, 長久以來, 人們認為XSS分類有以上三種, 但實際情況中經常無法區分, 所以更明確的分類方式可以分為以下兩類:
client(客戶端型)
server(服務端型)
當一端xss代碼是在服務端被插入的, 那麼這就是服務端型xss, 同理, 如果代碼在客戶端插入, 就是客戶端型xss.
無論是服務端型或客戶端型xss,攻擊達成都需要兩個條件
程式碼被注入
程式碼被執行
其實只要做好無論任何情況下保證程式碼不被執行就能完全杜絕xss攻擊.
總之, 任何時候都不要把不受信任的數據直接插入到dom中的任何位置, 一定要做轉義。
對於某些位置,不受信任的資料做轉義就可以保證安全
一般的標籤屬性值
p body 的內部html
對於某些位置,即使做了轉義依然不安全
script標籤中
註釋中
表籤的屬性名稱
標籤名
css標籤中
使用JSON.parse 而不是eval, request 的content-type要指定是Content-Type: application/json;
如果連結的URL中部分是動態產生的, 一定要做轉義.
可以透過http頭控制是否開啟 xss-filter, 預設為開啟.
通常情況下, 在http header中加入以下欄位表示啟用xss-filter.
X-XSS-Protection:1 (默认)
X-XSS-Protection:1;mode=block (强制不渲染, chrome跳空白页,IE展示一个#号)
如需禁用xss-filter, 將 X-XSS-Protection
設定為0即可.
如上, 現代瀏覽器都對反射型xss有一定的防禦力, 其原理是檢查url和dom中元素的相關性. 但這並不能完全防止反射型xss. 這裡有個可供測試的鏈接, 傳送門: XSS Test Page.
另外, 瀏覽器對於存儲型xss並沒有抵抗力, 原因很簡單, 用戶的需求是多種多樣的. 所以, 抵禦xss這件事情不能指望瀏覽器.
Content Security Policy, 即內容安全策略, 簡稱csp.
為了緩解很大一部分潛在的跨站腳本問題, 瀏覽器的擴展程序系統引入了CSP. CSP 管理網站允許加載的內容, 並且使用白名單的機制對網站加載或執行的資源起作用. 在網頁中, 這樣的策略透過HTTP 頭資訊或meta 元素定義.
CSP 並不是用來防止xss 攻擊的, 而是最小化xss 發生後所造成的傷害. 實際上, 除了開發者自己做好xss 轉義, 並沒有別的方法可以防止xss 的發生. CSP 可以說是HTML5為web安全帶來的最實惠的東西. 那麼如何引入CSP 呢?
通過response頭
只允許腳本從本來源載入Content-Security-Policy: script-src ‘self’
透過HTML的META標籤
作用同上
那麼CSP 除了限制script-src 之外還能限制什麼呢?
base-uri : 限制這篇文件的uri
child-src :限制子視窗的來源(iframe,彈跳窗等),取代frame-src
connect-src :限制腳本可以存取的來源
font-src : 限製字體的來源
form-action : 限製表單能夠提交到的來源
frame-ancestors : 限制了目前頁面可以被哪些頁面以iframe,frame,object等方式載入
frame-src :deprecated with child-src,限制了目前頁面可以載入哪些來源,與frame-ancestors對應
img-src : 限制圖片可以從哪些來源載入
media-src : 限制video, audio, source, track 能夠從哪些來源載入
object-src :限制外掛程式可以從哪些來源載入
sandbox :強制開啟沙盒模式
可以看出, CSP是一個強大的策略, 幾乎可以限制了所有能夠用到的資源的來源. 使用好CSP可以很大成都降低XSS帶來的風險.
另外, CSP還提供一個報告的頭域 Content-Security-Policy-Report-Only
, 使用這個頭域, 瀏覽器會向伺服器報告csp狀態.
Content-Security-Policy-Report-Only: script-src 'self'; report-uri http://cspReport/
使用了上面的設定, 若頁面上存在內聯的js, 它依然會執行, 不過瀏覽器會向發送一個post請求, 包含如下資訊.
{
"csp-report":
{
"document-uri": "http://cspReport/test.php",
"referrer": "",
"violated-directive": "script-src 'self'",
"original-policy": "script-src 'self'; report-uri http://cspReport/",
"blocked-uri": ""
}
}
CSP 目前有兩版, CSP1 和 CSP2. 兩版的支援狀態可以在 http://caniuse.com/#search=csp 中查到. 如下:
CSP1支持性
CSP2支持性
CSP雖然提供了強大的安全保護, 但是他也造成瞭如下問題: Eval及相關函數被禁用、內嵌的JavaScript程式碼將不會執行、只能透過白名單來載入遠端腳本.
X-Frame-Options 回應頭是用來給瀏覽器指示允許一個頁面可否在frame
, iframe
或者 object
等標籤中展現的標記. 網站可以使用此功能, 來確保自己網站的內容沒有被嵌到別人的網站中去,也從而避免了點擊劫持(clickjacking) 的攻擊. 但以後可能被CSP的frame-ancestors取代。目前支援的狀態比起 CSP frame-ancestors好.
X-Frame-Options 共有三個值:
DENY 表示這個頁面不允許被以frame的方式載入
SAMEORIGIN 表示這個頁面只允許被同源頁面載入
ALLOW-FROM uri 表示這個頁面只能被特定的網域載入
伺服器配置
java程式碼:
response.addHeader("x-frame-options","SAMEORIGIN");
Nginx設定:
addheader X-Frame-Options SAMEORIGIN
Apache設定:
Header always append X-Frame-Options SAMEORIGIN
瀏覽器相容性
特性 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
基礎支援 | 4.1.249.1042 | 3.6.9 (1.9.2.9) | 8.0 | 10.5 | 4.0 |
ALLOW-FROM 支援 | Not supported | 18.0 | 8.0? | ? | Not supported |
使用 http-only後, 可禁止js讀寫cookie, 可以保證即使發生了xss, 用戶的cookie也是安全的.
HTML5為iframe提供了安全屬性 sandbox, 進而限制iframe的能力. 如下:
<iframe src="untrusted.html" sandbox="allow-scripts allow-forms"></iframe>
X-Content-Type-Options 阻止瀏覽器進行content-type 嗅探, 能夠防止類型嗅探攻擊.
這個header主要用來防止在IE9、chrome和safari中的MIME類型混淆攻擊. 通常瀏覽器可以通過嗅探內容本身的方法來決定它是什麼類型, 而不是看響應中的content-type值. 通過設定X-Content-Type-Options:如果content-type和期望的類型匹配,則不需要嗅探,只能從外部載入確定類型的資源. 舉個例子, 如果載入了一個樣式表, 那麼資源的MIME類型只能是text/css, 對於IE中的腳本資源, 以下的內容類型是有效的:
application/ecmascript
application/javascript
application/x-javascript
text/ecmascript
text/javascript
text/jscript
text/x-javascript
text/vbs
text/vbscript
對於chrome, 則支援下面的MIME 類型:
text/javascript
text/ecmascript
application/javascript
application/ecmascript
application/x-javascript
text/javascript1.1
text/javascript1.2
text/javascript1.3
text/jscript
text/live script
正確的設定
nosniff – 这个是唯一正确的设置.
通常不正確的設定
‘nosniff’ – 引号是不允许的
: nosniff – 冒号也是错误的
如何偵測
在IE和chrome中開啟開發者工具,在控制台中觀察配置了nosniff和沒有配置nosniff的輸出有啥區別.
HPKP 是一個response 頭, 用來檢測一個證書的公鑰是否發生了改變, 防止中間人攻擊.
我們知道, 受信任的CA(證書頒發機構)有好幾百個, 他們成為整個網站身份認證過程中一個較大的攻擊面. 現有的證書信任鏈機制最大的問題是, 任何一家受信任的CA 都可以簽發任意網站的網站憑證, 這些憑證在瀏覽器看來, 都是合法的.
HPKP 技術給予我們主動選擇信任CA 的權利. 它的工作原理是通過響應頭或 標籤告訴瀏覽器當前網站的證書指紋, 以及過期時間等其它信息. 未來一段時間內, 瀏覽器再次訪問這個網站必須驗證憑證鏈中的憑證指紋, 如果跟之前指定的值不符, 即便憑證本身是合法的, 也必須斷開連線.
HPKP 官方文件見 RFC7469 , 目前 Firefox 35+ 和 Chrome 38+ 已經支援. 它的基本格式如下:
Public-Key-Pins: pin-sha256="base64=="; max-age=expireTime [; includeSubdomains][; report-uri="reportURI"]
HSTS 是國際互聯網工程組織IETE正在推行一種新的Web安全協議, 可以用來抵禦中間人攻擊, 它強制瀏覽器使用TSL作為數據通道, 即強制使用HTTPS與伺服器創建連接.
伺服器開啟HSTS的方法是, 當客戶端透過HTTPS發出請求時, 在伺服器傳回的超文本傳輸協定回應頭中包含Strict-Transport-Security欄位. 非加密傳輸時設定的HSTS欄位無效.
例如, https://xxx 的回應頭含有Strict-Transport-Security: max-age=31536000; includeSubDomains. 這表示兩點:
在接下來的一年(即31536000秒)中, 瀏覽器只要向xxx或其子域名發送HTTP請求時, 必須採用HTTPS來發起連接. 例如, 用戶點擊超鏈接或在地址欄輸入http:// xxx/ , 瀏覽器應自動將http 轉寫成https, 然後直接向https://xxx/ 發送請求.
在接下來的一年中, 如果 xxx 伺服器發送的TLS證書無效, 用戶不能忽略瀏覽器警告繼續訪問網站.
不足就是, 用戶首次訪問網址是不受HSTS保護的, 這是因為首次還未收到HSTS. 解決方案有兩個, 一是瀏覽器預置HSTS域名列表, Google Chrome、Firefox 和Internet Explorer 實現了此方案. 二是將HSTS資訊加入網域名稱系統記錄.
最後提供一個前端xss過濾的方法
function xssCheck(str,reg){
return str ? str.replace(reg || /[&<">'](?:(amp|lt|quot|gt|#39|nbsp|#\d+);)?/g, function (a, b) {
if(b){
return a;
}else{
return {
'<':'<',
'&':'&',
'"':'"',
'>':'>',
"'":''',
}[a]
}
}) : '';
}
可以直接看我的部落格原文,體驗更好。 xss攻防淺談
曾经蜡笔没有小新2017-05-16 13:10:53
伺服器端用的是什麼語言實現的,就是把表單的內容中有