天天看點

【面試篇】寒冬求職之你必須要懂的Web安全

随着網際網路的發展,各種Web應用變得越來越複雜,滿足了使用者的各種需求的同時,各種網絡安全問題也接踵而至。作為前端工程師的我們也逃不開這個問題,今天一起看一看Web前端有哪些安全問題以及我們如何去檢測和防範這些問題。非前端的攻擊本文不會讨論(如SQL注入,DDOS攻擊等),畢竟後端也非本人擅長的領域。

QQ郵箱、新浪微網誌、YouTube、WordPress 和 百度 等知名網站都曾遭遇攻擊,如果你從未有過安全方面的問題,不是因為你所開發的網站很安全,更大的可能是你的網站的流量非常低或者沒有攻擊的價值。

本文主要讨論以下幾種攻擊方式: XSS攻擊、CSRF攻擊以及點選劫持。

希望大家在閱讀完本文之後,能夠很好的回答以下幾個面試題。

1.前端有哪些攻擊方式?

2.什麼是XSS攻擊?XSS攻擊有幾種類型?如果防範XSS攻擊?

3.什麼是CSRF攻擊?如何防範CSRF攻擊

4.如何檢測網站是否安全?

在開始之前,建議大家先clone代碼,我為大家準備好了示例代碼,并且寫了詳細的注釋,大家可以對照代碼來了解每一種攻擊以及如何去防範攻擊,畢竟看再多的文字,都不如實操。(ReadMe中詳細得寫了操作步驟):https://github.com/YvetteLau/Blog/tree/master/Security

【面試篇】寒冬求職之你必須要懂的Web安全

1. XSS攻擊

XSS(Cross-Site Scripting,跨站腳本攻擊)是一種代碼注入攻擊。攻擊者在目标網站上注入惡意代碼,當被攻擊者登陸網站時就會執行這些惡意代碼,這些腳本可以讀取 cookie,session tokens,或者其它敏感的網站資訊,對使用者進行釣魚欺詐,甚至發起蠕蟲攻擊等。

XSS 的本質是:惡意代碼未經過濾,與網站正常的代碼混在一起;浏覽器無法分辨哪些腳本是可信的,導緻惡意腳本被執行。由于直接在使用者的終端執行,惡意代碼能夠直接擷取使用者的資訊,利用這些資訊冒充使用者向網站發起攻擊者定義的請求。

XSS分類

根據攻擊的來源,XSS攻擊可以分為存儲型(持久性)、反射型(非持久型)和DOM型三種。下面我們來詳細了解一下這三種XSS攻擊:

1.1 反射型XSS

當使用者點選一個惡意連結,或者送出一個表單,或者進入一個惡意網站時,注入腳本進入被攻擊者的網站。Web伺服器将注入腳本,比如一個錯誤資訊,搜尋結果等,未進行過濾直接傳回到使用者的浏覽器上。

反射型 XSS 的攻擊步驟:
  1. 攻擊者構造出特殊的 

    URL

    ,其中包含惡意代碼。
  2. 使用者打開帶有惡意代碼的 

    URL

     時,網站服務端将惡意代碼從 

    URL

     中取出,拼接在 HTML 中傳回給浏覽器。
  3. 使用者浏覽器接收到響應後解析執行,混在其中的惡意代碼也被執行。
  4. 惡意代碼竊取使用者資料并發送到攻擊者的網站,或者冒充使用者的行為,調用目标網站接口執行攻擊者指定的操作。

反射型 XSS 漏洞常見于通過 

URL

 傳遞參數的功能,如網站搜尋、跳轉等。由于需要使用者主動打開惡意的 

URL

 才能生效,攻擊者往往會結合多種手段誘導使用者點選。

POST 的内容也可以觸發反射型 XSS,隻不過其觸發條件比較苛刻(需要構造表單送出頁面,并引導使用者點選),是以非常少見。

檢視反射型攻擊示例

請戳: https://github.com/YvetteLau/Blog/tree/master/Security

根據 

README.md

 的提示進行操作(真實情況下是需要誘導使用者點選的,上述代碼僅是用作示範)。

注意 

Chrome

 和 

Safari

 能夠檢測到 

url

 上的xss攻擊,将網頁攔截掉,但是其它浏覽器不行,如 

Firefox

如果不希望被前端拿到cookie,後端可以設定 

httpOnly

 (不過這不是 

XSS攻擊

 的解決方案,隻能降低受損範圍)

如何防範反射型XSS攻擊

對字元串進行編碼。

對url的查詢參數進行轉義後再輸出到頁面。

app.get('/welcome', function(req, res) {	
    //對查詢參數進行編碼,避免反射型 XSS攻擊	
    res.send(`${encodeURIComponent(req.query.type)}`); 	
});
           

1.2 DOM 型 XSS

DOM 型 XSS 攻擊,實際上就是前端 

JavaScript

 代碼不夠嚴謹,把不可信的内容插入到了頁面。在使用 

.innerHTML

、 

.outerHTML

、 

.appendChild

、 

document.write()

等API時要特别小心,不要把不可信的資料作為 HTML 插到頁面上,盡量使用 

.innerText

、 

.textContent

、 

.setAttribute()

 等。

DOM 型 XSS 的攻擊步驟:
  1. 攻擊者構造出特殊資料,其中包含惡意代碼。
  2. 使用者浏覽器執行了惡意代碼。
  3. 惡意代碼竊取使用者資料并發送到攻擊者的網站,或者冒充使用者的行為,調用目标網站接口執行攻擊者指定的操作。
如何防範 DOM 型 XSS 攻擊

防範 DOM 型 XSS 攻擊的核心就是對輸入内容進行轉義(DOM 中的内聯事件監聽器和連結跳轉都能把字元串作為代碼運作,需要對其内容進行檢查)。

1.對于 

url

連結(例如圖檔的 

src

屬性),那麼直接使用 

encodeURIComponent

 來轉義。

2.非 

url

,我們可以這樣進行編碼:

function encodeHtml(str) {	
    return str.replace(/"/g, '"')	
            .replace(/'/g, ''')	
            .replace(/</g, '&lt;')	
            .replace(/>/g, '&gt;');	
}
           

DOM 型 XSS 攻擊中,取出和執行惡意代碼由浏覽器端完成,屬于前端 JavaScript 自身的安全漏洞。

檢視DOM型XSS攻擊示例(根據readme提示檢視)

請戳: https://github.com/YvetteLau/Blog/tree/master/Security

1.3 存儲型XSS

惡意腳本永久存儲在目标伺服器上。當浏覽器請求資料時,腳本從伺服器傳回并執行,影響範圍比反射型和DOM型XSS更大。存儲型XSS攻擊的原因仍然是沒有做好資料過濾:前端送出資料至服務端時,沒有做好過濾;服務端在接受到資料時,在存儲之前,沒有做過濾;前端從服務端請求到資料,沒有過濾輸出。

存儲型 XSS 的攻擊步驟:
  1. 攻擊者将惡意代碼送出到目标網站的資料庫中。
  2. 使用者打開目标網站時,網站服務端将惡意代碼從資料庫取出,拼接在 HTML 中傳回給浏覽器。
  3. 使用者浏覽器接收到響應後解析執行,混在其中的惡意代碼也被執行。
  4. 惡意代碼竊取使用者資料并發送到攻擊者的網站,或者冒充使用者的行為,調用目标網站接口執行攻擊者指定的操作。

這種攻擊常見于帶有使用者儲存資料的網站功能,如論壇發帖、商品評論、使用者私信等。

如何防範存儲型XSS攻擊:
  1. 前端資料傳遞給伺服器之前,先轉義/過濾(防範不了抓包修改資料的情況)
  2. 伺服器接收到資料,在存儲到資料庫之前,進行轉義/過濾
  3. 前端接收到伺服器傳遞過來的資料,在展示到頁面前,先進行轉義/過濾
檢視存儲型XSS攻擊示例(根據Readme提示檢視)

請戳: https://github.com/YvetteLau/Blog/tree/master/Security

除了謹慎的轉義,我們還需要其他一些手段來防範XSS攻擊:

1.Content Security Policy

在服務端使用 HTTP的 

Content-Security-Policy

 頭部來指定政策,或者在前端設定 

meta

 标簽。

例如下面的配置隻允許加載同域下的資源:

Content-Security-Policy: default-src 'self'
           
<meta http-equiv="Content-Security-Policy" content="form-action 'self';">
           

前端和服務端設定 CSP 的效果相同,但是 

meta

無法使用 

report

更多的設定可以檢視 Content-Security-Policy

嚴格的 CSP 在 XSS 的防範中可以起到以下的作用:

  1. 禁止加載外域代碼,防止複雜的攻擊邏輯。
  2. 禁止外域送出,網站被攻擊後,使用者的資料不會洩露到外域。
  3. 禁止内聯腳本執行(規則較嚴格,目前發現 GitHub 使用)。
  4. 禁止未授權的腳本執行(新特性,Google Map 移動版在使用)。
  5. 合理使用上報可以及時發現 XSS,利于盡快修複問題。

2.輸入内容長度控制

對于不受信任的輸入,都應該限定一個合理的長度。雖然無法完全防止 XSS 發生,但可以增加 XSS 攻擊的難度。

3.輸入内容限制

對于部分輸入,可以限定不能包含特殊字元或者僅能輸入數字等。

4.其他安全措施

  • HTTP-only Cookie: 禁止 JavaScript 讀取某些敏感 Cookie,攻擊者完成 XSS 注入後也無法竊取此 Cookie。
  • 驗證碼:防止腳本冒充使用者送出危險操作。

1.4 XSS 檢測

讀到這兒,相信大家已經知道了什麼是XSS攻擊,XSS攻擊的類型,以及如何去防範XSS攻擊。但是有一個非常重要的問題是:我們如何去檢測XSS攻擊,怎麼知道自己的頁面是否存在XSS漏洞?

很多大公司,都有專門的安全部門負責這個工作,但是如果沒有安全部門,作為開發者本身,該如何去檢測呢?

1.使用通用 XSS 攻擊字串手動檢測 XSS 漏洞

如: 

jaVasCript:(oNcliCk=alert())//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e

能夠檢測到存在于 HTML 屬性、HTML 文字内容、HTML 注釋、跳轉連結、内聯 JavaScript 字元串、内聯 CSS 樣式表等多種上下文中的 XSS 漏洞,也能檢測 eval()、setTimeout()、setInterval()、Function()、innerHTML、document.write() 等 DOM 型 XSS 漏洞,并且能繞過一些 XSS 過濾器。

<imgsrc=1onerror=alert(1)>

2.使用第三方工具進行掃描(詳見最後一個章節)

【面試篇】寒冬求職之你必須要懂的Web安全

2. CSRF

CSRF(Cross-site request forgery)跨站請求僞造:攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站發送跨站請求。利用受害者在被攻擊網站已經擷取的注冊憑證,繞過背景的使用者驗證,達到冒充使用者對被攻擊的網站執行某項操作的目的。

典型的CSRF攻擊流程:
  1. 受害者登入A站點,并保留了登入憑證(Cookie)。
  2. 攻擊者誘導受害者通路了站點B。
  3. 站點B向站點A發送了一個請求,浏覽器會預設攜帶站點A的Cookie資訊。
  4. 站點A接收到請求後,對請求進行驗證,并确認是受害者的憑證,誤以為是無辜的受害者發送的請求。
  5. 站點A以受害者的名義執行了站點B的請求。
  6. 攻擊完成,攻擊者在受害者不知情的情況下,冒充受害者完成了攻擊。

一圖勝千言:

【面試篇】寒冬求職之你必須要懂的Web安全
CSRF的特點

1.攻擊通常在第三方網站發起,如圖上的站點B,站點A無法防止攻擊發生。

2.攻擊利用受害者在被攻擊網站的登入憑證,冒充受害者送出操作;并不會去擷取cookie資訊(cookie有同源政策)

3.跨站請求可以用各種方式:圖檔URL、超連結、CORS、Form送出等等(來源不明的連結,不要點選)

運作代碼,更直覺了解一下

使用者 loki 銀行存款 10W。

使用者 yvette 銀行存款 1000。

我們來看看 yvette 如何通過 

CSRF

 攻擊,将 loki 的錢偷偷轉到自己的賬戶中,并根據提示,檢視如何去防禦CSRF攻擊。

【面試篇】寒冬求職之你必須要懂的Web安全

請戳: https://github.com/YvetteLau/Blog/tree/master/Security [根據readme中的CSRF部分進行操作]

CSRF 攻擊防禦

1. 添加驗證碼(體驗不好)

驗證碼能夠防禦CSRF攻擊,但是我們不可能每一次互動都需要驗證碼,否則使用者的體驗會非常差,但是我們可以在轉賬,交易等操作時,增加驗證碼,確定我們的賬戶安全。

2. 判斷請求的來源:檢測Referer(并不安全,Referer可以被更改)

`Referer` 可以作為一種輔助手段,來判斷請求的來源是否是安全的,但是鑒于 `Referer` 本身是可以被修改的,因為不能僅依賴于  `Referer`
           

3. 使用Token(主流)

CSRF攻擊之是以能夠成功,是因為伺服器誤把攻擊者發送的請求當成了使用者自己的請求。那麼我們可以要求所有的使用者請求都攜帶一個CSRF攻擊者無法擷取到的Token。伺服器通過校驗請求是否攜帶正确的Token,來把正常的請求和攻擊的請求區分開。跟驗證碼類似,隻是使用者無感覺。	
- 服務端給使用者生成一個token,加密後傳遞給使用者	
- 使用者在送出請求時,需要攜帶這個token	
- 服務端驗證token是否正确
           

4. Samesite Cookie屬性

為了從源頭上解決這個問題,Google起草了一份草案來改進HTTP協定,為Set-Cookie響應頭新增Samesite屬性,它用來标明這個 Cookie是個“同站 Cookie”,同站Cookie隻能作為第一方Cookie,不能作為第三方Cookie,Samesite 有兩個屬性值,分别是 Strict 和 Lax。

部署簡單,并能有效防禦CSRF攻擊,但是存在相容性問題。

Samesite=Strict

Samesite=Strict

 被稱為是嚴格模式,表明這個 Cookie 在任何情況都不可能作為第三方的 Cookie,有能力阻止所有CSRF攻擊。此時,我們在B站點下發起對A站點的任何請求,A站點的 Cookie 都不會包含在cookie請求頭中。

**Samesite=Lax**	
`Samesite=Lax` 被稱為是寬松模式,與 Strict 相比,放寬了限制,允許發送安全 HTTP 方法帶上 Cookie,如 `Get` / `OPTIONS` 、`HEAD` 請求.	
但是不安全 HTTP 方法,如: `POST`, `PUT`, `DELETE` 請求時,不能作為第三方連結的 Cookie
           

為了更好的防禦CSRF攻擊,我們可以組合使用以上防禦手段。

3. 點選劫持

點選劫持是指在一個Web頁面中隐藏了一個透明的iframe,用外層假頁面誘導使用者點選,實際上是在隐藏的frame上觸發了點選事件進行一些使用者不知情的操作。

典型點選劫持攻擊流程

  1. 攻擊者建構了一個非常有吸引力的網頁【不知道哪些内容對你們來說有吸引力,我就不寫頁面了,偷個懶】
  2. 将被攻擊的頁面放置在目前頁面的 

    iframe

     中
  3. 使用樣式将 iframe 疊加到非常有吸引力内容的上方
  4. 将iframe設定為100%透明
  5. 你被誘導點選了網頁内容,你以為你點選的是*,而實際上,你成功被攻擊了。

點選劫持防禦

1. frame busting

Frame busting

if ( top.location != window.location ){	
    top.location = window.location	
}
           

需要注意的是: HTML5中iframe的 

sandbox

 屬性、IE中iframe的 

security

 屬性等,都可以限制iframe頁面中的JavaScript腳本執行,進而可以使得 frame busting 失效。

2. X-Frame-Options

X-FRAME-OPTIONS是微軟提出的一個http頭,專門用來防禦利用iframe嵌套的點選劫持攻擊。并且在IE8、Firefox3.6、Chrome4以上的版本均能很好的支援。

可以設定為以下值:

DENY: 拒絕任何域加載

SAMEORIGIN: 允許同源域下加載

ALLOW-FROM: 可以定義允許frame加載的頁面位址

安全掃描工具

上面我們介紹了幾種常見的前端安全漏洞,也了解一些防範措施,那麼我們如何發現自己網站的安全問題呢?沒有安全部門的公司可以考慮下面幾款開源掃碼工具:

1. Arachni

Arachni是基于Ruby的開源,功能全面,高性能的漏洞掃描架構,Arachni提供簡單快捷的掃描方式,隻需要輸入目标網站的網址即可開始掃描。它可以通過分析在掃描過程中獲得的資訊,來評估漏洞識别的準确性和避免誤判。

Arachni預設內建大量的檢測工具,可以實施 代碼注入、CSRF、檔案包含檢測、SQL注入、指令行注入、路徑周遊等各種攻擊。

同時,它還提供了各種插件,可以實作表單爆破、HTTP爆破、防火牆探測等功能。

針對大型網站,該工具支援會話保持、浏覽器叢集、快照等功能,幫助使用者更好實施滲透測試。

2. Mozilla HTTP Observatory

Mozilla HTTP Observatory,是Mozilla最近釋出的一款名為Observatory的網站安全分析工具,意在鼓勵開發者和系統管理者增強自己網站的安全配置。用法非常簡單:輸入網站URL,即可通路并分析網站HTTP标頭,随後可針對網站安全性提供數字形式的分數和字母代表的安全級别。

檢查的主要範圍包括:
  • Cookie
  • 跨源資源共享(CORS)
  • 内容安全政策(CSP)
  • HTTP公鑰固定(Public Key Pinning)
  • HTTP嚴格安全傳輸(HSTS)狀态
  • 是否存在HTTP到HTTPs的自動重定向
  • 子資源完整性(Subresource Integrity)
  • X-Frame-Options
  • X-XSS-Protection

3. w3af

W3af是一個基于Python的Web應用安全掃描器。可幫助開發人員,有助于開發人員和測試人員識别Web應用程式中的漏洞。

掃描器能夠識别200多個漏洞,包括跨站點腳本、SQL注入和作業系統指令。

關注小姐姐的公衆号,和小姐姐一起學前端。
【面試篇】寒冬求職之你必須要懂的Web安全

後續寫作計劃(寫作順序不定)

1.《寒冬求職季之你必須要懂的原生JS》(下)

2.《寒冬求職季之你必須要知道的CSS》

3.《寒冬求職季之你必須要懂的一些浏覽器知識》

4.《寒冬求職季之你必須要知道的性能優化》

5.《寒冬求職季之你必須要懂的webpack原理》

針對React技術棧:

1.《寒冬求職季之你必須要懂的React》系列

2.《寒冬求職季之你必須要懂的ReactNative》系列

【面試篇】寒冬求職之你必須要懂的Web安全

編寫本文,雖然花費了很多時間,但是在這個過程中,我也學習到了很多知識,謝謝各位小夥伴願意花費寶貴的時間閱讀本文,如果本文給了您一點幫助或者是啟發,請不要吝啬你的贊和Star,您的肯定是我前進的最大動力。https://github.com/YvetteLau/Blog

參考文章:

[1] 如何防止CSRF攻擊?

[2] 談談對 Web 安全的了解

[3] 程式員必須要了解的web安全

[4] Cookie的SameSite屬性

[5] https://github.com/OWASP/CheatSheetSeries