###### tags: `2020 Kali讀書會-資安小聚`
## 你知道後端仔是如何阻礙你的 SQL injection 的嗎?
### Sponge
---
## 講者介紹
* 現任 後端工程師 (BackEnd)
* 曾任 資料庫設計師 (DataBaseDesigner)
* 曾任 資料庫管理師 (DataBaseAdministrator)
---
## 分享流程
* 資料庫介紹
* 防禦手段介紹
* 實際演練
---
## HackMD 共用筆記

[2020 Kali讀書會-資安小聚](https://hackmd.io/RhHpk1rTQEC5gPUUOfrfug)
---
## 網站的構成

---
## 資料庫的種類

---
## 那個資料庫最熱門呢?
https://db-engines.com/en/ranking

---
## 讓我們來針對 MS-SQL 來介紹
- 原因 :
* 其 SQL 方言多,獨立命名為 Transact-SQL
* 討論度排名為第三,市佔率也並不低
* 我比較熟悉 MS-SQL 的開發模式
---
## MS-SQL 的資料庫階層
資料庫是有階層的,而且 MS-SQL 比別人多一層
```SQL
--MySQL : database => table => column
SELECT * FROM `Test`.`Sanple`.`id`
```
```SQL
--MS-SQL : database => table => schema => column
SELECT * FROM [Test].[dbo].[Sanple].[id]
```
schema 是可以自訂的,預設皆為 dbo
---
## SQL
- SQL (Structured Query Language)
- 結構化查詢語言
- 對資料庫進行操作(插入 刪除 查詢)
- 在不同的資料庫上會有些微的不同
- Oracle MySQL MSSQL Postgresql
---
## T-SQL 與 MySQL 語法異同
欄位標示與限定筆數的不同
```sql
--MySQL :
SELECT * FROM `Test`.`Sanple`.`id` LIMIT 10
```
```sql
--MS-SQL :
SELECT TOP 10 * FROM [Test].[dbo].[Sanple].[id]
```
取得版本號的語法相同
```sql
--MySQL&MS-SQL :
SELECT @@VERSION
```
---
## 登入功能的 SQL 實現
```sql
SELECT COUNT(*)
FROM [dbo].[user]
WHERE uid='guest'
AND passward = 'xxxxxxx'
```
```sql
SELECT COUNT(*)
FROM user
WHERE Uid='INPUT'
AND passward = 'INPUT'
```
---

---
## 開發人員的防禦方法
1. 不顯示詳細錯誤訊息給使用者,避免透過 SQL Error Message 猜測資料表、查詢語法的的結構
2. 過濾使用者傳入的參數(-- 、//、/**/….)
3. 使用參數化的查詢方法,不使用 SQL 拼接
4. 透過 ORM 工具撰寫 LINQ 語法與資料庫溝通
---
## 甚麼是參數化的查詢?
```sql
DECLARE @USER nvarchar(20) = 'guest',@PWD nvarchar(30) = 'xxxxxxx'
SELECT COUNT(*)
FROM [dbo].[user]
WHERE [uid] = @USER
AND [passward] = @PWD
```
---
## 程式要如何實作參數化查詢
```csharp=
SqlCommand cmd = new SqlCommand(
"SELECT COUNT(*) FROM user WHERE uid = @uid AND passward = @passward", conn);
cmd.Parameters.AddWithValue("@uid", userName);
cmd.Parameters.AddWithValue("@passward", password);
conn.Open();
return ((int)cmd.ExecuteScalar() > 0);
```
---
## 參數化的查詢可以阻止攻擊?
在使用參數化查詢的情況下,資料庫伺服器不會將參數的內容視為SQL指令的一部份來處理,而是在資料庫完成SQL指令的編譯後,才套用參數執行,因此就算參數中含有具破壞性的指令,也不會被資料庫所執行。
---
## 那麼甚麼是 ORM?
- Object-Relation Mapping
- ORM
- 對象關係映射
- 用程式語言而非 SQL 來操作資料庫
- 可透過同一套語法操作不同資料庫,降低耦合
- 最終轉譯成 SQL
- 由於經由中間層轉譯,效能會降低
- 還是有風險,ORM Injection
---
## ORM 如何實作
```csharp=
protected void Login(object sender, EventArgs e)
{
NorthwindDataContext context
= new NorthwindDataContext();
if( (
from s1 in context.user
where s1.uid == TextBox1.Text
&& s1.passward == TextBox2.Text
select s1).Count() = 1
)
Label1.Text = "success";
else
Label1.Text = "error";
}
```
---
## 還是有網站可以攻擊?
- 系統老舊沒有維護
- 效能考量
- 有進行防護但仍有漏洞
---
## 那該如何防禦SQLInjection
目前最佳解為參數化查詢,但由於會影響效能與降低開發速度,因此多採用 ORM 框架來防禦,
現今主流的 ORM 框架如 .NET 系列的
Dapper、Entity framework
---
## 那麼,來試試看吧
### 我準備了一個 blazor 專案供大家遊玩

---
## 成功進來會顯示恭喜喔

---
## 會記錄登入的名稱與 ip

---
## 參考資料
- [stackoverflow_parameterized-query](https://stackoverflow.com/questions/4712037/what-is-parameterized-query)
- [stackoverflow_orm](https://stackoverflow.com/questions/37189863/which-orm-should-i-be-using-for-net-in-2016-to-talk-to-sql-server)
- [db-engines](https://db-engines.com/en/ranking)
- [ORM_Injection](https://www.owasp.org/index.php/Testing_for_ORM_Injection_(OTG-INPVAL-007))
---
## 希望大家能有所收穫
### 如有錯誤請不吝告知,十分感謝
---
```
{"metaMigratedAt":"2023-06-15T02:57:43.170Z","metaMigratedFrom":"Content","title":"Untitled","breaks":true,"description":"現任 後端工程師 (BackEnd)","contributors":"[{\"id\":\"3a9f7467-86ee-4e65-969a-d2212f5ccee7\",\"add\":4449,\"del\":632}]"}