本節課重點內容#
安全問題很常見,會危害
- 用戶
- 公司
- 程序員(祭天 QAQ)
兩個角度看 web 安全#
假如你是一個 hacker—— 攻擊#
跨站腳本攻擊 XSS (Cross Site Scripting)#
注入惡意腳本,完成攻擊,後果:洩露用戶隱私等
XSS 主要利用了開發者對用戶提交內容的盲目信任
特點
- 通常難以從 UI 上感知(一般都是暗地裡執行腳本)
- 竊取用戶信息(cookie/token) - 繪製 UI(如彈窗等),誘騙用戶點擊 / 填寫表單
舉個栗子
public async submit(ctx) {
const {content, id} = ctx.request.body;
await db.save({
content, // 沒有對content進行過濾!!
id
});
}
public async render(ctx) {
const { content } = await db.query({
id: ctx.query.id
});
// 沒有對content進行過濾!!
ctx.body = `<div>${content}</div>`;
}
可以看到上述代碼,壓根沒有對用戶輸入的 content 內容進行任何過濾。這個時候就可以提交一個<script>alert('xss');</script>
腳本,進行攻擊
xss 攻擊也分幾大類:Store XSS、Reflected XSS、DOM-based XSS、Mutation-based XSS
Store XSS#
- 提交的惡意腳本被存在數據庫中
- 訪問頁面 -> 讀數據 == 被攻擊
- 危害最大,對全部用戶可見
- 如:某個視頻網站,上傳了惡意腳本被存到數據庫中,從此電商網站上便多了一個視頻共享賬戶。
Reflected XSS#
-
不涉及數據庫
-
從 URL 上攻擊,在 URL 上帶上腳本
DOM-based XSS#
-
不需要服務器的參與
-
惡意攻擊的發起 + 執行,全在瀏覽器完成
-
完成注入腳本的地方,是由瀏覽器來的,這是它與 Reflected XSS 的不同之處
Mutation-based XSS#
-
一個巧妙地攻擊方式,利用瀏覽器的特性
如果用戶所提供的富文本內容通過 javascript 代碼進入 innerHTML 屬性後,一些意外的變化會使得這個認定不再成立:瀏覽器的渲染引擎會將本來沒有任何危害的 HTML 代碼渲染成具有潛在危險的 XSS 攻擊代碼。
-
巧妙,最難防禦的一種方式,攻擊者非常的懂瀏覽器
Cross-site request forgery(CSRF,跨站偽造請求)#
-
在用戶不知情的前提下
-
利用用戶權限(cookie)
-
構造指定 HTTP 請求,進而竊取或修改用戶敏感信息
一個用戶訪問了一個惡意的頁面,這個頁面向銀行發送一個轉賬請求,ServerA 為銀行的服務器,發現這個請求帶有用戶的 cookie,成功
CSRF 通過偽裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF 攻擊往往不大流行(因此對其進行防範的資源也相當稀少)和難以防範,所以被認為比XSS
更具危險性
。
Injection(注入)#
-
SQL 注入:通過 SQL 參數進行注入
案例:讀取請求字段,直接以字符串的形式拼接 SQL 語句
public async rederForm(ctx) { const {username, form_id } = ctx.query; const result = await sql.query(` SELECT a, b, c FROM table WHERE username = ${username} AND form_id = ${form_id} `); ctx.body = renderForm(result); }
那麼攻擊者可以傳入一個 userName:
any; DROP TABLE table;
,於是被動刪庫跑路成就達成√ -
命令行注入等
-
讀取 + 改進流量攻擊
Denial of Service(DOS)攻擊#
-
通過某種方式 (構造特定請求),導致服務器資源被顯著消耗,
-
來不及響應更多請求,導致請求擠壓,進而雪崩效應。
-
拓展:正則表達式 —— 貪婪模式
- 重複匹配時,
?
/no ?
:滿足”一個即可“
/盡可能多
- 重複匹配時,
-
例子:ReDoS: 基於正則表達式的 DoS
-
貪婪:n 次不行?n-1 次再試試?—— 回溯
-
Distributed Dos (DDOS)
-
短時間內,來自大量殭屍設備的請求流量,服務器不能及時完成全部請求,導致請求堆積,進而雪崩效應,無法響應新請求。(量大就完事兒了)
-
特點:
-
直接訪問 IP
-
任意 API
-
消耗大量帶寬(耗盡)
-
-
中間人攻擊(傳輸層)#
-
明文傳輸
-
信息篡改不可知
-
對方身份未驗證
假如你是一個開發者 —— 防禦#
XSS 攻擊防禦#
-
永遠不要信任用戶的提交內容
- 不要將用戶的提交內容直接轉換成 DOM
-
現成工具
- 主流框架默認防禦 XSS(react 等)
- google-closure-library
- 服務端:DOMPurify
-
用戶需求:不講武德,必須動態生成 DOM?
-
new DOMParser();
-
svg:也要掃描,因為其中也可以插入 script 標籤
-
不要用戶自定義跳轉鏈接(或者做好過濾)!
<a href="javascript:alert('xss')"></a>
-
-
自定義樣式也要留意
同源策略(CSP)#
- 協議
- 域名
- 端口
任意一者不同,跨域 ×
瀏覽器的同源策略 - Web 安全 | MDN (mozilla.org)
一般的同源請求都是沒有問題的,而跨域的不行,CSP 允許開發者定義
- 哪些源(域名)是被認為是安全的
- 來自安全源的腳本可以被執行,否則直接拋錯
- 對 eval + inline script 直接拒絕
- 設置
- 服務器的響應頭部
Content-Security-Policy: script-src 'self'; // 同源 Content-Security-Policy: script-src 'self' https://domain.com
- 瀏覽器的響應頭部
<meta http-equiv=" Content-Security-Policy" content="script-src self">
CSRF 攻擊防禦#
-
Origin + Referrer
-
其他判斷【請求來自於合法來源】的方式
- 先有頁面,後有請求
- if 請求來自合法頁面
- then 服務器接受過頁面請求
- then 服務器可以標識
- 先有頁面,後有請求
-
-
iframe 攻擊:限制 Origin 是吧,那我同源請求
-
避免 GET + POST 一起請求,攻擊者一石二鳥!
// 不要像下面這樣將更新+獲取邏輯放到同一個GET接口 public async getAndUpdate(ctx) { const { update, id } = ctx.query; if (update) { await this.update(update); } ctx.body = await this.get(id); }
-
SameSite Cookie
-
限制 Cookie domain
-
頁面域名是否匹配
-
依賴 cookie 的第三方服務怎麼辦?
內嵌一個 X 站播放器,識別不了用戶登錄態,發不了彈幕
Set-Cookie: SameSite=None; Secure ;
-
-
SameSite vs CORS(跨站資源共享)
以上這麼多防禦 CSRF 的方法,那麼什麼是防禦 CSRF 的正確姿勢呢?寫一個中間件,專門生成這方面的防禦。
Injection 防禦#
-
找到項目中查詢 SQL 的地方
-
使用 prepared statement
PREPARE q FROM 'SELECT user FROM users WHERE gender = ?'; SET @gender = 'female'; EXECUTE q USING @gender; DEALLOCATE PREPARE q;
-
最小權限原則
- 所有命令都不要用 sodo || root ×
-
建立允許名單 + 過濾
- rm 堅決拒絕
-
對 URL 類型參數進行協議、域名、ip 等限制
- 避免攻擊者訪問內網
防禦 DoS#
- Code Review (避免貪婪匹配等)
- 代碼掃描 + 正則性能測試
- 避免用戶提供的使用正則
防禦 DDos#
傳輸層 —— 防禦中間人#
搬出大名鼎鼎的 HTTPS
- 可靠性:加密
- 完整性:MAC 驗證
- 不可抵賴性:數字簽名
-
拓展:數字簽名
-
私鑰(自己藏好)
-
公鑰(公開可見)
-
CA:Certificate Authority 證書機構
-
數字簽名,瀏覽器內置 CA 公鑰
-
- 當簽名算法不夠健壯時:被暴力破解(現在都已比較完善)
HTTP Strict-Transport-Security(HSTS)
- 將 HTTP 主動升級到 HTTPS
靜態資源被劫持篡改?對比 hash
尾聲#
- 安全無小事
- 使用的依賴 (npm package, 甚至是 NodeJS) 可能成為最薄弱的一環
- 保持學習心態
總結感想#
這節課老師圖文並茂的講解了 Web 安全相關的很多知識,非常有意思,包括 Web 攻擊的種類、防禦方式等
本文引用的內容大部分來自劉宇晨老師的課、MDN、外部博客引用:這一次,徹底理解 XSS 攻擊、淺談 CSRF