Recently, I planned to reproduce vulnerabilities. I must say that Vulhub is incredibly useful, saving a lot of time in setting up environments and allowing me to focus on studying the vulnerabilities themselves. CVE-2016-5734 is a remote code execution (RCE) vulnerability in PhpMyAdmin (4.3.0-4.6.2) from quite some time ago. It is considered a classic PHP regex vulnerability, as the `preg_replace` function with the `/e` modifier was commonly used to write web shell backdoors in the past.
phpMyAdmin is an open-source, web-based MySQL database management tool. In its “Find and Replace” functionality, user input is concatenated into the first parameter of the preg_replace
function.
In PHP versions prior to 5.4.7, the first parameter of preg_replace
could be truncated using `\0`, allowing the regex pattern to be modified to include the `e` modifier. As is well-known, the `e` modifier in regex enables code execution, which can then be exploited to construct an arbitrary code execution vulnerability.
The following versions are affected:
- 4.0.x versions prior to 4.0.10.16
- 4.4.x versions prior to 4.4.15.7
- 4.6.x versions prior to 4.6.3 (In practice, this version requires PHP 5.5+, so the vulnerability cannot be reproduced)
The issue lies in the _getRegexReplaceRows
function within /libraries/TableSearch.class.php
.

The variables `$find` and `$replaceWith` are referenced in `preg_replace`. Tracing these variables back, the `getReplacePreview` function calls `_getRegexReplaceRows`.

Using Notepad++ to globally search for the `getReplacePreview` function within the source code directory, I found that it is called in the `tbl_find_replace.php` file in the parent directory.

Further analysis revealed that the parameters are passed via POST, meaning they are controllable.

The `getReplacePreview()` function is used here, with parameters passed via the POST method, leading to the vulnerability. However, exploiting this vulnerability requires database query permissions, so it can only be exploited after authenticating with a token.
To exploit this vulnerability, three parameters must be controlled. The last two parameters can be null, but the first three are mandatory. Among these, the first two are directly passed via POST, but the third parameter is not controllable. The third parameter represents the original string to be searched and replaced. Since its value cannot be predicted, we need to insert a known value in advance—essentially, creating a table in the database first. This allows the command execution vulnerability to be fully triggered.
Since CVE-2016-5734 has a readily available exploit on Exploit-DB, we can analyze the exploitation logic based on the author’s exploit.

From the following code in the exploit, we can see that the vulnerability’s trigger point lies in the `tbl_find_replace.php` script. The author exploits a bug in PHP versions prior to 5.4.7, where the `preg_replace` function mishandles null bytes, allowing injected code to be executed remotely.
According to the exploit, two conditions must be met to exploit this script:
- Valid credentials to log in to phpMyAdmin
- Knowledge of the corresponding database table or permissions to create a table in the database
Ultimately, the root cause is the improper handling of the `preg_replace` function. Many web shell backdoors are also constructed using this function.
The preg_replace Function
This function is originally intended to replace strings matching a regex pattern. However, it has an additional feature—command execution
. The first parameter of this function is a regex pattern, formatted in PHP between two slashes (`/`). If we append an `e` to the end of the pattern, the second parameter of the function will be executed as code.
Now, using an existing exploit from the web, we can test this. The exploit first executes a query on the specified database table. If the table does not exist, it creates one named `prgpwn` and writes a field named `first` with a value of `0/e`.
Exploit reference: https://www.exploit-db.com/exploits/40185
Payload: `python3 CVE-2016-5734.py -u root -p root -d test http://localhost:1100/ -c ‘system(“tail /etc/passwd”);’`
Summary: This vulnerability requires an account with permissions to create tables and insert fields. In this case, the root account is used directly. First, a table is created, and then a field with the value `0/e` is inserted. Combined, this results in the following: `preg_replace(‘/0/e’,’payload’,’0/e’);`. This constructs the vulnerability. However, this `preg_replace`-triggered vulnerability can only be exploited in PHP versions 4.3.0 to 5.4.6. It is no longer exploitable in PHP 5.4.7 and later. Despite its limitations, it remains a classic RCE vulnerability.