SQLi → RCE: Exploiting PostgreSQLi
文章介绍了一种基于CTF的Web应用程序中的SQL注入攻击方法,使用PostgreSQL作为后端数据库。通过错误基、联合查询和布尔盲注等技术手段,成功实现了身份验证绕过、数据库信息提取以及最终的远程代码执行(RCE)。文章还讨论了如何利用PostgreSQL的高权限用户和危险功能来执行操作系统命令,并提供了相应的防御建议。 2025-12-29 06:5:18 Author: infosecwriteups.com(查看原文) 阅读量:4 收藏

In this blog, we will see types of sqli and how we can achieve RCE at last

Raj Prasad Kuiri

Press enter or click to view image in full size

I am here not going to explain SQLi and its types. There are plenty of resources out there that you can check here

So it's a CTF-based web application which is using PostgreSQL as a backend database

Error-Based SQLi

Press enter or click to view image in full size

By giving a single quote, we can see the error. What happened in the backend? let's see

SELECT * FROM users WHERE username = 'admin'' AND password = ''

We typed admin’ and that breaks the SQL syntax, and due to this database throws a SQL syntax error, and from the error style its confirmed it's a PostgreSQL

These are the error styles for each database variant to identify

Press enter or click to view image in full size

Press enter or click to view image in full size

Authentication bypassed. What happened in the backend?

SELECT * FROM users WHERE username = 'admin' --' AND password = '';

-- means comments and everything after this is ignored by database
So, the password check never executes

Union-Based SQLi

Press enter or click to view image in full size

' ORDER BY 1-- used for finding the no of columns

Press enter or click to view image in full size

After providing ORDER by 1,2,3,4,5, at 6 database throws the error, which means it has 5 columns. Let's enumerate further !!

Press enter or click to view image in full size

Actual SQL query => SELECT id, name, price, description, image

Injected SQL query => UNION SELECT null, null, null, null, null;

UNION combines results of two SELECT queries.

Why Null is used

null → int
null → varchar
null → text
null → image

Because null can be a integer, character, numeric value

Press enter or click to view image in full size

As we can see 1st column is an integer i replaced null with 1.

Press enter or click to view image in full size

As in the 2nd column databse throws an error. So it's not accepting an integer. Likewise, we need to check and confirm what each column is accepting integer, character, or text. After enumerating further i was able to fetch the database version and tables.

Press enter or click to view image in full size

-2 UNION SELECT NULL, version(), NULL, NULL, NULL --

-2 is used as an invalid or non-existing ID value so that:

the original query returns ZERO rows
only the UNION SELECT output is shown

Press enter or click to view image in full size

id=-2 UNION SELECT NULL,string_agg(table_name,CHR(44)),NULL,NULL,NULL FROM information_schema.tables WHERE table_schema=current_schema()--

Boolean-Based Blind SQLi

  • Boolean True Condition
  • Boolean False condition
%' AND 3=3-- always return true
%' AND 5=8-- always return false
We need to look for true response and enumerate further!!

Let's check the database name length

Press enter or click to view image in full size

%' AND LENGTH(current_database())=5-- 

So, it’s confirmed that the database name length is 5 characters.

Get Raj Prasad Kuiri’s stories in your inbox

Join Medium for free to get updates from this writer.

Now, let's check the database name

Press enter or click to view image in full size

Press enter or click to view image in full size

After enumerating manually, we can confirm the database name starts with a small letter l. Similarly, we need to check for each character like this

%' AND SUBSTRING(current_database(),1,1)='A'--  1st character
%' AND SUBSTRING(current_database(),2,1)='b'-- 2nd character
%' AND SUBSTRING(current_database(),3,1)='c'-- 3rd character
%' AND SUBSTRING(current_database(),4,1)='d'-- 4th character
%' AND SUBSTRING(current_database(),5,1)='e'-- 5th character

Total 5 character as per the database length

Let’s automate this process via Burp. We will use ASCII characters; there are a total of 128 ascii characters, including 0–1, a-z, A-Z. You can check here

Press enter or click to view image in full size

Send this to the intruder

Press enter or click to view image in full size

Enumerate the highlight fields and select the attack type cluster bomb

Then, use the grep extract I had provided to the correct response string value.

Press enter or click to view image in full size

Press enter or click to view image in full size

5 success responses received as we had set true response in grep.

Let's decode these ASCII characters

payload 1

1 2 3 4 5

payload 2

108,97,98,100,98

As per ASCII table it shows labdb

So the database name is labdb

Press enter or click to view image in full size

So it shows true response, and finally, we confirmed our database name.

q=%' AND current_database()='database-name'--

If this article helped you learn something new, you can support my work here , it motivates me to create more helpful content for readers like you and for the community

RCE via SQLi

Here comes the interesting part that we have been waiting so far. Lets see

Condition for RCE in PostgreSQL

  • > The attacker-controlled SQL context should have high privileges, typically: Superuser

Press enter or click to view image in full size

id=-1 UNION SELECT NULL,usesuper::text,NULL,NULL,NULL FROM pg_user WHERE usename=current_user--

Superuser is enabled as it shows true

Press enter or click to view image in full size

Press enter or click to view image in full size

Able to open the phpinfo page, Now lets run some shell commands

Press enter or click to view image in full size

This payload abuses PostgreSQL’s server-side program execution capability to run OS commands and return their output via a UNION-based SQL injection, resulting in full remote code execution when misconfigured privileges exist.

Press enter or click to view image in full size

Press enter or click to view image in full size

id=-1 UNION SELECT NULL,cmd_output,NULL,NULL,NULL FROM cmd_output--

We can able to perform shell commands. Let’s check on SQL map as well

Press enter or click to view image in full size

Press enter or click to view image in full size

Mitigations

Use parameterized queries (prepared statements) everywhere — never concatenate user input into SQL.

Run the application with a non-superuser PostgreSQL role — no SUPERUSER, no elevated privileges.

Disable dangerous PostgreSQL features such as server-side program execution and unsafe extensions.

Restrict database file system access — PostgreSQL must run as a low-privileged OS user with no write/execute access to sensitive paths.

Do not expose database errors to users — handle exceptions and return generic messages.

Do check this out, how I automate OWASP Mobile security testing with this single Frida script

Do follow me in medium and connect with me on LinkedIn.


文章来源: https://infosecwriteups.com/sqli-rce-exploiting-postgresqli-f5bb81d24630?source=rss----7b722bfd1b8d--bug_bounty
如有侵权请联系:admin#unsafe.sh