Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions ext/mysqli/tests/fake_server.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1428,6 +1428,20 @@ function my_mysqli_test_stmt_response_field_len_premature(my_mysqli_fake_server_
$conn->read(65536);
}

function my_mysqli_test_sha256_password_short_scramble(my_mysqli_fake_server_conn $conn): void
{
$conn->send_server_greetings();
$conn->read();
// AuthSwitchRequest (0xfe) to sha256_password carrying a scramble shorter
// than SCRAMBLE_LENGTH (20). mnd_emalloc sizes the heap copy to this
// length, so the sha256 plugin's 20-byte XOR over-reads it without the
// length guard.
$payload = "\xfe" . "sha256_password\x00" . str_repeat("\x41", 8);
$header = substr(pack('V', strlen($payload)), 0, 3) . "\x02";
$conn->send($header . $payload, "Auth Switch Request [short sha256 scramble]");
$conn->read();
}

function run_fake_server(string $test_function, int|string $port = 0): void
{
$host = '127.0.0.1';
Expand Down
52 changes: 52 additions & 0 deletions ext/mysqli/tests/mysqli_sha256_password_short_scramble.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
--TEST--
mysqlnd sha256_password: reject server scramble shorter than 20 bytes
--EXTENSIONS--
mysqli
--SKIPIF--
<?php
ob_start();
phpinfo(INFO_MODULES);
$tmp = ob_get_contents();
ob_end_clean();
if (!stristr($tmp, "auth_plugin_sha256_password"))
die("skip SHA256 auth plugin not built-in to mysqlnd");
?>
--FILE--
<?php
require_once 'fake_server.inc';

mysqli_report(MYSQLI_REPORT_OFF);

$process = run_fake_server_in_background('sha256_password_short_scramble');
$process->wait();

$key_file = __DIR__ . '/mysqli_sha256_password_short_scramble.pem';
file_put_contents($key_file, <<<PEM
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvz0SP+XekztaRD5Ghdx8
ZLjXB8TKlF3tup4n6fJqhf6LyCX//AX/ppTZUmoiptxMucJrSaXYuI2YOeh2tfuR
HFMLqlAnK96UxpQMfWSSXVTKaeA4ld0DwQjQeWUIN+2AAN6HNGp7ilnS+7DlSHhd
7KLLZDJqrhQWtDynxGuIx55bAgPMp7adVn8CXg1vVMh62KYZDYmGU69HVVEuHq1n
odJdC1S2HYSJ4LgVIKg9eUBPKO1Bvwrwxse7UDGUNCSOyF+r8/jTKdrPdXp1qRNQ
9dU4/gMzMWd2NJ3+unXaLEEmpWEj/8x56X46PmpfbVAKm0tyn7YZH3tqamPo1piz
rQIDAQAB
-----END PUBLIC KEY-----
PEM);

$link = mysqli_init();
$link->options(MYSQLI_SERVER_PUBLIC_KEY, $key_file);
@$link->real_connect("127.0.0.1", "root", "password longer than the scramble", "", $process->getPort());
printf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());

$process->terminate();
print "done!\n";
?>
--CLEAN--
<?php
@unlink(__DIR__ . '/mysqli_sha256_password_short_scramble.pem');
?>
--EXPECTF--
[*] Server started on 127.0.0.1:%d
%A
[2027] The server sent wrong length for scramble
done!
5 changes: 5 additions & 0 deletions ext/mysqlnd/mysqlnd_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,11 @@ mysqlnd_sha256_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self
DBG_ENTER("mysqlnd_sha256_auth_get_auth_data");
DBG_INF_FMT("salt(%zu)=[%.*s]", auth_plugin_data_len, (int) auth_plugin_data_len, auth_plugin_data);

if (auth_plugin_data_len < SCRAMBLE_LENGTH) {
SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "The server sent wrong length for scramble");
DBG_ERR_FMT("The server sent wrong length for scramble %zu. Expected %u", auth_plugin_data_len, SCRAMBLE_LENGTH);
DBG_RETURN(NULL);
}

if (conn->vio->data->ssl) {
DBG_INF("simple clear text under SSL");
Expand Down
Loading