Lucene search

K
hackeroneEgixH1:1063039
HistoryDec 20, 2020 - 5:38 p.m.

Concrete CMS: Phar Deserialization Vulnerability via Logging Settings

2020-12-2017:38:21
egix
hackerone.com
55

0.013 Low

EPSS

Percentile

86.1%

Vulnerability Description:

The vulnerable code is located within the concrete/controllers/single_page/dashboard/system/environment/logging.php script.
Specifically, into the Logging::update_logging() method:

    public function update_logging()
    {
        $config = $this->app->make('config');
        $request = $this->request;

        if (!$this->token->validate('update_logging')) {
            return $this->showError($this->token->getErrorMessage());
        }

        // Load in variables from the request
        $mode = (string) $request->request->get('logging_mode') === 'advanced' ? 'advanced' : 'simple';
        $handler = $mode === 'simple' ? (string) $request->request->get('handler', 'database') : null;
        $logFile = $handler === 'file' ? (string) $request->request->get('logFile') : null;
        $enableDashboardReport = $request->request->get('enable_dashboard_report') ? true : false;
        $loggingLevel = strtoupper((string) $request->request->get('logging_level'));
        $intLogErrorsPost = $request->request->get('ENABLE_LOG_ERRORS') === 1 ? 1 : 0;
        $intLogEmailsPost = $request->request->get('ENABLE_LOG_EMAILS') === 1 ? 1 : 0;
        $intLogApiPost = $request->request->get('ENABLE_LOG_API') === 1 ? 1 : 0;


        // Handle 'file' based logging
        if ($handler === 'file') {
            $directory = dirname($logFile);

            // Validate the file name
            if (pathinfo($logFile, PATHINFO_EXTENSION) !== 'log') {
                return $this->showError(t('The filename provided must be a valid filename and end with .log'));
            }

            // Validate the file path, create the log file if needed
            if (!file_exists($logFile)) {
                // If the file doesn't exist, make sure we can create one
                if (!is_writable($directory) || !is_dir($directory)) {
                    return $this->showError(t('Log file does not exist on the server. The directory of the file provided must exist and be writable on the web server.'));
                }

User input passed through the “logFile” request parameter is not properly sanitized before being used in a call to the file_exists function. This can be exploited by malicious users to inject arbitrary PHP objects into the application scope (PHP Object Injection via phar:// stream wrapper), allowing them to carry out a variety of attacks, such as executing arbitrary PHP code.

Reproduction Steps:

  1. Login to the Concrete5 instance as an admin user
  2. Go to “System & Settings” -> “Files” -> “Allowed File Types” and add log to File Extensions to Accept
  3. Use the attached Proof of Concept (PoC) script to create a sample Phar file to upload (just run php phar-generator.php from the CLI)
  4. Go to “Files” and upload the phar.log file
  5. Take note of the path where the file has been uploaded (e.g. application/files/4916/0848/5009/phar.log)
  6. Go to “System & Settings” -> “Environment” -> “Logging Settings” and select File as Handler
  7. Put the following string into the File text box: phar://./application/files/4916/0848/5009/phar.log
  8. Click the Save button, go to http://[host]/[concrete5]/application/files/tmp/test.php and you will see a “phpinfo” page

Notes:

The vulnerability has been successfully tested on Concrete5 versions 8.5.4 and 8.5.5 RC1.

Impact

This vulnerability might be abused by malicious users to inject and execute arbitrary PHP code on the web server.
However, successful exploitation requires an admin account, and this partially mitigates the issue.

0.013 Low

EPSS

Percentile

86.1%