關於Web安全常見的攻防姿勢
關於Web安全的問題,是一個老生常談的問題,作為離使用者最近的一層,我們大前端應該把手伸的更遠一點。
我們最常見的Web安全攻擊有以下幾種:
XSS CSRF ClickJacking SQL Injection
一、XSS
XSS (Cross Site Script),中文是跨站指令碼攻擊;其原本縮寫是 CSS,但為了和層疊樣式表(Cascading Style Sheet)有所區分,因而在安全領域叫做 XSS。
惡意攻擊者往Web頁面裡插入惡意Script程式碼,當用戶瀏覽該頁之時,嵌入其中Web裡面的Script程式碼會被執行,從而達到惡意攻擊使用者的目的。
XSS攻擊可以分為3類:
Reflected XSS Stored XSS DOM-based or local XSS
1. 反射型
反射型 XSS 只是簡單地把使用者輸入的資料 “反射” 給瀏覽器,這種攻擊方式往往需要攻擊者誘使使用者點選一個惡意連結,或者提交一個表單,或者進入一個惡意網站時,注入指令碼進入被攻擊者的網站。
假裝我是一個惡意連結(Click Me~)
const http = require('http'); // 啟http服務 const server = http.createServer(function (req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.writeHead(200, {'Content-Type': 'text/html; charset=UTF-8'}); res.write('<script>while(true)alert("反射型 XSS 攻擊")</script>'); res.end(); }); server.listen('8000'); 複製程式碼
這樣就產生了反射型 XSS 攻擊。攻擊者可以注入任意的惡意指令碼進行攻擊,可能注入惡作劇指令碼,或者注入能獲取使用者隱私資料(如cookie)的指令碼,這取決於攻擊者的目的。
2.儲存型
儲存型 XSS 會把使用者輸入的資料 "儲存" 在伺服器端,當瀏覽器請求資料時,指令碼從伺服器上傳回並執行。這種 XSS 攻擊具有很強的穩定性。
比較常見的一個場景是攻擊者在社群或論壇上寫下一篇包含惡意 JavaScript 程式碼的文章或評論,文章或評論發表後,所有訪問該文章或評論的使用者,都會在他們的瀏覽器中執行這段惡意的 JavaScript 程式碼。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>儲存型 XSS</title> </head> <body> <div>Try Me:<input type="text" id="input"></div> <button id="btn">Submit</button> <script> const input = document.getElementById('input'); const btn = document.getElementById('btn'); let val; input.addEventListener('change', e => { val = e.target.value; }, false); btn.addEventListener('click', e => { fetch('http://localhost:8000/save', { method: 'POST', body: val }); }, false); </script> </body> </html> 複製程式碼
const http = require('http'); let userInput = ''; function handleReequest (req, res) { const method = req.method; res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type') if (method === 'POST' && req.url === '/save') { let body = ''; req.on('data', chunk => { body += chunk; }); req.on('end', () => { if (body) { userInput = body; } res.end(); }); } else { res.writeHead(200, { 'Content-Type': 'text/html; charset=UTF-8' }); res.write(userInput); res.end(); } } // 啟http服務 const server = http.createServer((req, res)=> { handleReequest(req, res) }); server.listen('8000'); 複製程式碼
3.基於DOM
基於DOM或本地的XSS其實是一種特殊型別的反射型XSS,它是基於DOM文件物件模型的一種漏洞。可以通過DOM來動態修改頁面內容,從客戶端獲取DOM中的資料並在本地執行。基於這個特性,就可以利用JS指令碼來實現XSS漏洞的利用。
<body> <input type="text" id="input"> <button id="btn">Submit</button> <div id="div"></div> <script> const input = document.getElementById('input'); const btn = document.getElementById('btn'); const div = document.getElementById('div'); let val; input.addEventListener('change', (e) => { val = e.target.value; }, false); btn.addEventListener('click', () => { div.innerHTML = `<a href=${val}>Try Me~</a>` }, false); </script> </body> 複製程式碼
總結:XSS攻擊的本質就是,利用一切手段在目標使用者的瀏覽器中執行攻擊指令碼。
防範:對於一切使用者的輸入、輸出、客戶端的輸出內容視為不可信,在資料新增到DOM或者執行了DOM API的時候,我們需要對內容進行HtmlEncode或JavaScriptEncode,以預防XSS攻擊。
現在主流的瀏覽器內建了防範 XSS 的措施,例如內容安全策略(CSP)。但對於開發者來說,也應該尋找可靠的解決方案來防止 XSS 攻擊。
二、CSRF
CSRF(Cross-site request forgery)跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。
通常情況下,CSRF 攻擊是攻擊者藉助受害者的 Cookie 騙取伺服器的信任,可以在受害者毫不知情的情況下以受害者名義偽造請求傳送給受攻擊伺服器,從而在並未授權的情況下執行在許可權保護之下的操作。
關於瀏覽器的Cookie策略請參考HTTP Cookie。
1. 通過 Cookie 進行 CSRF 攻擊
假設有一個BBS站點http://www.a.com
:
-
當用戶登入之後,會設定如下 cookie:
res.setHeader('Set-Cookie', ['user=william; expires=Fri, 23 Mar 2019 00:00:00 GMT;'])
-
當登入後的使用者發起
http://www.a.com/delete?id=666666
請求時,會刪除 id 為 666666 的帖子。 -
CSRF攻擊者準備的網站B:
<img src="http://www.a.com/delete?id=666666">
-
當登入使用者訪問攻擊者的網站B時,會向
www.a.com
發起一個刪除使用者帖子的請求。此時若使用者在切換到www.a.com
的帖子頁面重新整理,會發現ID 為 666666 的帖子已經被刪除。
要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:
- 登入受信任網站A,並在本地生成Cookie。
- 在不登出A的情況下,訪問危險網站B。
2. CSRF攻擊的防範
1.驗證 HTTP Referer 欄位 2.新增 token 驗證 3.驗證碼 複製程式碼
儘管CSRF聽起來像跨站指令碼(XSS),但它與XSS非常不同,XSS利用站點內的信任使用者,而CSRF則通過偽裝來自受信任使用者的請求來利用受信任的網站。
與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防範的資源也相當稀少)和難以防範,所以被認為比XSS更具危險性,往往同XSS一同作案!
三、ClickJacking
ClickJacking點選劫持,也叫UI覆蓋攻擊,攻擊者會利用一個或多個透明或不透明的層來誘騙使用者支援點選按鈕的操作,而實際的點選確實使用者看不到的一個按鈕,從而達到在使用者不知情的情況下實施攻擊。
1. iframe覆蓋
這種攻擊方式的關鍵在於可以實現頁中頁的<iframe>
標籤,並且可以使用css樣式表將他不可見。
防止點選劫持有兩種主要方法:
-
X-FRAME-OPTIONS X-FRAME-OPTIONS是微軟提出的一個http響應首部,指示瀏覽器不允許從其他域進行取景,專門用來防禦利用iframe巢狀的點選劫持攻擊。並且在IE8、Firefox3.6、Chrome4以上的版本均能很好的支援。
DENY
: 拒絕任何域載入SAMEORIGIN
: 允許同源域下載入ALLOW-FROM
: 可以定義允許frame載入的頁面地址 -
頂層判斷 在UI中採用防禦性程式碼,以確保當前幀是最頂層的視窗,如:
top != self || top.location != self.location || top.location != location
2. 圖片覆蓋
圖片覆蓋攻擊(Cross Site Image Overlaying),攻擊者使用一張或多張圖片,利用圖片的style或者能夠控制的CSS,將圖片覆蓋在網頁上,形成點選劫持。當然圖片本身所帶的資訊可能就帶有欺騙的含義,這樣不需要使用者點選,也能達到欺騙的目的。
<a href="http://www.a.com/delete?id=666666"> <img src="~~~" style="~~~" /> </a> 複製程式碼
解決方案: 在防禦圖片覆蓋攻擊時,需要檢查使用者提交的HTML程式碼中,img標籤的style屬性是否可能導致浮出。
四、SQL Injection
SQL 注入漏洞(SQL Injection)是 Web 開發中最常見的一種安全漏洞。可以用它來從資料庫獲取敏感資訊,或者利用資料庫的特性執行新增使用者,匯出檔案等一系列惡意操作,甚至有可能獲取資料庫乃至系統使用者最高許可權。
而造成 SQL 注入的原因是因為程式沒有有效的轉義過濾使用者的輸入,使攻擊者成功的向伺服器提交惡意的 SQL 查詢程式碼,程式在接收後錯誤的將攻擊者的輸入作為查詢語句的一部分執行,導致原始的查詢邏輯被改變,額外的執行了攻擊者精心構造的惡意程式碼。
很多 Web 開發者沒有意識到 SQL 查詢是可以被篡改的,從而把 SQL 查詢當作可信任的命令。殊不知,SQL 查詢是可以繞開訪問控制,從而繞過身份驗證和許可權檢查的。更有甚者,有可能通過 SQL 查詢去執行主機系統級的命令。
更多文章在我的個人部落格www.williamife.com等你喲~
Thanks.