前端知識筆記 - 安全

前端知識筆記 - 安全

本文章總結 https://github.com/thedaviddias/Front-End-Checklist
內部,非原創性內容。javascript

https

  1. 儘可能使用 Https,我的網站可以使用 Let's Encrypt
  2. 使用 Strict-Transport-Security 返回頭。解決的問題是https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet
  • 使用書籤或手動輸入網址訪問 http 網址
  • https 頁面中不經意使用了 https 的資源(連接、內容等)
  • 中間攻擊人讓用戶信任證書,設置返回頭後,瀏覽器不接受不受信任的證書

設置方式以下:
max-age 表示在該有效時間內應該使用 https 訪問,includeSubDomains 表示該域名的全部子域名適用於該策略,preload 表示預加載時不會使用 http 連接。
三個參數必須都設置才更安全。
示例:php

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Secure Server Design 安全服務設計

地址:https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheetcss

  1. 在任意地方使用 TLS 或其餘更強的加密服務 (Use TLS or Other Strong Transport Everywhere)
    內部網絡也可被黑客攻擊到,登陸頁必須使用 HTTPS,不然表單和 session 都有被盜取的可能
    不支持 TLS 的服務 SEO 權重會下降前端

  2. 涉及安全的頁面必須使用 TLS(Do Not Provide Non-TLS Pages for Secure Content)java

  3. TLS 下不要混用非 TLS 內容(Do Not Mix TLS and Non-TLS Content)
    非 TLS 內容可被篡改nginx

  4. cookie 使用 secure 標識( Use "Secure" Cookie Flag)
    設置 httpOnly 能夠禁止頁面訪問該 cookie,設置 secure 能夠設置 cookie 只在 https 下傳輸git

  5. 敏感數據不使用 URL 傳輸(Keep Sensitive Data Out of the URL)
    URL 中不能傳輸數據,即便使用了 HTTPS。有兩種可能泄漏:
  • URL 會被瀏覽器緩存,也就是該電腦上其餘人能夠看到該解碼後的數據
  • 頁面上點擊其餘網站,其餘網站會取到 referral 字段,從而泄漏
  1. 不要緩存敏感數據(Prevent Caching of Sensitive Data)
    TLS 只能保證傳輸安全,客戶端和代理部分泄漏數據是沒法避免的,因此須要設置敏感數據不緩存
Cache-Control: no-cache, no-store"
"Expires: 0"
  1. 使用 Strict-Transport-Security (Use HTTP Strict Transport Security)
    確保用戶不會訪問 HTTP 頁面github

  2. Pinning 技術(Use Public Key Pinning)
    地址: https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinningweb

這一部分主要是講使用雙向驗證的方式來解決掉中間人攻擊的問題。簡單來講就是客戶端存儲服務端的 public key,
經過驗證服務端下發的公鑰和當前存儲的公鑰是否相同,或者 hash 值是否相同。這種方式可使用自簽發證書,不須要使用 ca 簽發的證書。
在客戶端中使用該技術比較多, web 端一樣可使用:ajax

Public-Key-Pins: max-age=2592000;
pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=";
report-uri="http://example.com/pkp-report"

設置 key 的 hash 值,在指定的過時時間以前,服務端使用的 public key hash 不會變化,不然不該該信任。

服務端證書相關

  1. 使用加密更強的 key 和安全存儲(Use Strong Keys & Protect Them)
    目前安全最低位爲 2048 位

  2. 使用包含當前必須域名的證書(Use a Certificate That Supports Required Domain Names)
    使用一致的域名或主機名,不要使用過時證書。有多域名,須要證書中指定多域名,即Subject Alternate Names (SANs)

  3. 使用正確的名稱(Use Fully Qualified Names in Certificates)
    不要使用 localhost 或者 ip 或者 www 等

  4. 不要使用通配符證書(Do Not Use Wildcard Certificates)

  5. 不要使用 RFC 1918 地址(Do Not Use RFC 1918 Addresses in Certificates)
    好比:192.168/16, 172.16/12, and 10/8.

  6. 根據用戶基數設計合適的證書認證方式(Use an Appropriate Certification Authority for the Application's User Base)
    內部應用可以使用內部證書,全部用戶應該安裝該證書,其餘狀況請使用公用證書服務商,他們的證書已經內置於當前應用中。
    不容許使用自簽發證書

  7. 請提供全部須要的證書(Always Provide All Needed Certificates)
    證書必須可被回溯到信任的根證書。證書路徑可有多級,因此須要證書提供到根證書以前的全部證書

  8. SHA1 證書已廢棄(Be aware of and have a plan for the SHA-1 deprecation plan)

服務端協議和加密配置

  1. 僅支持強協議(Only Support Strong Protocols)
    儘可能提供支持 TLS 1.1 和 TLS 1.2 的

  2. 使用短暫密鑰(Prefer Ephemeral Key Exchanges)

  3. 只支持強加密算法(Only Support Strong Cryptographic Ciphers)

  4. (Support TLS-PSK and TLS-SRP for Mutual Authentication)

  5. 只支持安全的從新協商(Only Support Secure Renegotiations)

  6. 禁用壓縮(Disable Compression)

  7. 更新加密庫(Update your Crypto Libraries)

客戶端配置

web 服務是由瀏覽器進行認證的,不受應用控制。其餘狀況下須要進行配置:

  • 服務端應用以 TLS 方式鏈接其餘的 web 服務或者交換數據。
  • 重客戶端應用 TLS 鏈接服務器
    配置是否正確必定要驗證

其餘

  1. EV 證書(Extended Validation Certificates),目的是的費用是合法的實體,給用戶更多的保證,注意,它自己不提供更好的加密方式,
    只是增長用戶信心

  2. 客戶端證書,也就是「雙向 TLS」,即服務端一樣須要驗證客戶端的身份,因爲證書生成複雜,分發安全性,客戶端配置,證書吊銷和重發行,
    這類證書用法只在高價值的鏈接且用戶量比較少的場景

  3. 證書和公鑰的 pinning(Certificate and Public Key Pinning)。Pinning 是將 host(好比服務器)和認證內容(證書或者公鑰),
    應用對已經存在的關係進行認證。意思是若是從服務端下載的證書和本地存在的證書不匹配,不創建鏈接。一般在 Hybrid 和Native 應用中使用。
    而 web 瀏覽器的應用沒法實現。

最後後端服務也須要進行加密,包括內網服務。

Cross Site Request Forgery (CSRF)

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
簡單翻譯下:跨域請求僞造,一個惡意的網站、郵件、博客或者實時信息,經過瀏覽器針對信任的網站發起請求(用戶已登陸狀況下)。

須要保護的內容包括:

  • form 使用 POST
  • Ajax/Xhr 調用
    注意:不要使用 GET 請求執行狀態改變操做,若是不得不,須要保護該方法。

CSRF 保護總結:建議使用基於 token 減小 CSRF 攻擊。在高度敏感操做中,使用交互式保護,使用二次認證或者一次性 TOKEN。
深度防禦參照後面

相關文章見:https://seclab.stanford.edu/websec/csrf/csrf.pdf

CSRF 推薦防禦方式

主要方式:遷移 TOKEN 方式(Token Based Mitigation)

注:須要使用強加密或者 HMAC 方法,推薦使用 AES256-GCM 或者 SHA256/512 方式
嚴格的加密 KEY 輪換和 token 生命週期策略

  • 令牌同步模式(Synchronizer Token Pattern,STP),寫操做須要添加安全的隨機 token,該 token 能夠放在 headers 或者參數中(ajax)、URL (GET),與服務端的 token 進行對比。該方案原本用於防止表單重複提交,由服務端進行是否存在和是否正確進行驗證,開發者能夠更好的驗證用戶的提交意圖,從而避免 CSRF 攻擊。注意的是: token 不能像 cookie 同樣由瀏覽器自動發出,同時若是使用基於請求的 token 比基於用戶 session 的 token 安全性更高,但可用性較低,可能形成正常訪問失效的問題。不要使用 GET 請求進行敏感操做,在 referer 字段中會暴露 csrf token,
  • 令牌加密模式(Encryption based Token Pattern),即無狀態模式。服務端基於用戶 ID,時間戳,一次性數字使用惟一的 KEY 對 token 進行加密,返回給客戶端,這種狀況下重放攻擊和修改攻擊失效。主要用於無狀態應用。
  • 令牌HMAC模式(HMAC Based Token Pattern),即便用HMAC(hash-based message authentication code,哈希運算消息認證碼)加密方式。它與令牌加密模式相似,有兩點不一樣:1. 使用強 HMAC 函數而不是使用加密函數;2. 包括額外的字段"operation" 代表操做的目的。一樣包含用戶 ID,時間戳和 nouce,operation 字段

深度防禦

  1. 驗證標準 headers 中的 origin 字段(Verifying origin with standard headers)。

有兩個步驟:1. 驗證請求來源(source origin. 可經過 Origin/Referer header),2. 驗證請求要去哪裏(target origin)。之全部使用標準字段,是由於使用 javascript 的 XSS 攻擊沒法修改這兩個字段(forbidden headers,只能由瀏覽器設置)。

  • 驗證來源 origin。其中 Referer 在從 https 跳轉至 http 中會丟失,但會保留 Origin 字段,同協議之間跳轉會保留 Referer. 必定要強驗證,如 site.com 和 site.com.attacker.com. 若是兩個字段都不存在,建議 block 掉該請求,或者記錄請求,後續確認後進行攔截。
  • 驗證目標 origin。若是用戶直接訪問服務,可以使用 URL 驗證目標 origin; 若是你的服務在代理後面,1. 設置服務爲已知的 origin,若是存在多域,可考慮使用集中的配置,實例從中獲取;2. 使用 host 請求頭的值,若是位於 proxy 後面,host 值會變化。3. 使用 X-Forwarded-Host 的值,該值的上的是包括初始的請求 host,大多數 proxy 會將 Host 值傳過來。

一般狀況下驗證 header 沒有問題,但特殊狀況下可能不存在該 headers。好比

  • IE11 在跨域信任區時不帶 Origin 字段
  • 302 重定向跨域請求不帶 Origin
  • 一些隱私狀況下 Origin 會爲 null
  • Origin 在跨域請求中所有攜帶,在同域時只包括 post/delete/put 方法。
  • Referer 也一樣有問題,部分狀況下會被省略,同時負載均衡、代理、嵌入式設置也會因隱私的緣由移除該字段。

    因此要使用驗證須要先觀察一段時間,而後將例外添加至代碼中。該方式有兩個問題:依賴於瀏覽器行爲,須要更新規則,同時存在 XSS 攻擊時,防範效果有限。

  1. 再次提交 cookie 策略(Double Submit Cookie)
    若是不方便使用 csrf token,可使用該方式,經過比較請求帶的隨機值和 cookie 中隨機值是否相等來判斷。該方式基於用戶沒法讀取 cookie 或者修改該 cookie 值,在跨域狀況下也會出現寫 cookie 的狀況,好比寫 cookie 能夠指定爲父域,則該域下的 cookie 都不安全,或者中間人攻擊將 https 轉換爲 http。因此使用該方式要保證子域都安全,且只接受 HTTPS 請求。該方式的另外一種變體是 header 中帶有 加密的 token,請求中再帶該 token。

  2. 同站 Cookie 屬性(SameSite Cookie Attribute)
    由 google 提出,阻止瀏覽器跨域發送 cookie。設置以下:

Set-Cookie: JSESSIONID=xxxxx; SameSite=Strict
Set-Cookie: JSESSIONID=xxxxx; SameSite=Lax
瀏覽器全局生效,但要注意,該技術目前處於草案狀態,實現的並不徹底。不推薦做爲主要的防護方式
  1. 使用自定義請求頭(Use of Custom Request Headers)
    自定義請求頭則只限於同域,在跨域時須要服務端指定其餘攜帶的 Headers。該方式可保護 ajax 請求,不能保護 form 請求,跨域 CORS 設置

  2. 用戶交互式防護(User Interaction Based CSRF Defense)

    用戶交互式會更爲方便,好比使用
  • 二次認證(密碼或者更強)
  • 一次性 token
  • 驗證碼

僅限於高度敏感的場景

  1. 登陸 SCRF(Login CSRF)

    登陸頁面也會產生 CSRF 攻擊,在用戶已經登陸的狀況下,防範方式是未登陸前產生一個pre-session(可以使用以上三種技術)

其餘:三次提交驗證,使用 content-type 的 pre-flight

Cross Site Scripting (XSS)

本文地址: https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

攻擊方式: Strored, Reflected 和 DOM XSS。

Stored: 將注入攻擊腳本存儲在目標服務器上,好比數據庫,消息論壇,訪客日誌,評論等,受害者從服務器獲取存儲的信息時獲得了惡意腳本, 爲 Type-I 攻擊

Reflected: 反射攻擊的腳本不在 web 服務器上,主要是在錯誤提示,搜索結果,或者其餘返回信息有一部分輸入。反射攻擊在其餘路由上,好比郵件或者其餘網站,當用戶點惡意連接,提交了釣魚表單或者只是瀏覽了惡意站點,惡意代碼會被帶到受攻擊的網站。Type-II 攻擊

DOM XSS 會在後面講到。

注意,請使用已經成熟的一些庫來實現,避免遺漏。一般實現 rule2 和3 便可知足大部分狀況的需求。

XSS 預防規則

  1. 不在未容許的位置插入不信任的數據(Never Insert Untrusted Data Except in Allowed Locations)
  2. 插入 HTML 片斷前須要進行轉義(HTML Escape Before Inserting Untrusted Data into HTML Element Content)
    ,包括一些執行的上下文,如 script,style,事件. 使用 16 進制的實體
  3. HTML 普通屬性轉義(Attribute Escape Before Inserting Untrusted Data into HTML Common Attributes),僅限於普通屬性如w idth,name,value等,屬性設置不能用於複雜屬性如 href, src, style 或者其餘事件處理 onmouseover。
  4. js 代碼在插入js 數據值時轉義(JavaScript Escape Before Inserting Untrusted Data into JavaScript Data Values), setInterval 等函數是沒法轉爲可靠數據的。HTML 中的 JSON 字符串一樣須要轉義,使用 JSON.parse 而不是 eval
  5. css 轉義並在插入style 屬性值前嚴格驗證(CSS Escape And Strictly Validate Before Inserting Untrusted Data into HTML Style Property Values), url,behavior,custom 不能使用。例如:
{ background-url : "javascript:alert(1)"; }  // and all other URLs
 { text-size: "expression(alert('XSS'))"; }   // only in IE
  1. 插入 URL 參數時對URL 進行轉義 (URL Escape Before Inserting Untrusted Data into HTML URL Parameter Values)
  2. 使用專用庫來過濾 HTML 標籤(Sanitize HTML Markup with a Library Designed for the Job)
  3. 阻止基於 DOM 的 XSS 攻擊(Prevent DOM-based XSS)

其餘預防方式

  1. 使用 httpOnly 的 cookie,防止cookie 被讀取
  2. 實現 Content Security Policy. 這是解決 XSS 攻擊的一個好方式,即建立來源白名單,若是 javascript,css,image 等。
Content-Security-Policy: default-src: 'self'; script-src: 'self' static.domain.tld
  1. 使用自動轉換模板系統(Use an Auto-Escaping Template System)
  2. 使用 X-XSS-Protection 返回頭(Use the X-XSS-Protection Response Header)

總結請參考 https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

數據類型 上下文 樣例 防護方式
String HTML Body <span>UNTRUSTED DATA</span> HTML 實體轉義
String 安全的 HTML 屬性 <input type="text" name="fname" value="UNTRUSTED DATA"> 1. 侵入式轉換爲 > 256 爲&#xHH; 格式.
2. 只在安全白名單內的屬性添加不信任的數據
3. 針對不安全的屬性如 background,id , name 進行嚴格驗證
String GET 參數 <a href="/site/search?value=UNTRUSTED DATA">clickme</a> 使用 %HH 格式對 GET 中參數進行轉義
String src 或 href 中不受信任的 URL <a href="UNTRUSTED URL">clickme</a>
<iframe src="UNTRUSTED URL" />
1. 規範化輸入
2. URL 驗證
3. 安全 URL 覈實
4. 只使用安全白名單內的 HTTP 或 HTTPS 地址,避免使用 JS 協議打開新窗口
5. 屬性轉義
String Css 值 <div style="width: UNTRUSTED DATA;">Selection</div> 1. 使用嚴格的結構驗證
2. CSS 16進制轉義
3. 設計良好的 CSS 特性
String javascript 變量 <script>var currentValue='UNTRUSTED DATA';</script>
<script>someFunction('UNTRUSTED DATA');</script>
1. 確保 js 變量使用引號起起來
2. js 16 進制轉義
3. js Unicode 轉義
4. 避免 \",\',\\的轉義
HTML HTML Body <div>UNTRUSTED HTML</div> 對 HTML 的標籤等進行驗證
String DOM XSS <script>document.write("UNTRUSTED INPUT: " + document.location.hash);<script/> 參見 DOM 的 XSS 攻擊

DOM XSS 防範

DOM XSS 和 stored reflected 攻擊的主要區別在於應用中攻擊注入的位置。 relected 和 stored 都是服務端注入,而 DOM 注入則是客戶端注入。XSS 攻擊老是在客戶端執行的。本部分中HTML 等攻擊都是由 Javascript 執行的,因此稱爲子上下文。

本部分摘自: https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet

防範規則

  1. 插入 HTML 子上下文未受信任的數據時時須要先對 HTML 轉義而後是 JavaScript 轉義(HTML Escape then JavaScript Escape Before Inserting Untrusted Data into HTML Subcontext within the Execution Context)
  2. 在爲 HTML 屬性插入不受信任的數據時須要進行 javascript 轉義(JavaScript Escape Before Inserting Untrusted Data into HTML Attribute Subcontext within the Execution Context)
  3. 在向事件監聽和 js 代碼插入未知數據時必定要當心(Be Careful when Inserting Untrusted Data into the Event Handler and JavaScript code Subcontexts within an Execution Context)
  4. 對要插入的 CSS 屬性值進行 JS 轉義(JavaScript Escape Before Inserting Untrusted Data into the CSS Attribute Subcontext within the Execution Context)
  5. 對要插入的 URL 屬性進行 URL 轉義(URL Escape then JavaScript Escape Before Inserting Untrusted Data into URL Attribute Subcontext within the Execution Context)
  6. 添加 DOM 時使用安全的函數或方法(Populate the DOM using safe JavaScript functions or properties),好比使用 textContent
  7. 修復 DOM 跨域腳本攻擊(Fixing DOM Cross-site Scripting Vulnerabilities)

XSS 攻擊難防範是因爲攻擊面廣且瀏覽器之間有差別。下面是推薦實踐:

  1. 不受信任的數據應該只做爲展現的文本
  2. 使用模板的時候老是對 js 代碼進行轉義並將數據限定在引號以內
  3. 使用 document.createElement("xx"), element.setAttribute(), element.appendChild 等來構建動態的界面
  4. 避免 InnerHtml 等 HTML 渲染方法使用不受信任的數據
  5. 避免使用隱式 eval 的函數, 好比 setTimeout等。轉義的正確方式是服務轉換外部的的數據,客戶端只轉義子上下文好比 dom 方法的數據。
  6. 限制未知數據在正確的操做下使用,即不要使意料以外的生效
  7. URL 轉義時要注意字符集的問題
  8. 限制 object[x] 使用的範圍
  9. 讓代碼運行在 es5 下或者沙盒內,增長 API 解碼難度
  10. 不要使用 evel 來解析 JSON 對象

推薦的轉義庫:esapi, Apache Commons String Utils,Jtidy, 其餘本身公司的實現
最後,innerText 在某些標籤下仍舊可被執行,火狐也不支持該方法。

Content Type 選項

主要是爲了阻止 Chrome 和 IE 對服務端返回的類型進行文本 mime 類型嗅探。
減小在上傳或下載文件時因爲用戶設置其餘名稱會致使文件後綴變爲其餘類型,好比可執行文件。

即設置 X-Content-Type-Options
nosniff, 好比nginx

add_header X-Content-Type-Options "nosniff" always;

X-Frame-Options(XFO)

保護用戶避免點擊劫持, 主要指浮層或者連接篡改。該信息能夠設置爲 DENY(代表當前站點不能夠被 iframe 嵌入) 或者 SAMEORIGIN(同一來源),ALLOW-FROM https://e.com 指定站點

nginx 設置:

add_header X-Frame-Options "SAMEORIGIN" always;

Content Security Policy

該屬性表示網站內容如何載入且在哪裏容許載入,也能夠用於解決點擊劫持的問題。
這個屬性可設置內容比較多,解決一些 CSRF,XSS 問題。 CSP 設置決定哪些內容是屬於白名單以內的。

Content-Security-Policy: script-src 'self'

參見:https://content-security-policy.com/
該屬性可保護的內容包括:

default-src: 全部資源可容許的路徑,主要是用於 fallback
script-src: 定義 script 可被執行的來源
object-src: 定義能夠加載插件的的來源, 針對<object>, <embed> or <applet>
style-src: 定義css 來源
Img-src: 圖片來源
media-src: 定義 video 和 audio 加載 來源
frame-src: 定義哪一個來源能夠加載  frame
frame-ancestors: 可引用當前頁面的配置,設置爲 none 幾乎等同於 X-Frame-Options: DENY
font-src: 定義寶體來源
connect-src: 哪一個來源能夠加載  script 接口,針對的是 AJAX WEBSOCKET 和 EventSource
form-action: 哪一個來源能夠用於加載form 元素
sandbox: 哪一個來源使用沙盒
script-none: script 元素加載哪一個形式的的腳本
plugin-types: 
reflected-xss: 
report-uri: 報告衝突的網址,即策略攔截的後上報地址

Content-Security-Policy: default-src https: 容許加載 https 任何域

Content-Security-Policy: default-src https://scotthelme.co.uk:443 限定了加載地址

Content-Security-Policy: default-src https://scotthelme.co.uk:* 可任意端口

none 阻止加載此類資源

self 只加載當前來源

unsafe-inline 容許使用行內的 js 和 css

unsafe-eval 容許使用 eval

CSP 包含的內容仍是比較多,使用的時候建議去閱讀原文

相關文章
相關標籤/搜索