---
# System prepended metadata

title: 前端理解資料安全

---

# 前端理解資料安全
> keyword : SQL Injection、XSS、CSRF

**本文作者學習筆記網站：https://dev.rraiy.cc/**


資安是一個網站非常重要的議題，前後端都要了解並盡量做足。

---
## SQL Injection
對資料庫進行攻擊 - 使用者輸入的字串內容帶入 SQL 相關查詢語句時，若沒有過濾非法字元，使得字串成為 SQL 語句的一部分，讓攻擊者能任意操控資料庫的動作。

### 常見的手法
:::warning
使用者登入攻擊 - 不要輕易相信使用者輸入的資料
:::
```sql=
// 一個正常的登入表單語法驗證
SELECT * FROM users WHERE email = `${email}` AND password = `${password}`
// 被惡意攻擊 密碼帶入 'or 1=1 --
// 會變成下圖狀況
```
![](https://i.imgur.com/zusVwJV.png)
首先「’」單引號的作用是將 password 的 input 方塊內容關閉，接下來 or 1=1 因為恆正，所以都會回傳 true，最後的兩條橫槓則是將後方接著的 query 註解化，讓後面的指令不會執行，如此一來就算不知道正確密碼的狀況下，攻擊者仍然可以取得 Kyle 的個人訊息，甚至也可以因此登入成功 ，利用登入後的權限做更多惡意的行為（可想而知這隻帳號基本上就掛掉了）。這也就是常被稱為 Authorization Bypass 的 SQL Injection 攻擊。

除了上面這種取得不該被取得的資訊的攻擊以外，有的攻擊者也會利用字元漏洞直接注入可以改變資料庫資料的惡意 query，例如 DROP Table、或是 DELETE 資料等等，非常可怕

其他攻擊還有 注入 SQL 子語法 、 預存程序，之後有空再研究

### SQL Injection 防範方式

1. 預處理 （Prepared Statement），利用預處理提供的 bind value 或者 bind param 方法將參數值綁定，該參數值不會成為查詢語句的一部分。
2. 參數化查詢( ORM 框架都會處理這塊，所以大部分也推薦直接使用框架 )
3. RegEx - 驗證並過濾輸入值，將單引號改成雙引號
4. 特殊字符轉譯
5. 資料庫設定權限

## XSS（Cross-site scripting） 跨站指令碼攻擊
也稱為 JavaScript Injection

運作方式：
![](https://i.imgur.com/0otpMB1.png)

有心人士利用前端表單或者文本輸入框等，帶入`<script>`標籤將惡意腳本傳送到後端，之後其他正常使用者瀏覽網站時，後端會對其執行惡意腳本的內容，瀏覽器也不會知道這是惡意的因而執行，這些內容可能是獲取用戶的密碼、session token、cookie等操作。

### XSS 常見類型：( XSS 攻擊五花八門)
::: spoiler Stored XSS 儲存型 - 遭到被保存在伺服器資料庫中的 JavaScript 代碼引起的攻擊
把腳本存在後端資料庫中。
例如留言板網頁，若有人留言 `<script>alert(‘攻擊你！’)</script>`，每當其他用戶開啟留言板時，就會跑出這段 alert。
:::
:::spoiler Reflected XSS 反射型 - 網站反應使用者輸入的 URL（含 JavaScript 代碼）引起的攻擊
將 script 藏在 url ，發送 GET 請求時透過參數傳遞腳本
```
// 直接弄看起來很可疑
http://localhost:8080/reflected-xss-demos/?username='><script src='http://malicious-site.com/malicious.js'></script><a href='

// 因此大部分會重新編碼 掩耳盜鈴
http://localhost:8080/reflected-xss-demos/?username=%22%3E%3Cscript+src%3d%22http://malicious-site.com/malicious.js%22%3E%3C/script%3E%3Ca+href%3d%22
```
![](https://i.imgur.com/QRMG96M.png)

:::
::: spoiler DOM Based XSS - 網頁javascript在執行過程中，沒有詳細檢查資料使操作DOM的過程中帶入惡意的指令
主要是透過 innerHTML 來製造機會
![](https://i.imgur.com/OJk5rEe.png)
在 input 裡放入 `<img src=# onerror="alert(123)">` 就會執行 alert
通常 DOM XSS 會搭配前兩種來製造惡意內容，再用 DOM 運行惡意代碼

:::

### XSS 防範方式 
:::warning
重點：字串的輸出
:::

![](https://i.imgur.com/i1OVcmi.png)
* 盡可能過濾危險字元
  輸入通常擋不了，但還是可多做一層防護，要記得「輸出 encoding」比較重要。
  目前框架幾乎都有針對 XSS 做處理，我們所用的 React JSX 語法就會在渲染之  前把所有內容轉成字串。
* 除了 JS ，URL、HTML、CSS、XML 都可能成為被攻擊的對象，最好都做上「輸出 encoding」
- 請求表頭 Content-Type、X-Content-Type-Options，例如：json資料不該被解析為text/html
- 不要用 innerHTML 帶入使用者可以輸入的值，可以用 innerText


## CSRF （Cross Site Request Forgery） 跨站請求偽造
> 網站開發者越是相信瀏覽器，就容易受到攻擊
- 利用瀏覽器的 cookie 機制來攻擊，又稱 one-click attack
- cookie 的機制 → 只要發送任何請求，都會帶上該網域關聯的 cookie
- 不同 domain 下偽造出「本人發起請求」的假象

#### 運作方式
在 B 網站操作時，某按鈕點擊後卻是對 A 網站操作
```htmlmixed=
// 在 momobank 執行轉帳操作後，瀏覽器已經記住你所使用的 cookie
https://momobank.com/withdraw?account=you&amount=1000&for=Raiy

// 瀏覽別的網站時，可能放了一張圖片，該圖片的 src 卻是惡意請求
// 一打開網站就用圖片的 src 來攻擊 momobank，帶入先前的 cookie 把你的錢轉出來，只要 cookie 還沒過期就會成功執行
<img src="https://momobank.com/withdraw?account=you&amount=1000&for=hacker" />

// 另個例子 從 B 網站刪 A 網站的文章
<img src='https://small-min.blog.com/delete?id=3' width='0' height='0' />
```

### CSRF 防範方式
使用者端的防禦效果不彰，總不可能每次使用完功能就登出，對用戶來說非常不友善，pattern 能驗證的也有限，最基本還是從 server 端去避免。

cross site 代表著可以在任何網址下發動攻擊，所以追根究底必須阻擋來自不同 domain 的請求，那該怎麼判斷不同的 domain ？
:::spoiler 檢查 request header referer - 並不完善
referer 欄位會判斷請求從哪裡來
(!) but 某些瀏覽器沒有 referer、使用者可以自己關閉 referer 、要確保判定合法 domain 的程式邏輯沒有漏洞
:::
:::spoiler 加上圖形驗證或驗證碼機制 - 有用但使用者體驗不好
後端必須接收到正確的驗證才會執行該請求
雖然有用，但對一些重複度高的日常操作，使用者會煩死，例如刪除文章
:::
:::spoiler Double Submit Cookie - 似乎是目前的主流處理之一
**核心觀念：「攻擊者無法讀取目標網站的 cookie」**
讓 cookie 中跟 form 都存著一個 token，這兩個 token 會隨著請求發出一起送到後端，後端必須判定兩個 token 是否一樣才能繼續操作。
```htmlmixed=
Set-Cookie: csrftoken=fj1iro2jro12ijoi1

<form action="https://blog.com/delete" method="POST">
  <input type="hidden" name="id" value="3"/>
  <input type="hidden" name="csrftoken" value="fj1iro2jro12ijoi1"/>
  <input type="submit" value="刪除文章"/>
</form>
```
但在每個表單都設置隱藏的 token 有點麻煩，若為 SPA ，可以統一資訊放在 request header。
Axios 套件也能設定共用表頭。
:::
:::spoiler 加上 CSRF Token - 好方法之一 ，除了 origin * 的情況外
（許多 framework 如 django 內建都有提供 CSRF Token 的機制）
由後端生成隨機的 token 送到前端，前端藉由 js 取出並在發送請求時帶上該 token ，後端會判斷 token 是否一致，且每段 session 就要換一個 token。
但若網站的請求設置 * ，或者對惡意網站開通，那麼這方法沒用

:::
::: spoiler SameSite Cookie - 似乎是目前的主流處理之一
由瀏覽器來阻擋 CSRF ，這方法需要先理解 cookie 的同源政策
```htmlmixed=
Set-Cookie: session_id=ewfewjf23o1; // 原本的 cookie 設置
Set-Cookie: session_id=ewfewjf23o1; SameSite // 在後面加上即可

// SameSite 有三種模式，None、Lax跟Strict，默認是後者，你也可以自己指定模式：
Set-Cookie: session_id=ewfewjf23o1; SameSite=Strict
Set-Cookie: foo=bar; SameSite=Lax
```
**Strick 模式**：該cookie僅能在同網站被使用，任何跨域的請求都不可以加上
→ `<a href="">, <form>,` new XMLHttpRequest，只要是瀏覽器驗證不是在同一個 site 底下發出的 request，全部都不會帶上這個 cookie

**Lax 模式**：`<a>`, `<link rel="prerender">`, `<form method="GET"> `這些都還是會帶上 cookie。但是 POST 方法 的 form，或是只要是 POST, PUT, DELETE 這些方法，就不會帶上 cookie。但 Lax 模式之下就沒辦法擋掉 GET 形式的 CSRF，這點要特別注意一下。

**None 模式**： SameSite=None 相較於 Lax 又開放了更多第三方 Cookie 的使用情境，例如：iframe、AJAX、Image 。但是以 Chrome 瀏覽器的規定，這項設定必須配合加上 Secure，限制在 Https 下傳輸才可以生效。
:::

---
**本文作者學習筆記網站：https://dev.rraiy.cc/**

---
參考資料
[https://medium.com/@manojsingh047/understanding-frontend-security-ff6585395534](https://medium.com/@manojsingh047/understanding-frontend-security-ff6585395534)

[https://medium.com/starbugs/身為-web-工程師-你一定要知道的幾個-web-資訊安全議題-29b8a4af6e13](https://medium.com/starbugs/%E8%BA%AB%E7%82%BA-web-%E5%B7%A5%E7%A8%8B%E5%B8%AB-%E4%BD%A0%E4%B8%80%E5%AE%9A%E8%A6%81%E7%9F%A5%E9%81%93%E7%9A%84%E5%B9%BE%E5%80%8B-web-%E8%B3%87%E8%A8%8A%E5%AE%89%E5%85%A8%E8%AD%B0%E9%A1%8C-29b8a4af6e13)

[https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)

[https://blog.techbridge.cc/2017/02/25/csrf-introduction/](https://blog.techbridge.cc/2017/02/25/csrf-introduction/)

[https://www.ithome.com.tw/voice/115822](https://www.ithome.com.tw/voice/115822)

https://medium.com/%E7%A8%8B%E5%BC%8F%E7%8C%BF%E5%90%83%E9%A6%99%E8%95%89/%E5%86%8D%E6%8E%A2%E5%90%8C%E6%BA%90%E6%94%BF%E7%AD%96-%E8%AB%87-samesite-%E8%A8%AD%E5%AE%9A%E5%B0%8D-cookie-%E7%9A%84%E5%BD%B1%E9%9F%BF%E8%88%87%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85-6195d10d4441