---
# System prepended metadata

title: LeetCode讀書會（7/29~8/04) 前後端加密的差別 / SQL Injection

---

# LeetCode讀書會（7/29~8/04) 前後端加密的差別 / SQL Injection


## 前後端密碼加密（hash）
## -----瑋晨-----
 ---
 ![](https://i.imgur.com/Nq1DNQP.png)

 ---
 ## 加密方式
 * Encode
 -- 只是換個方式來表達資料，例如Base64、encodeURL、decodeURL
 * Encrypt
 -- 必須要有金鑰(KEY)，例如AES(對稱加密)、RSA(非對稱加密)
 * Hash
 -- Data -> Hash function(SHA-1、md5) -> Hash Value
 -- 無法反推回原字串
 
 * [參考資料](https://medium.com/starbugs/what-are-encoding-encrypt-and-hashing-4b03d40e7b0c)
 
 ---
 
 ## 資料庫存放明文密碼
 
 * 前後端分離架構，明文密碼的隱憂
 * 資料庫洩漏
 
 --- 
 
 ## 如何加密?
 1. Encrypt 加密 
 ![](https://i.imgur.com/QCegoq5.png)
 * 缺點: 
     * KEY還是放在SERVER上，一旦洩漏密碼還是危險
     * 員工若知道KEY，還是很防止資料洩漏
 
 --- 
 ## 如何加密?
 2. HASH 
 ![](https://i.imgur.com/ichbcCv.png)
 登入時比對HASH值，若相同， __高機率__ 為本人，放行
 * 缺點
 ![](https://i.imgur.com/Q2jmyqU.png)
 * 因為大多數密碼格式其實相差不大，所以可以用暴力破解
 ex. [彩虹表破解法](https://zh.wikipedia.org/wiki/%E5%BD%A9%E8%99%B9%E8%A1%A8)
 
 --- 
 ## 如何加密?
 3. HASH 加鹽
 
 既然建表就可以從hash值反推回我的明文， __那就把明文弄得更亂__ 再HASH
 ![](https://i.imgur.com/KQcpY8Z.png)
 
 * 這樣的優點是反推會更複雜，遠超目前電腦的極限。
 * 進階可以利用Bcrypt 再進行更複雜的加密
 
  [參考資料](https://medium.com/starbugs/what-are-encoding-encrypt-and-hashing-4b03d40e7b0c)
 ---
 
 ## 前端有需要加密嗎?
 
 * 防人之心不可無
 * 網站最好永遠，永遠不要有可能知道用戶的明文密碼。因為HTTPS只保證通信過程的安全，不保證服務器上數據的隱秘性 

 --- 
 ## github登入 -- 前端沒加密
 ![](https://i.imgur.com/wZbFtkU.png)
 * 明文傳送，但是確保安全，WHY? --> https
 * TLS 是可以保證我們和服務器端傳輸的安全性
 * 這安全性主要包括三方面：
1. 機密性。（第三方截獲數據無法知道明文是什麼）
2. 數據完整性。（第三方篡改數據，會使得數據變得無效）
3. 認證。（交流雙方可以確認對方的身份，第三方無法偽裝成任何一方進行交流）
 * Public-Private-Key加密（保證第一個），對稱加密（保證第一個）
 *  hash 散列函數（保證第二個），
 * CA機構（保證第三個）。
 
 --- 
 
 ## 為何前端需要加密?
 
 * 保護客戶的隱私
  -> 在多個網站都使用同一個密碼是很普遍的現象
 * https 有時不太可靠 -> [可參考](https://program-think.blogspot.com/2016/09/About-WoSign.html)
 * 隱憂，以HASH加密傳輸，若攻擊者拿到HASH還是可以進行登入

[前端要不要加密很有趣的討論](https://www.zhihu.com/question/25539382)
 
 ## -----瑋晨-----
### bcrypt(承翰)
bcrypt 能夠將一個字串做雜湊加密，其中有個參數叫 saltRounds 是在密碼學中的加鹽(salt)，加鹽的意思是在要加密的字串中加特定的字符，打亂原始的字符串，使其生成的散列結果產生變化，其參數越高加鹽次數多越安全相對的加密時間就越長。

#### 解析加密字串
加密後的 bcrypt 分為四個部分：

##### Bcrypt
該字串為 UTF-8 編碼，並且包含一個終止符
##### Round
(回合數)每增加一次就加倍雜湊次數，預設10次
##### Salt
(加鹽)128 bits 22個字元
##### Hash
(雜湊)138 bits 31個字元

![img](https://ithelp.ithome.com.tw/upload/images/20180108/20107247r1tPcIUHFo.png)

參考資料：https://ithelp.ithome.com.tw/articles/10196477

-- Argon2資料--
https://medium.com/analytics-vidhya/password-hashing-pbkdf2-scrypt-bcrypt-and-argon2-e25aaf41598e

## SQL Injection
--震瑋--
SQL injection中文譯作SQL注入、SQL隱碼。SQL Injection是一種常見的網路攻擊手法，藉由在輸入字串中夾帶惡意指令，試圖改變SQL語法上的邏輯，得以非法破壞、入侵資料庫伺服器，例如竊取使用者機密資料，帳戶資料，密碼等，甚至癱瘓整個系統。

#### SQL語法註解
```sql
/*
--
#
```
#### SQL Injection範例
```sql
SELECT * FROM member WHERE account = 'ply' AND password = 'ply'
```
如果只在帳號輸入欄位輸入「' or 1=1 /*」，SQL語法會變成：
```sql
SELECT * FROM member WHERE account = '' or 1=1 /* AND password = "ply"
```
WHERE後面的條件判斷， account='' or 1=1 ，因為1=1數學式恆等，該判斷式永遠會成立，而/*是註解符號，因此該SQL語法實際效果如下：
```sql
SELECT * FROM member WHERE account = '' or 1=1
```
藉由在字串中夾帶特殊字元，便可以改變SQL語法邏輯進而登入網站。


--宇軒--
**所以SQL該怎麼被防範**

為什麼我們不寫像這樣的語法
```python=
res = db.execute(f"SELECT * FROM member WHERE account = {account} AND password = {password}").fetchone()

```
最常見的防禦方式為parameterized query(參數化查詢)，該方法會先將SQL語法固定防止重構，以上方登入為例，SQL語法會固定為
```sql=
SET @account := XXX;
SET @password := XXX;
SELECT * FROM member WHERE account = @account  AND password = @password
```

此時就算在email或password中安插其他SQL語法，在參數化後都會只視為字串而非SQL語法，就算使用者輸入帳號／密碼為 a / b' OR '1'='1，依然只會查找帳號「a」，密碼是「b' OR '1'='1」的使用者，也無法執行其他SQL injection的操作了。

在python-mysql-connector的操作則會像是
```python=
res = db.execute("SELECT * FROM member WHERE account = %s AND password = %s", (account, password)).fetchone()
print(res)
```

--宇軒--

## Leetcode討論區
