關於Web安全的問題,是一個老生常談的問題,作為離使用者最近的一層,我們大前端應該把手伸的更遠一點。
我們最常見的Web安全攻擊有以下幾種:
XSS
跨站指令碼攻擊CSRF
跨站請求偽造ClickJacking
點選劫持/UI-覆蓋攻擊SQL Injection
SQL隱碼攻擊
一、XSS
XSS (Cross Site Script),中文是跨站指令碼攻擊;其原本縮寫是 CSS,但為了和層疊樣式表(Cascading Style Sheet)有所區分,因而在安全領域叫做 XSS。
惡意攻擊者往Web頁面裡插入惡意Script程式碼,當使用者瀏覽該頁之時,嵌入其中Web裡面的Script程式碼會被執行,從而達到惡意攻擊使用者的目的。
XSS攻擊可以分為3類:
- 反射型 - 非持久型
Reflected XSS
- 儲存型 - 持久型
Stored XSS
- 基於DOM或本地的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 開發中最常見的一種安全漏洞。可以用它來從資料庫獲取敏感資訊,或者利用資料庫的特性執行新增使用者,匯出檔案等一系列惡意操作,甚至有可能獲取資料庫乃至系統使用者最高許可權。
1. 原理
SQL隱碼攻擊指的是通過構建特殊的輸入作為引數傳入Web應用程式,而這些輸入大都是SQL語法裡的一些組合,通過執行SQL語句進而執行攻擊者所要的操作,其主要原因是程式沒有細緻地過濾使用者輸入的資料,致使非法資料侵入系統。
根據相關技術原理,SQL隱碼攻擊可以分為平臺層注入和程式碼層注入。前者由不安全的資料庫配置或資料庫平臺的漏洞所致;後者主要是由於程式設計師對輸入未進行細緻地過濾,從而執行了非法的資料查詢。基於此,SQL隱碼攻擊的產生原因通常表現在以下幾方面:
① 不當的型別處理;
② 不安全的資料庫配置;
③ 不合理的查詢集處理;
④ 不當的錯誤處理;
⑤ 轉義字元處理不合適;
⑥ 多個提交處理不當。
2. 攻擊
當應用程式使用輸入內容來構造動態sql語句以訪問資料庫時,會發生sql注入攻擊。如果程式碼使用儲存過程,而這些儲存過程作為包含未篩選的使用者輸入的字串來傳遞,也會發生sql注入。sql注入可能導致攻擊者使用應用程式登陸在資料庫中執行命令。相關的SQL隱碼攻擊可以通過測試工具pangolin進行。
3. 防護
① 永遠不要信任使用者的輸入。對使用者的輸入進行校驗,可以通過正規表示式,或限制長度;對單引號和雙"-"進行轉換等。
② 永遠不要使用動態拼裝sql,可以使用引數化的sql或者直接使用存詢存取。
③ 永遠不要使用管理員許可權的資料庫連線,為每個應用使用單獨的許可權有限的資料庫連線。
④ 不要把機密資訊直接存放,加密或者hash掉密碼和敏感的資訊。
⑤ 應用的異常資訊應該給出儘可能少的提示,最好使用自定義的錯誤資訊對原始錯誤資訊進行包裝
⑥ sql注入的檢測方法一般採取輔助軟體或網站平臺來檢測,軟體一般採用sql注入檢測工具jsky,網站平臺就有億思網站安全平臺檢測工具MDCSOFT SCAN等。採用MDCSOFT-IPS可以有效的防禦SQL隱碼攻擊,XSS攻擊等。
更多文章在我的個人部落格www.williamife.com等你喲~
Thanks.