Authored by Ian Lin, Director of Research and Development at Packetlabs.
Developer tools in organizations play an important role in automating, operating, and developing an organization’s business functions. The use and abuse of these common tools also play an essential role in an adversary’s ability to achieve initial access, persistence, and lateral movement.
This post will examine how a Python application whitelist led to a cascading compromise of an organization's security stack.
The originality of this idea did not first occur within Packetlabs; it was in a 2022 DEFCON conference talk a researcher by the name of Diego Capriotti (@naksyn) presented on the viability of utilizing a signed interpreter for EDR evasion.
As adversaries, finding methods and techniques to operate under the purview of detection and alerts becomes valuable as organizations mature their security stack. However, in many organizations, developer tools are often overlooked for what code they run. In some instances, we’ve found companies to go as far as to whitelist Python executables for the endpoint agent or on the corporate firewalls.
Checking what developer tools are allowed outbound gives an insight into what an organization may or may not allow in their environments. Even though sometimes cmd.exe or powershell.exe are blocked, signed interpreters like python.exe remain reliable for developers and attackers to execute untrusted code.
A threat actor group dubbed UAC-0184 is one of many instances where they’ve leveraged Python executables in their malware infection chain. Specifically, this actor has been found to target Ukrainian organizations in Finland and has been observed using the Remcos RAT to drop Python-related files to avoid detection.
In that case, security products are unlikely to alert on a binary commonly classified as benignware when used maliciously. Additionally, when organizations use Python for legitimate business or custom internal applications, this further adds to the complexity of detection.
The Windows operating system enables applications to load dynamic link libraries (DLLs) during runtime. A DLL is a library that contains code and data that can be used by more than one program at the same time. Applications can dictate the location of the DLLs by providing a full path, using DLL redirection, or incorporating a manifest. Otherwise, Windows will search for the DLL in a specific sequence of predefined directories.
Why is DLL sideloading a continuous bane of existence for antivirus and endpoint protection software vendors? This is because traditional detection strategies involve whole-file hash generation, which is a common method for creating file signatures. This can also be done sectionally (such as .text, .rdata, and data). Furthermore, process hash generation can also be done by the anti-malware software, taking the digital fingerprint of a specific process executable file. When DLL sideloading is successfully executed, the digital fingerprint of the binary executable would still match the legitimate version of the binary. Unless anti-malware software matches and compares every single DLL that is loaded upon application run-time, it would be difficult to capture when an application is loading a potentially malicious DLL.
Furthermore, DLL sideloading exists in various default and third-party applications. To monitor for each and every one would add unnecessary processing on endpoints and servers. With a popular project called HijackLibs (an open-source project for keeping track of publicly disclosed DLL hijacking opportunities), Microsoft has 429 DLLs that adversaries can leverage. Beyond that, multiple software vendors have affected DLLs in their applications. Threat groups have also been found to leverage undisclosed DLLs in their complex infection chains.
There are several ways to run a Python interpreter in native Windows environments. The most common method is to run the MSI installer and add the Python binary folder to the Windows environment paths. However, on the official Python website, there is another way to run Python without the need for installation.
Developer tools would be difficult to install in mature environments where an approval process enforces application installation. With embedded packages, this control can be circumvented.
The Windows-embedded package is a zip file that contains a signed Python interpreter binary and the DLLs required to run its code.
This is further confirmed by utilizing Microsoft Sysinternals’ Process Monitor to verify that the python.exe binary image loads. It runs various DLLs from the C:\Windows\System32 directory, but within the downloads folder, it loads vcruntime140.dll and python311.dll.
In essence, adversaries and threat groups can replace the legitimate Python DLL with a custom-crafted DLL.
Due to how easy and flexible higher-level languages like Python have become, they are easily adopted in many software, engineering, manufacturing, and technology industries. One problem with this is the whitelisting of Python.exe in such organizations. In one such organization, there was a strict requirement to complete our tasks undetected without alerting the SOC/SIEM.
During the initial reconnaissance from the perspective of a compromised external contractor, it was identified that many development websites, such as (www.java.com and www.ruby-lang.com) were specifically blocked from the ForcePoint DLP. However, python.org was allowed through. This is an indicator that developers within the organization may use Python as part of their business operations and development process. In short, developers need to request whitelisting or administrative permissions to run and test their development code before they push it into production. Without a good baseline and understanding of what Python does in an environment, it can easily allow attackers to blend.
By bringing our own Python package, we were able to execute the sideload without any alerts from Microsoft Defender for Endpoint, a fully updated version with real-time protection, cloud-delivered protection, automatic sample submission, and no system exclusions.
The sideload can connect back to an attacker-controlled command and control server, and from this vantage point, the threat group can continue to load their tradecraft to enumerate, exploit, and deepen their access with this trivial sideload.
Another interesting scenario that we often execute in our purple teams is the ability to run signature tooling such as Bloodhound. Bloodhound is a tool for managing attack paths that leverages graph theory to uncover hidden relationships, user permissions, sessions, and potential attack vectors within a Windows domain.
Typically, running Bloodhound by dropping its collector binaries would often be a tell-tale sign to the Blue Team that Active Directory enumeration is taking place. With Microsoft Defender for Endpoint installed in a custom-built environment, the SharpHound.exe collector is often flagged. Even with custom obfuscation of the binary, there is still sufficient difficulty in getting the binary to run in environments configured with application control (preventing unsigned executables from running is a common control).
However, the Python variant of Bloodhound authored by Jan Mollema (@dirkjanm) does not appear to be flagged within Microsoft Defender for Endpoint (and a good number of other EDR vendors). This is likely due to the lack of optics for the default python.exe binary and the lack of auditing capabilities by default (pointed out by @naksyn).
While Bloodhound collection for Active Directory is not always necessary, it has become a common step for speeding up the discovery of potential abuse paths. Diego Capriotti's (@naksyn) tool Pyramid has made executing Bloodhound from a Windows workstation context without the use of a C2 and evading EDR sensors extremely effective. Launching a server to run the Pyramid server component and pasting the base64 encoded string on the client target works.
Since on-the-fly encryption and the decoding and decryption of its Python modules allow one to avoid creating uncommon process relationships and allow the Python binary to appear like legitimate usage, this results in a successful Bloodhound run on a workstation configured with Microsoft Defender for Endpoint.
If your organization also utilizes developer tools like Python, ask your team the following:
Does your organization also utilize developer tools like Python?
What kind of baselines have been drawn?
Do audits occur on which users or groups need to run this binary, or does a single IT help desk request give access to this powerful binary?
Can developers building Python applications use it for nefarious purposes?
What optics exist for python.exe to communicate with the Internet?
These questions are important to ask when establishing an appropriate baseline.
Reach out to see how Purple Teaming can help your organization stay ahead of sophisticated threats and under gaps in creating baselines in your environment.
Find Risks Before They Become Threats
December 10 - Blog
Hardware token protocols: what are they, and what role do they play in your organization's cybersecurity? In today's article, our ethical hackers outline the most common hardware token protocols.
October 24 - Blog
Packetlabs is thrilled to have been a part of SecTor 2024. Learn more about our top takeaway's from this year's Black Hat event.
September 27 - Blog
InfoStealer malware plays a key role in many cyber attacks, enabling extortion and lateral movement via stolen credentials. Learn the fundamentals about InfoStealers in this article.
© 2024 Packetlabs. All rights reserved.