user2746604
user2746604

Reputation: 19

SQL injection in LIKE with backslash allowed

Currently, I'm testing some code, and I noticed this:

$data = str_replace( array('"', "'") , "", $_GET['input']);
$query = "SELECT * FROM tab WHERE LOWER(title) LIKE '%$data%'";

Now, I have no interest in asking how to make this code safe. I would be interested to know how you could use the backslash (\\), or anything else, to cause an SQL injection in real world. Any ideas?

Upvotes: 1

Views: 1221

Answers (3)

Marcos Fernandez Ramos
Marcos Fernandez Ramos

Reputation: 677

It's just not possible with current code. Although you can perform a sql injection when there are 2 parameters present, imagine the next piece of code:

$data1 = str_replace( array('"', "'") , '', $_GET['input1']);
$data2 = str_replace( array('"', "'") , '', $_GET['input2']);
$query = "SELECT * FROM tab WHERE LOWER(title) = '$data1' AND asd = '$data2';";

Now you guess the order of the params (permutations or try/error) and then send a backslash in the first $_GET param, propertly encoded (%5c). You get:

SELECT * FROM tab WHERE LOWER(title) = '\' AND asd = '$data2';

Title field now must match "\' AND asd = " which I doubt happens. As a second $_GET param, you can pass (AND 1=1) -- . The final comment (--) here is important because you have to get rid of the last quote. You finally get:

SELECT * FROM tab WHERE LOWER(title) = '\' AND asd = '(AND 1=1) --';

Its done. If you want to dump impormation schema you cant still use quotes, so you have to use hex values, the server is completely powned.

Upvotes: 0

Janoz
Janoz

Reputation: 953

@Laxus It depends not realy on used encodings, but assumed encodings. If the php code assumes one encoding (which usually isn't UTF-8 because php can't handle multibyte strings by default so it just takes a character for every byte) while the database uses another (for example UTF-8)

The UTF-8 scheme can use mutiple bytes to encode a code point to a character as can be seen on the wikipage http://en.wikipedia.org/wiki/UTF-8

Codepoints below 127 are stored in a single byte using the following scheme:

0xxx xxxx

where x is the bits of the code point. If a codepoint is above 127 (ie: more than 7 bits) it uses two bytes:

110x xxxx 10xx xxxx

The ' has a codepoint of 27 (hex) or 10 0111 (binary). Normaly this is stored in a single byte

0 010 0111

in hex still: 27

A malicious attacker could choose to store this in two bytes (padded with 0's)

110 0 0000 10 10 0111

and in hex: C0 A7

Now php processes this and assumes these two bytes are two separate characters (because it just uses ascii). It tries to replace 27 by nothing, but the string only contains C0 and A7 so no 27 found. However, the database does understand UTF-8 and decodes this code point back to '.

Possible Injection!!

These type of encodings are called overlong encodings and arn't really valid utf-8 characters, but it might just slip trough a buggy utf-8 implementation.

Upvotes: 1

Janoz
Janoz

Reputation: 953

Although there might be some unicode tricks to insert an ' in $data which isn't a ' in php terms, but is interpreted as an ' by your database (I know this sounds fussy) the first thing I notice about this example is that I'm unable to search for phrases like "it's" or "I'm".

Upvotes: 1

Related Questions