Trust of System Event Data

Description

Trust of System Event Data is a vulnerability that occurs when software relies on system event information—such as window messages, keyboard/mouse events, accessibility callbacks, or UI automation events—for security decisions without proper validation or authentication of the event source. On many platforms, particularly Windows, the event messaging system lacks inherent authentication mechanisms, allowing any application running in the same session to send messages to windows or processes without verification. This architectural limitation enables "Shatter attacks" where malicious applications send spoofed events to higher-privileged applications, manipulating them into performing unauthorized actions. Similarly, accessibility and UI automation frameworks designed to assist users with disabilities can be abused by malware to read sensitive data, inject input, or manipulate applications. The fundamental problem is that applications trust that events originate from legitimate sources such as user input or the operating system when they may actually come from malicious software.

Risk

Trusting system event data enables local privilege escalation, data theft, and security control bypass. Classic Windows Shatter attacks allowed unprivileged applications to execute arbitrary code in the context of system services by sending specially crafted window messages (WM_TIMER, WM_SETTEXT) to privileged processes. While Windows Vista's User Interface Privilege Isolation (UIPI) mitigated many Shatter scenarios, the underlying design pattern remains exploitable in other contexts. Modern attacks abuse accessibility frameworks and UI automation APIs: the Coyote banking malware uses Windows UI Automation to steal credentials while evading all tested EDR solutions. Android banking trojans like FluBot and MysteryBot abuse Accessibility Services to perform keylogging, capture 2FA codes, overlay fake login screens, grant themselves permissions, and block uninstallation. Akamai researchers demonstrated that UI Automation abuse can exfiltrate data from browsers, manipulate chat applications like WhatsApp and Slack, redirect browsers to phishing sites, and harvest credit card information—all without detection by endpoint security products. The attack surface is vast because accessibility and automation frameworks are designed with elevated privileges to interact with other applications.

Solution

Never trust or rely on information from events for security-critical decisions without independent validation. For Windows applications, validate that window messages come from expected sources and avoid processing messages that could lead to code execution (such as WM_TIMER with callbacks) from untrusted origins. Run high-privilege services without GUI components where possible; when GUI interaction is necessary, use separate processes with appropriate integrity levels. Implement User Interface Privilege Isolation (UIPI) by ensuring applications run at appropriate integrity levels. For mobile applications, detect when Accessibility Services are interacting with security-sensitive screens and warn users or require additional verification (e.g., device shake to confirm, as Coinbase does). On Android, use the AccessibilityDataSensitive flag introduced in Android 16 to protect sensitive UI elements. Monitor for unusual use of accessibility and UI automation APIs, including processes loading UIAutomationCore.dll and unexpected named pipe connections. Implement defense in depth: do not assume that the inability to send certain messages provides security guarantees, as bypass techniques continue to evolve.

Common Consequences

ImpactDetails
IntegrityScope: Integrity

Execute Unauthorized Code or Commands - Spoofed events can trigger execution of attacker-controlled code in the context of a privileged process. Shatter attacks historically allowed arbitrary shellcode execution in system services through manipulated WM_TIMER callbacks.
Access ControlScope: Access Control

Gain Privileges or Assume Identity - Attackers can manipulate high-privilege applications through spoofed events to perform privileged operations, effectively escalating their privileges without exploiting traditional memory corruption vulnerabilities.
ConfidentialityScope: Confidentiality

Read Application Data - Accessibility and UI automation frameworks allow reading screen content, input fields, and application data. Malware abusing these frameworks can keylog credentials, steal 2FA codes, and harvest sensitive information from any application.

Example Code

Vulnerable Code

// VULNERABLE: Window procedure that trusts all incoming messages
LRESULT CALLBACK VulnerableWndProc(HWND hwnd, UINT msg,
                                   WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_COPYDATA: {
            // VULNERABLE: Processes data from ANY sender without validation
            COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam;

            // VULNERABLE: Directly executes command from message
            // Any process on same desktop can trigger this
            ExecuteCommand((char*)cds->lpData);
            break;
        }

        case WM_TIMER: {
            // VULNERABLE: Classic Shatter attack vector
            // Attacker can set callback pointer to shellcode
            TIMERPROC callback = (TIMERPROC)lParam;
            if (callback) {
                // VULNERABLE: Executes attacker-controlled function pointer
                callback(hwnd, WM_TIMER, wParam, GetTickCount());
            }
            break;
        }

        case WM_USER + 100: {
            // VULNERABLE: Custom message triggers privileged action
            // No verification of message source
            PerformPrivilegedAction(wParam);
            break;
        }
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}
# VULNERABLE: Android app trusting Accessibility Service events
class VulnerableLoginActivity:
    def on_text_changed(self, event):
        # VULNERABLE: No check if event is from malicious Accessibility Service
        # Keylogger malware can intercept all typed text

        if event.source.resource_id == "password_field":
            password = event.text
            # Password exposed to any Accessibility Service
            self.validate_password(password)

    def on_focus_changed(self, event):
        # VULNERABLE: Malware can detect when sensitive screens open
        # And overlay fake login dialogs
        pass

# VULNERABLE: Desktop automation without security considerations
class VulnerableDesktopApp:
    def handle_automation_event(self, event):
        # VULNERABLE: Trusts all UI Automation events
        # Malware can read sensitive data from any field

        if event.property == "Value.Value":
            # Sensitive data (credit cards, passwords) exposed
            self.process_value(event.new_value)

Fixed Code

// FIXED: Window procedure with message source validation
LRESULT CALLBACK SecureWndProc(HWND hwnd, UINT msg,
                               WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_COPYDATA: {
            // FIXED: Validate sender process
            HWND senderWindow = (HWND)wParam;
            DWORD senderPid;
            GetWindowThreadProcessId(senderWindow, &senderPid);

            // FIXED: Only accept from known trusted processes
            if (!IsProcessTrusted(senderPid)) {
                LogSecurityEvent("Rejected WM_COPYDATA from untrusted PID: %d",
                                 senderPid);
                return 0;
            }

            COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam;

            // FIXED: Validate and sanitize data before use
            if (!ValidateCommandData(cds->lpData, cds->cbData)) {
                return 0;
            }

            // FIXED: Don't execute arbitrary commands - use allowlist
            ProcessAllowedCommand(cds->dwData, cds->lpData);
            break;
        }

        case WM_TIMER: {
            // FIXED: Never use callback from lParam - Shatter attack vector
            // Instead, use timer ID to look up known handlers
            UINT_PTR timerId = wParam;

            // FIXED: Only call registered, known callback functions
            TimerCallback handler = GetRegisteredTimerHandler(timerId);
            if (handler) {
                handler(hwnd, timerId);
            }
            break;
        }

        case WM_USER + 100: {
            // FIXED: Validate message authenticity
            // Consider using separate IPC mechanism with authentication
            if (!ValidatePrivilegedRequest(hwnd, wParam, lParam)) {
                LogSecurityEvent("Rejected unauthorized privileged request");
                return 0;
            }

            PerformPrivilegedAction(wParam);
            break;
        }
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

// FIXED: Check process integrity level (UIPI)
BOOL IsProcessIntegrityValid(DWORD processId) {
    // Processes with lower integrity cannot send messages to higher integrity
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
                                   FALSE, processId);
    if (!hProcess) return FALSE;

    HANDLE hToken;
    if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
        CloseHandle(hProcess);
        return FALSE;
    }

    DWORD integrityLevel = GetProcessIntegrityLevel(hToken);
    CloseHandle(hToken);
    CloseHandle(hProcess);

    // FIXED: Ensure sender has at least our integrity level
    return integrityLevel >= GetCurrentProcessIntegrityLevel();
}
// FIXED: Android app with Accessibility Service abuse detection
public class SecureLoginActivity extends AppCompatActivity {

    private static final String PASSWORD_HINT = "Enter password";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // FIXED: Detect potentially malicious Accessibility Services
        if (isUntrustedAccessibilityServiceEnabled()) {
            showSecurityWarning();
        }

        // FIXED: Mark sensitive fields to prevent accessibility capture
        EditText passwordField = findViewById(R.id.password);

        // Android 16+: Use AccessibilityDataSensitive
        if (Build.VERSION.SDK_INT >= 36) {
            passwordField.setAccessibilityDataSensitive(
                View.ACCESSIBILITY_DATA_SENSITIVE_YES);
        }

        // FIXED: Additional protection - detect automated input
        passwordField.setOnEditorActionListener((v, actionId, event) -> {
            // Verify input comes from real user interaction
            if (event != null && !isGenuineUserInput(event)) {
                logSecurityEvent("Suspicious automated input detected");
                showShakeToConfirmDialog();
                return true;
            }
            return false;
        });
    }

    private boolean isUntrustedAccessibilityServiceEnabled() {
        AccessibilityManager am = getSystemService(AccessibilityManager.class);
        List<AccessibilityServiceInfo> services =
            am.getEnabledAccessibilityServiceList(
                AccessibilityServiceInfo.FEEDBACK_ALL_MASK);

        for (AccessibilityServiceInfo service : services) {
            String packageName = service.getResolveInfo()
                .serviceInfo.packageName;

            // FIXED: Check against allowlist of trusted services
            if (!isTrustedAccessibilityService(packageName)) {
                return true;
            }
        }
        return false;
    }

    private void showShakeToConfirmDialog() {
        // FIXED: Require physical device shake to confirm
        // Malware cannot simulate shake sensor data
        new ShakeToConfirmDialog(this)
            .setMessage("An app is trying to interact with your password. " +
                        "Shake your device to allow.")
            .setOnConfirmed(() -> proceedWithLogin())
            .show();
    }
}

The vulnerable code demonstrates trusting window messages and accessibility events without validation. The fixed code implements sender validation, avoids using message parameters as function pointers (the classic Shatter attack), detects potentially malicious Accessibility Services, and uses shake-to-confirm for sensitive operations that cannot be spoofed by malware.


Exploited in the Wild

Coyote Banking Malware - Windows UI Automation Abuse (Global, 2025)

In February 2025, security researchers identified the Coyote banking malware actively exploiting Windows UI Automation framework to steal credentials—the first documented real-world case of this attack technique. The malware abuses Microsoft's UI Automation framework, originally designed to assist users with disabilities, to read sensitive data from browsers and applications while completely evading endpoint detection and response (EDR) solutions. Akamai researchers had warned about this possibility in December 2024, demonstrating that attackers could exfiltrate data, manipulate internet browsing, execute commands, and read/write messages from applications like WhatsApp and Slack without detection by any tested EDR product. The attack works because UI Automation has elevated permissions to interact with UI elements across processes, and malware leveraging these APIs appears as legitimate accessibility tooling.

FluBot Android Banking Trojan - Accessibility Service Abuse (Europe, 2021)

FluBot, one of the most prolific Android banking trojans, extensively abused Accessibility Services to perform malicious actions while appearing as a legitimate package delivery notification app. Once users granted Accessibility permissions, FluBot could read all screen content including passwords and 2FA codes, overlay fake login screens over banking apps to harvest credentials, intercept and forward SMS messages, grant itself additional permissions without user interaction, disable Google Play Protect, and prevent its own uninstallation by automatically pressing "back" when users tried to view its app info screen. The malware spread rapidly across Europe in 2021, primarily through SMS phishing campaigns. Its success demonstrated how accessibility frameworks designed for legitimate purposes can be weaponized for comprehensive device compromise.


Tools to test/exploit

  • UIAutomationSpy — Microsoft's Accessibility Insights tool that can inspect UI Automation elements, useful for understanding what data is exposed to accessibility clients.

  • Shatter attack PoC tools — Proof-of-concept tools demonstrating classic Windows Shatter attack techniques for security testing legacy applications.

  • AccessibilityService analyzer — Tool for analyzing Android Accessibility Service usage and detecting potentially malicious implementations.


CVE Examples

  • CVE-2004-0213 — Attacker used Shatter attack to bypass GUI-enforced protection, enabling privilege escalation through spoofed window messages.

  • CVE-2002-0864 — Windows Utility Manager allowed local users to execute arbitrary code via a specially crafted message, demonstrating Shatter attack exploitation.

  • CVE-2019-1388 — Windows UAC privilege escalation through UI manipulation, allowing attackers to spawn elevated processes through dialog interaction.


References

  1. MITRE Corporation. "CWE-360: Trust of System Event Data." https://cwe.mitre.org/data/definitions/360.html

  2. Akamai. "Teaching an Old Framework New Tricks: The Dangers of Windows UI Automation." December 2024. https://www.akamai.com/blog/security-research/2024-december-windows-ui-automation-attack-technique-evades-edr

  3. Chris Paget. "Exploiting design flaws in the Win32 API for privilege escalation - Shatter Attacks." August 2002. https://www.helpnetsecurity.com/2002/08/08/exploiting-design-flaws-in-the-win32-api-for-privilege-escalation-shatter-attacks-how-to-break-windows/

  4. SRLabs. "When your phone gets sick: FluBot abuses Accessibility features to steal data." https://www.srlabs.de/blog-post/flubot-abuses-accessibility-features-to-steal-data