如果程式把使用者輸入錯誤的交給Database資料庫會發生什麼事?
SQL Injection (SQL注入)
一樣用健身房舉例:
員工的會員管理網站
通常裡面會有
- 會員編號
- 姓名
- 帳號
- 方案
這些資料通常不會直接寫在網頁裡
而是放在資料庫Database中
例如:
(資料庫)
| ID | name | |
|---|---|---|
| 1. | MIKEY | XXX@mail.com |
| 2. | TONY | YYY@mail.com |
當網站要查詢資料時:
Web application網頁應用程式 -> Database資料庫 -> 取得資料 -> 回傳給使用者
Structured Query Language,SQL
結構化查詢語言用來和關聯式Database資料庫溝通、查詢、操作資料的語言
例如:
想找一個Username是MIKEY的會員
SELECT * FROM users
WHERE username = 'MIKEY';
翻譯
從users這個資料表中,選取所有欄位 (*=全部)WHERE username = 'MIKEY';篩選條件
只回傳username欄位中,值等於MIKEY的那幾筆資料
使用者操作上會是:
輸入MIKEY->Web application網頁應用程式
用SQL語法對資料庫下指令(資料庫查詢Database Query)->資料庫
找到MIKEY -> 回傳結果
資料庫查詢通常分四大類
INSERT — 把新資料塞進去SELECT - 把資料撈出來看(剛剛的例子)UPDATE - 修改已有的資料庫DELETE - 把資料移除通常問題會出在:
程式怎麼去處理使用者的輸入
假設把程式寫成: (字串拼接)
SQL=
"SELECT * FROM users WHERE username ='"
+ 使用者輸入
+ "'"
SQL= 存進名為"SQL的變數""SELECT * FROM users WHERE username ='"'(把使用者輸入包起來用)+ 使用者輸入'的後面加入使用者輸入內容(+是接上的意思)+ "'"'做呼應,包住中間的值MIKEY
SELECT * FROM users WHERE username ='MIKEY'那假設使用者不照規矩來
使用者輸入的不是普通文字,而是帶有SQL語法的內容呢?
出來的回應就會是SELECT * FROM users WHERE username ='' OR'1'='1'
username =''被提早結束了,是一個空值OR (或者),只要前後任一條件成立就算通過
'1'='1' 1=1,永遠成立true
WHERE後面的條件,是對每一筆資料逐筆檢查的
資料庫會一筆一筆問:「這筆資料符合條件嗎?」
因為
OR後面永遠是true所以不管前面的條件是什麼,每一筆資料都符合,整張表全部回傳
運作過程 以上面的健身房資料庫舉例:
WHERE會去比對第一筆MIKEY
username =''->MIKEY不是空值->所以不成立'1'='1'-> 1=1 -> 成立true
這筆資料通過可以回傳第二筆TONY
username =''->TONY不是空值->所以不成立'1'='1'-> 1=1 -> 成立true
這筆資料通過可以回傳結果就是每一筆資料都因為1=1成立所以回傳
導致攻擊者可以查看所有資料
機密性受影響
出來的回應會是:SELECT * FROM users WHERE username =''; DROP TABLE users; --'
username ='' ->用空值提早結束查詢; -> 代表這句結束,開始下一句users資料表,整張消失; -> 第二句結束--' -> SQL的註解,把後面的'註解忽略掉,才不會造成語法錯誤原本的指令執行完成後,雖然沒成立
但後面又串了一個獨立的SQL指令是DROP TABLE users把整張資料表刪除
再用--把原本程式設計串接的'註解掉讓它不會造成語法上的錯誤完整性受影響
學習指引描述SQL Injection
在輸入字串中夾帶SQL指令;如果程式設計不良、沒妥善處理輸入,資料庫可能把惡意內容當成正常SQL指令執行
資料與指令被混在一起
IPAS 114-2 Q3
關於 SQL 注入(SQL Injection)攻擊的描述,下列何者較為適當?
C: 在資料庫中執行惡意SQL語句
IPAS 114-2 Q25
在 Web 應用程式中,若未對使用者輸入進行適當的驗證與過濾,攻擊者可能利用下列何種攻擊方法,輸入惡意資料進而未經授權地存取或修改資料庫中的資料?
B: SQL注入攻擊
用字串拼接的方式會造成Database最後收到的只有一整串的SQL
但它不知道:
導致程式指令與資料混淆
先把 SQL 的結構固定好,再把使用者輸入當成「參數資料」放進去
參數?
SELECT * FROM users WHERE username = ?;這裡的
?是佔位符
意思是等等會有一個值,但現在還不知道是什麼
(提前告訴資料庫這是一個值)
這時不管使用者輸入什麼都會被當成值,而不會是指令
與字串拼接不同的地方
關鍵在於處理順序
資料庫收到一串SQL會先進行解析
判斷哪些是關鍵字、哪些是符號、哪些是值
字串拼接:
使用者輸入的內容會被加進SQL原本的設計中一同被送去資料庫
這時資料庫會進行解析(但這個時候惡意使用者已經把惡意指令輸入了)
參數化查詢:
資料庫會先收到程式設計者原本設計好的結構
並告訴資料庫?是一個值
所以再來使用者的輸入都會被當成值來處理
而不是指令
IPAS 115-1 Q26
在開發Web應用程式時,為防止SQL注入攻擊(SQL Injection),下列措施中何項較為有效?
A: 使用預備語句或參數化查詢
在使用者的輸入送進資料庫前,先檢查它合不合理
這比較好理解
例如:
人家輸入框要你輸入年齡
正常應該填數字,並且通常是2位數
結果你給人家填ABC或?":之類的符號
只有在使用者輸入正常年齡該有的數字格式時才給予通過
這時才能進入資料庫中
輸入驗證防禦有用
不能當作唯一的防線
因為有些欄位本來就很難驗證
只是剛好舉例年齡比較好說
115-1 Q26 對使用者輸入資料進行 Encoding(編碼)
為什麼它錯
對輸入編碼、跳脫屬於次要的輔助防線
可能被繞過,不是主要防禦
假設網頁應用程式連資料庫時使用的帳號:
只有SELECT查詢會員資料的權限
這樣造成傷害時
也能限制影響的範圍資料庫就會拒絕
DELETE、UPDATE、DROP的指令
IPAS 請問下列何種 SQLi 攻擊類型可利用資料庫伺服器所發出的 DNS(Domain Name System)請求功能將資料傳遞給攻擊者?
A: Inferential SQL Injection
B: Out-of-band SQL Injection 帶外SQL注入
C: Blind SQL Injection
D: In-band SQL Injection 同通道SQL注入
攻擊者注入 SQL,結果直接顯示在網頁回應中,用的是同一個通道
讓資料從原本攻擊的地方看到
靠回應的真假反應推測資料,不會讓資料庫主動對外送封包
簡單來說就是看不到資料,只能靠系統反應來推
帶外注入走的是另一條通道,逼資料庫自己發 DNS 查詢、把要偷的資料夾在網域名稱裡送出去,正是題目描述的手法
簡單來說就是讓資料走另一個通道出來