Starting in September 2018, we identified attackers actively attempting to exploit an information disclosure vulnerability (CVE-2018-7204) within versions 5.0.0 and earlier of the WordPress Giribaz File Manager plugin (CVE-2018-7204). Successful execution of this WordPress security vulnerability would allow the attacker to extract sensitive system information from the victim host.

Overview

The vulnerability exists as a consequence of the plugin’s verbose logging functionality. The plugin logs all file activity to the ‘/wp-content/uploads/file- manager/log.txt’ file, which is publicly accessible. Should the plugin be used to interact with a file containing sensitive information, for example the ‘wp-config.php’ file, the contents of that file would be added to the log and exposed.

Attack payloads we have observed are as follows, which would allow the attacker to access the contents of the log.txt as requested. This information would be returned to the attacker in the response.

GET /[victim]/wp-content/uploads/file-manager/log.txt HTTP/1.1
Host: [host]
User-Agent: [user-agent]
Accept: */*

An attacker being able to extract server information significantly increases the risk to an organization. It can allow an attacker to engage in more sophisticated attack techniques based on the information supplied. Any time an attacker is encouraged to spend additional time inspecting a host or has reason to focus on a potential victim materially increases the risk of a compromise.

Code Review

This information disclosure vulnerability is the result of verbose logging output being stored in a location accessible to anyone.

function logger($cmd, $result, $args, $elfinder) { 
    global $FileManager; 
    $log = sprintf("[%s] %s: %s \n", date('r'), strtoupper($cmd), var_export($result, true)); 
    $logfile = $FileManager->upload_path . DS . 'log.txt';
    dir = dirname($logfile);
    if (!is_dir($dir) && !mkdir($dir)) {
        return; 
    } 
    if (($fp = fopen($logfile, 'a'))) {
        fwrite($fp, $log); 
    fclose($fp); 
}
return;

Source: /wp-content/plugins/filemanager/file-manager.php [Lines: 239-253, v4.1.6]

The function responsible for logging is located within the ‘file-manager.php’ file in the plugins root directory. The function accepts a number of arguments including the command executed, the results of the command execution, the command arguments and a reference to an ‘elfinder’ object which is an open source JavaScript file manager.

The function is relatively straight forward and uses sprintf to generate a line containing the date followed by the upper-case command string, the result of the operation, and finally stores this in the variable ‘$log’.

With the log message constructed, the function proceeds to prepare to open the log file which is expected to be the value of the ‘$FileManager->upload’ property concatenated with the filename ‘log.txt’ and a directory separator constant ‘DS’. This will, by default, result in the path ‘/wp-content/uploads/file-manager/log.txt’ and is subsequently accessible to anyone who can access the WordPress site.

If the above log file does not exist, the function will attempt to create the file and terminate if it is unable to do so. Assuming all goes well and the log file either exists or has been created, the function opens the file in ‘append mode’, writes the contents of the ‘$log’ variable to the file, closes the descriptor and returns.

There is additional code following the return statement which appears to contain error handling and more detail with regards to what (if any) changes were made to the file in question, however the return statement renders all of it unreachable.

In testing it was determined that both the ‘preview’ and ‘edit’ operations will cause a ‘get’ command to be logged along with the verbatim contents of the target file. This verbose logging of file contents combined with the publicly accessible location in which the log file is stored are the root causes of the information disclosure vulnerability.

function logger($cmd, $result, $args, $elfinder) { 
    global $FileManager; 
    $log = sprintf("[%s] %s: \n", date('r'), strtoupper($cmd)); 
    foreach ($result as $key => $value) { 
        if (empty($value)) { 
            continue; 
        }
        $data = array();
 
        if (in_array($key, array('error', 'warning'))) { 
            array_push($data, implode(' ', $value)); // logs only error and warning. 
        } 
        $log .= sprintf(' %s(%s)', $key, implode(', ', $data)); 
    }
    $log .= "\n"; 
    $log = get_option('fm_log', '') . $log; 
    update_option('fm_log', $log); 

Source: /wp-content/plugins/file-manager/inc/logger.php [Lines: 21-40, v5.0.2]

In the patched version of the plugin, the logger function can be found in a standalone file for inclusion elsewhere when logging is required. The function as outlined above bears a close resemblance to the unreachable code from version 4.1.6 without the direct file write operations.

The first difference that jumps out is the removal of the ‘var_export($result)’ portion of the sprintf call which populates the ‘$log’ variable. This immediately prevents the entire contents of the ‘$results’ array from being logged, including any file content.

The contents of the ‘$result’ array is then looped through with empty values skipped. The ‘$key’ of each array element must contain either ‘error’ or ‘warning’ strings to be pushed onto the empty ‘$data’ array. This effectively reduces the logged data to only warnings and error messages, neither of which will contain potentially sensitive file contents.

After the ‘$result’ array is processed and the ‘$data’ array has been populated with error and warning messages, the contents of the ‘$data’ array are imploded and appended to the ‘$log’ variable using another sprintf call.

Finally, the ‘$log’ variable is updated to contain the value returned by the WordPress ‘get_option’ call with the current value of the ‘$log’ variable appended. This newly appended log data is then passed via a call to ‘update_option’ to update the stored log data to include any new warning or error data.

The WordPress options API is used to enable easy storage of information in the database. The above code effectively translates to “get the current log data stored in the database under the key ‘fm_log’, append the new log data, and store the result in the database using the same ‘fm_log’ key”. At no point does the code perform any file write operations and the previous log path in the ‘uploads’ directory is absent.

These changes effectively address the two root causes of the information disclosure vulnerability present in previous versions. First the logger function now discriminates based on the presence of error and warning information, which prevents potentially sensitive file contents from appearing in log data. Secondly the log data is now stored in the database using built-in WordPress functionality which is much more likely to be robust and maintained than custom code.

Remediation

Update the Giribaz File manager to version 5.0.2.

About Alert Logic Threat Research

Alert Logic routinely tracks emerging vulnerabilities and active use of new exploits in the wild. This allows us to keep up with the latest tools, techniques, and practices of attackers and provide protection for our customers for their most critical threats.

Fortra's Alert Logic
About the Author
Fortra's Alert Logic

Related Post

Ready to protect your company with Alert Logic MDR?