3

I know you need prepared statements and such to avoid SQL injection, and I've seen that there are different questions about exploits for SELECT, INSERT, UPDATE injectable queries.

But I couldn't come up with an exploit sample for USE statement. Suppose I have an injectable single statement that looks like this:

USE `data_from_attacker`;

What data could the attacker use if they can put anything in place of the data_from_attacker, considering I'm looking for an exploit example that is not just selecting a DB (ie: selecting information_schema or mysql DB seems harmless, as the next queries won't work because tables won't exist; and selecting a DB that do not exists seems also harmless).

Also, consider that mysql will only interpret the 1st query, so attacker cannot inject:

mysql`; SELECT * FROM `users

Can you find such exploit for MySQL? The USE syntax seems very "poor" for such injection...

4

Quote Xenos
Can you find such exploit for MySQL? The USE syntax seems very "poor" for such injection

Lets track down how USE works in MySQL and which files MySQL in the source code needs to access.

---

**Query #1**

    SET PROFILING = 1;

There are no results to be displayed.

---
**Query #2**

    USE test;

There are no results to be displayed.

---
**Query #3**

    SHOW PROFILES;

| Query_ID | Duration   | Query    |
| -------- | ---------- | -------- |
| 1        | 0.00006425 | USE test |

---
**Query #4**

    SHOW PROFILE ALL FOR QUERY 1;

| Status         | Duration | CPU_user | CPU_system | Context_voluntary | Context_involuntary | Block_ops_in | Block_ops_out | Messages_sent | Messages_received | Page_faults_major | Page_faults_minor | Swaps | Source_function       | Source_file  | Source_line |
| -------------- | -------- | -------- | ---------- | ----------------- | ------------------- | ------------ | ------------- | ------------- | ----------------- | ----------------- | ----------------- | ----- | --------------------- | ------------ | ----------- |
| starting       | 0.000038 | 0.000019 | 0.000012   | 0                 | 0                   | 0            | 0             | 0             | 0                 | 0                 | 0                 | 0     |                       |              |             |
| query end      | 0.000003 | 0.000002 | 0.000001   | 0                 | 0                   | 0            | 0             | 0             | 0                 | 0                 | 0                 | 0     | mysql_execute_command | sql_parse.cc | 4310        |
| closing tables | 0.000003 | 0.000001 | 0.000001   | 0                 | 0                   | 0            | 0             | 0             | 0                 | 0                 | 0                 | 0     | mysql_execute_command | sql_parse.cc | 4356        |
| freeing items  | 0.000009 | 0.000006 | 0.000003   | 0                 | 0                   | 0            | 0             | 0             | 0                 | 0                 | 0                 | 0     | mysql_parse           | sql_parse.cc | 4968        |
| cleaning up    | 0.000012 | 0.000007 | 0.000005   | 0                 | 0                   | 0            | 0             | 0             | 0                 | 0                 | 0                 | 0     | dispatch_command      | sql_parse.cc | 1978        |

---

see demo

MySQL basic lexer works with yacc so we check file sql_yacc.yy first.
Below is the USE keyword defined.

/* change database */

use:
          USE_SYM ident
          {
            LEX *lex=Lex;
            lex->sql_command=SQLCOM_CHANGE_DB;
            lex->select_lex->db= $2.str;
          }
        ;

When we check sql_parse.cc and within the function mysql_execute_command() we find

case SQLCOM_CHANGE_DB: {
  const LEX_CSTRING db_str = {select_lex->db, strlen(select_lex->db)};

  if (!mysql_change_db(thd, db_str, false)) my_ok(thd);

  break;
}

To answer the question.
No i could not find a possible exploit as it is very clear in the source code the <database> part in the USE <database> statement expects a "string" and does not parse and or execute a SQL statement futher.

With string i mean database_name in the format of USE database_name or with backticks.

  • 1
    Excellent, that's the type of answer I was looking for : ) I've digged even a bit further in the mysql_change_db code and it's sub-called functions, but I also saw nothing attackable there (even tho I'm not expert in MySQL source code). Thanks again ! :) – Xenos Aug 7 at 8:36
  • @Xenos in some cases character encoding mixing injections might work if the client not explicitly uses a connection charset or the server does not enforce the client to use one but you will also not gain much from it... Also as C/C++ strings are NULL terminated lets test that case aswell, well also no gain here.. – Raymond Nijland Aug 7 at 14:01
2

If any of the elements of the schema in your database have names in common with other databases on the SQL engine, it might be possible to cross queries to produce undesirable results.

Let’s say the expected database has a name of ‘PROD _DB’, but your developers have another database on the same SQL server named ‘TEST_DB’. They use the test database for testing the app, so it has the identical schema, but is filled with junk data that is used only for testing and nobody cares about; things like UserName == ‘test1’, PassWord == ‘abc’, AdminFlag == 1. By changing the USE statement at will, from PROD_DB to TEST_DB and back again, they could authenticate using the ‘test1’ credentials and set their status to Admin, then flip back and use their admin status to do whatever they want inside your production application.

  • Indeed, the prod/test example is neat. I'm still less impressed than other usual DML injection. Do you have any other idea how to read or alter data in the tables through that single injection (without relying on other queries from the normal process flow being fired on the "wrong" database)? – Xenos Aug 1 at 15:55
  • Certainly it’s not as generically useful as an exploit that lets you break out of the existing SQL. If I was attacking the system, I’d be trying to find a way to escape the restrictions preventing that. Regardless, it probably should be fixed now, even if there isn’t a visible exploit. Consider that in the future someone else may migrate the database to a prod/test type of configuration, at which point it would become vulnerable. Or maybe they migrate it to Postgres, which could be vulnerable. Too many possibilities for the future. – John Deters Aug 1 at 20:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.