Burp Suite User Forum

Login to post

PostgreSQL Conditional Error Cheat Sheet

Christian | Last updated: Jun 17, 2022 10:47AM UTC

I have been seeing different PostgreSQL error-based SQL injections lately (both in labs and in the wild) that cannot be correctly exploited with the following payload (found here: https://portswigger.net/web-security/sql-injection/cheat-sheet): SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN cast(1/0 as text) ELSE NULL END I am seeing that the "cast(1/0 as text)" executes independently of the condition being TRUE or FALSE. I guess that is because the way Postgres parses the query string, so it cannot be used to retrieve contents from the database, as it will always return the same error. In my case, I have changed this type of injections to follow this "template": SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/(SELECT 0) ELSE 1 END Which works correctly; It only raises the error when the condition is TRUE. I don't know if this depends on the PostgreSQL version or the injection context (I have tried this in the WHERE and ORDER BY clauses). If it has been happening to more people, maybe it would be a good idea to update the cheat sheet. Thanks!

Liam, PortSwigger Agent | Last updated: Jun 17, 2022 01:26PM UTC

Thanks for your message, Christian. I've passed on your thoughts to our research team. Please let us know if you need any further assistance.

Gareth | Last updated: Jun 20, 2022 08:08AM UTC

Hi Christian We've tested the examples on multiple versions of Postgres and it does work however the context in which you are in is important, if you cast the incorrect type from the when statement then it will always fail. For example if you're in a unquoted WHERE statement you'd need to use the integer type: #division by 1 error SELECT * FROM test WHERE id = 1 OR 1 = (SELECT CASE WHEN (1=1) THEN cast(1/0 as integer) ELSE NULL END) #no error SELECT * FROM test WHERE id = 1 OR 1 = (SELECT CASE WHEN (0=1) THEN cast(1/0 as integer) ELSE NULL END) If you're in a quoted string context then you'd need to return the text type: #division by 1 error SELECT * FROM test WHERE username LIKE '%test%' OR ''=(SELECT CASE WHEN (1=1) THEN cast(1/0 as text) ELSE NULL END)-- #no error SELECT * FROM test WHERE username LIKE '%test%' OR ''=(SELECT CASE WHEN (1=1) THEN cast(1/0 as text) ELSE NULL END)-- We can see how this would be confusing so we'll update the cheat sheet to enforce a consistent context. Thanks

You need to Log in to post a reply. Or register here, for free.