<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://0xkeval.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://0xkeval.github.io/" rel="alternate" type="text/html" /><updated>2026-10-28T14:30:14+00:00</updated><id>https://0xkeval.github.io/feed.xml</id><title type="html">0xKeval</title><subtitle>Malware analysis, Vulnerability analysis and Threat Intelligence investigations</subtitle><author><name>Andrea Naspi</name></author><entry><title type="html">Demystifying Qilin Ransomware</title><link href="https://0xkeval.github.io/malware%20analysis/Qilin/" rel="alternate" type="text/html" title="Demystifying Qilin Ransomware" /><published>2026-10-27T00:00:00+00:00</published><updated>2026-10-27T00:00:00+00:00</updated><id>https://0xkeval.github.io/malware%20analysis/Qilin</id><content type="html" xml:base="https://0xkeval.github.io/malware%20analysis/Qilin/"><![CDATA[<p>Over the past year, <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.agendacrypt">Qilin</a>, also known as Agenda and AgendaCrypt, has established itself as one of the most prominent ransomware operations in the threat landscape. Operating under a <a href="https://en.wikipedia.org/wiki/Ransomware_as_a_service">Ransomware-as-a-Service (RaaS)</a> model, the group has demonstrated a steady evolution in both its malware capabilities and affiliate ecosystem, allowing it to target organizations across multiple sectors and geographies.</p>

<p>Qilin’s operations are supported by resilient infrastructure, including services associated with bulletproof hosting providers. This infrastructure powers the group’s <a href="https://en.wikipedia.org/wiki/Tor_(software)">Tor</a> data leak site, which forms a key component of its double-extortion model by publicly naming victims and publishing stolen data to increase pressure during ransomware negotiations.</p>

<p><a href="/assets/images/qilin/qilin_portal.png" class="full"><img src="/assets/images/qilin/qilin_portal.png" alt="1" /></a></p>

<p>Qilin follows a largely opportunistic targeting strategy, showing little preference for specific industries or countries. Its victims span multiple sectors, including manufacturing, healthcare, technology, and professional services, with organizations across North America, Europe, and other regions appearing on its leak site.</p>

<p>The wide range of affected industries and regions is also reflected in public ransomware tracking data. In fact, according to the <a href="https://www.ransom-db.com/threat-groups">Ransom-DB</a> statistics, Qilin consistently ranks among the most active ransomware operations, recording a high volume of claimed victims compared to other major ransomware groups. This sustained activity highlights both the effectiveness of its affiliate ecosystem and its ability to maintain a steady stream of successful intrusions across diverse targets.</p>

<p><a href="/assets/images/qilin/qilin_victim.png" class="full"><img src="/assets/images/qilin/qilin_victim.png" alt="2" /></a></p>

<p>One notable aspect of Qilin’s evolution is the adoption of multiple platforms and programming languages. The ransomware is available in both Windows and Linux / ESXi variants and has evolved from its original <a href="https://en.wikipedia.org/wiki/Go_(programming_language)">Golang</a> implementation toward a more recent <a href="https://en.wikipedia.org/wiki/Rust_(programming_language)">Rust</a> version. While both variants share the same core functionality, the Rust implementation has become increasingly prevalent in recent campaigns, likely due to its performance benefits and the additional challenges it presents to reverse engineers. Although Qilin actively targets both Windows and Linux/ESXi environments, this analysis primarily focuses on the Windows variant, as it is the version most commonly observed in real-world intrusions and provides the largest attack surface for enterprise environments.</p>

<h1 id="initial-access">Initial Access</h1>

<p>The initial access techniques employed by Qilin affiliates have evolved over time. Historically, the group relied heavily on phishing campaigns, Business Email Compromise (BEC) operations, and the acquisition of valid credentials from Initial Access Brokers (IABs) to gain a foothold within victim environments.</p>

<p>More recently, however, Qilin operators and affiliates have increasingly shifted toward the exploitation of <a href="https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures">publicly disclosed vulnerabilities</a>, particularly those affecting internet-facing appliances, VPN gateways, backup infrastructure, and enterprise management platforms.</p>

<p>Notable and recent vulnerabilities linked to Qilin intrusions include:</p>
<ul>
  <li><a href="https://nvd.nist.gov/vuln/detail/cve-2026-0257">CVE-2026-0257</a> - Palo Alto Networks PAN-OS / Prisma Access authentication bypass.</li>
  <li><a href="https://nvd.nist.gov/vuln/detail/cve-2026-5075">CVE-2026-5075</a> - Check Point Remote Access &amp; Mobile Access VPN authentication bypass.</li>
  <li><a href="https://nvd.nist.gov/vuln/detail/cve-2026-20079">CVE-2026-20079</a> + <a href="https://nvd.nist.gov/vuln/detail/cve-2026-2036">CVE-2026-2036</a> - Cisco Secure Firewall Management Center (FMC) authentication bypass.</li>
</ul>

<h1 id="windows-encryptor">Windows Encryptor</h1>

<p>The Windows variant of Qilin is distributed as a 32-bit Portable Executable (PE), typically ranging between 2 and 4 MB in size. In many observed samples, the payload is compressed using the <a href="https://upx.github.io/">UPX packer</a>, likely to reduce its size and complicate static analysis. Since the ransomware is written in Rust, execution does not immediately reach the ransomware logic; instead, the PE entry point traverses the standard <a href="https://en.wikipedia.org/wiki/MinGW">MinGW</a> startup routines before invoking the Rust <code class="language-plaintext highlighter-rouge">main()</code> function. Additionally, TLS callbacks are used to perform runtime initialization and cleanup tasks before and after the core ransomware functionality executes.</p>

<p>Qilin supports numerous command-line arguments that allow affiliates to customize its behavior during execution. Notably, the ransomware requires a password to be supplied through the <code class="language-plaintext highlighter-rouge">--password</code> parameter, which acts as a prerequisite for execution.</p>

<p><a href="/assets/images/qilin/qilin_run.png" class="full"><img src="/assets/images/qilin/qilin_run.png" alt="3" /></a></p>

<p>Beyond this requirement, operators can configure delayed execution (<code class="language-plaintext highlighter-rouge">--timer</code>), restrict encryption to specific paths or hosts (<code class="language-plaintext highlighter-rouge">--paths</code>, <code class="language-plaintext highlighter-rouge">--ips</code>), enable lateral movement across Windows, ESXi, and vCenter environments (<code class="language-plaintext highlighter-rouge">--spread</code>, <code class="language-plaintext highlighter-rouge">--spread-vcenter</code>), disable safety checks and anti-analysis features (<code class="language-plaintext highlighter-rouge">--no-vm</code>, <code class="language-plaintext highlighter-rouge">--no-sandbox</code>), suppress ransomware notes and visual artifacts (<code class="language-plaintext highlighter-rouge">--no-note</code>, <code class="language-plaintext highlighter-rouge">--no-wallpaper</code>), reboot systems into Safe Mode (<code class="language-plaintext highlighter-rouge">--safe</code>), destroy cluster environments (<code class="language-plaintext highlighter-rouge">--kill-cluster</code>), skip local or network encryption targets, archive operational logs, or perform a complete encryption simulation through a dedicated <code class="language-plaintext highlighter-rouge">--dry-run</code> mode.</p>

<p>Unfortunately, the use of Rust significantly complicates reverse engineering due to the large amount of compiler-generated code, complex control flow, and extensive runtime components embedded within the binary. As a result, distinguishing malicious functionality from legitimate runtime logic can be challenging and time-consuming. Therefore, rather than providing a function-by-function breakdown, this analysis focuses on the ransomware’s core capabilities and execution workflow.</p>

<p><a href="/assets/images/qilin/qilin_flow.png" class="full"><img src="/assets/images/qilin/qilin_flow.png" alt="4" /></a></p>

<h3 id="recovery-inhibition-routine">Recovery Inhibition Routine</h3>

<p>At the start of the <code class="language-plaintext highlighter-rouge">main()</code> function, the ransomware launches a separate thread for process and service interference. That thread handles processes first, then services. The main thread continues without waiting for it, so interference can overlap the delay and need not finish before encryption begins.</p>

<p>AFter setting up the thread, the launcher attempts to delete the shadow copies creating a recognizable child process through the command <code class="language-plaintext highlighter-rouge">cmd.exe /C vssadmin.exe delete shadows /all /quiet</code>. Additionally, on WOW64, the program attempts to disable filesystem redirection around that command. This is necessary because WOW64 transparently redirects access from <code class="language-plaintext highlighter-rouge">C:\Windows\System32</code> to the 32-bit SysWOW64 directory, potentially causing the process to interact with 32-bit system components rather than the native 64-bit binaries. By disabling redirection, Qilin ensures that the legitimate 64-bit <code class="language-plaintext highlighter-rouge">vssadmin.exe</code> is executed successfully.</p>

<p><a href="/assets/images/qilin/qilin_vss.png" class="full"><img src="/assets/images/qilin/qilin_vss.png" alt="5" /></a></p>

<h3 id="processes-and-services-termination">Processes and Services Termination</h3>

<p>The separate interference thread handles processes before services, though either operation can fail or be delayed by the host.</p>

<p>The process path call the <code class="language-plaintext highlighter-rouge">EnumProcesses</code> API with a fixed 16 KiB buffer. The resulting processes are matched through case-insensitive regular expressions against a predefined list of processes that could interfere with file encryption or maintain locks on valuable data. The target list includes productivity applications such as Microsoft Outlook, Microsoft Word, Excel, and PowerPoint, database-related processes such as Oracle, SQL Server, as well as virtualization and management components including Hyper-V. The matching processes are terminated with a call to the <code class="language-plaintext highlighter-rouge">TerminateProcess</code> API with the <code class="language-plaintext highlighter-rouge">PROCESS_TERMINATE</code> flag.</p>

<p><a href="/assets/images/qilin/qilin_proc.png" class="full"><img src="/assets/images/qilin/qilin_proc.png" alt="5" /></a></p>

<p>In addition to processes, Qilin also tries to terminate a predefined list of Windows services primarly associated to backup solutions, database platforms, email infrastructure, and enterprise applications, including Veeam, Acronis, Microsoft Exchange, SQL Server, SAP, and Commvault components. The service inventory call the <code class="language-plaintext highlighter-rouge">EnumServicesStatusW</code> API and, similarly to the process inventory, matches the desired services through case-insensitive regular expressions. The matching services are teminated with a call to the <code class="language-plaintext highlighter-rouge">ChangeServiceConfigW</code> API with the <code class="language-plaintext highlighter-rouge">SERVICE_DISABLED</code> flag.</p>

<p><a href="/assets/images/qilin/qilin_service.png" class="full"><img src="/assets/images/qilin/qilin_service.png" alt="6" /></a></p>

<h3 id="storage-discovery">Storage Discovery</h3>

<p>When explicit paths or hosts are supplied through the command-line parameters, the encryptor foillows those targets. Otherwise, Qilin enumerates both local and remote storage resources to maximize the impact of the encryption process. For local storage discovery, the ransomware leverages the <code class="language-plaintext highlighter-rouge">GetLogicalDrives</code> API, which returns a bitmask representing all logical drives currently accessible on the system, including fixed disks, removable media, and mapped drives. In parallel, Qilin uses the <code class="language-plaintext highlighter-rouge">NetShareEnum</code> API to enumerate network shares exposed by remote systems, allowing it to identify additional storage locations that may be accessible through the compromised user context.</p>

<p><a href="/assets/images/qilin/qilin_net.png" class="full"><img src="/assets/images/qilin/qilin_net.png" alt="7" /></a></p>

<p>To maximize encryption coverage while preserving system stability, Qilin implements multiple layers of filtering based on file extensions, directory names, and specific filenames. The ransomware excludes a large number of extensions associated with operating system components and executables, such as .dll, .exe, .sys, .drv, .msi, .bat, and .cmd, preventing the accidental corruption of files required for continued execution of Windows and the ransomware itself. Additionally, the ransomware skips critical operating system locations such as Windows, System Volume Information, Boot, Program Files, Program Files (x86), ProgramData, AppData, SysVol, and NetLogon, as well as directories related to browsers and common applications. Likewise, it excludes important system files including bootmgr, ntldr, boot.ini, ntuser.dat, desktop.ini, and thumbs.db.</p>

<h3 id="encryption-routine">Encryption Routine</h3>

<p>Like most modern ransomware families, Qilin implements a hybrid encryption scheme that combines the speed of symmetric cryptography with the secure key management provided by asymmetric cryptography. Specifically, the ransomware leverages ChaCha20 to encrypt victim files and RSA to protect the encryption material required for recovery.</p>

<p>The encryptor uses standard 20-round ChaCha20. Its state constants decode to <code class="language-plaintext highlighter-rouge">expand 32-byte k</code>, and the round function uses the 16/12/8/7 rotation schedule. To ensure randomness for each encrypted file, Qilin generates a unique ChaCha20 key and nonce through a thread-local <a href="https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator">CSPRNG (Cryptographically Secure Pseudo-Random Number Generator)</a> with a 32 bytes seded from the <code class="language-plaintext highlighter-rouge">BCryptGenRandom</code> API.</p>

<p><a href="/assets/images/qilin/qilin_chacha.png" class="full"><img src="/assets/images/qilin/qilin_chacha.png" alt="8" /></a></p>

<p>Since ChaCha20 is a symmetric algorithm, the same key required to encrypt the file is also required to decrypt it. Simply storing this key alongside the encrypted data would allow defenders to recover the file without interacting with the attackers. To prevent this, Qilin encrypts the ChaCha20 key material using an embedded RSA public key and appends the resulting encrypted blob to the end of the encrypted file together with other metadata.</p>

<p>Upon successfull encryption, the ransomware adds a per-victim / per-campaign extension to the encrypted files and, for each directory, drops the ransomware note (usually named <code class="language-plaintext highlighter-rouge">README-RECOVER-*.txt</code>) containing victim-specific information and payment instructions for accessing the operators TOR-based negotiation portal.</p>

<p><a href="/assets/images/qilin/qilin_note.png" class="full"><img src="/assets/images/qilin/qilin_note.png" alt="9" /></a></p>

<h3 id="detection-opportunities">Detection Opportunities</h3>

<p>From a detection perspective, YARA rules remain one of the most effective mechanisms for identifying Qilin samples, particularly during static analysis. Despite the use of Rust and, in some cases, UPX packing, many samples contain highly distinctive strings that are rarely encountered in legitimate software. Examples include debug and error messages such as <code class="language-plaintext highlighter-rouge">[FATAL] provide password with --password before start</code>, operational artifacts like <code class="language-plaintext highlighter-rouge">vssadmin.exe delete shadows /all /quiet</code>, and Rust source-code paths embedded in the binary, including <code class="language-plaintext highlighter-rouge">encryptor/src/config/embedded_config.rs</code> and <code class="language-plaintext highlighter-rouge">/usr/src/myapp/file_encryption/src/lib.rs</code>.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">rule</span> <span class="n">MALWARE_Win_Qilin</span> <span class="p">{</span>
	<span class="nl">meta:</span>
		<span class="n">author</span> <span class="o">=</span> <span class="s">"Andrea Naspi"</span>
		<span class="n">date</span> <span class="o">=</span> <span class="s">"2026-10-28"</span>
		<span class="n">description</span> <span class="o">=</span> <span class="s">"Detects the Qilin Rust-based Windows encryptor and decryptor"</span>
		<span class="n">tlp</span> <span class="o">=</span> <span class="s">"green"</span>
		<span class="n">version</span> <span class="o">=</span> <span class="s">"1.0"</span>
		<span class="n">id</span> <span class="o">=</span> <span class="s">"845f6412-c1a3-42c9-861c-6a6625881693"</span>
		<span class="n">hash</span> <span class="o">=</span> <span class="s">"37546b811e369547c8bd631fa4399730d3bdaff635e744d83632b74f44f56cf6"</span>
		<span class="n">hash</span> <span class="o">=</span> <span class="s">"f910b2a6d84d0677cda9aefabfa4a45863ba51a8831588e3b527e8e1d3a9927c"</span>
		<span class="n">packed_hash</span> <span class="o">=</span> <span class="s">"650a03c40c45eef3590058c37de8ea2e978c9c69f289390b2ab89be3910549fb"</span>
		
	<span class="nl">strings:</span>
		<span class="c1">// Rust-based artifacts</span>
		<span class="err">$</span><span class="n">rust_1</span> <span class="o">=</span> <span class="s">"RUST_BACKTRACE"</span> <span class="n">ascii</span>
		<span class="err">$</span><span class="n">rust_2</span> <span class="o">=</span> <span class="s">"Local</span><span class="se">\\</span><span class="s">RustBacktraceMutex"</span> <span class="n">ascii</span> 
		<span class="c1">// Rust source code paths</span>
		<span class="err">$</span><span class="n">path_1</span> <span class="o">=</span> <span class="s">"/usr/src/myapp/file_encryption/src/lib.rs"</span> <span class="n">ascii</span> 
		<span class="err">$</span><span class="n">path_2</span> <span class="o">=</span> <span class="s">"/usr/src/myapp/rsa/src/oaep.rs"</span> <span class="n">ascii</span> 
		<span class="err">$</span><span class="n">path_3</span> <span class="o">=</span> <span class="s">"decryptor/src/pipelines/decryption_pipeline.rs"</span> <span class="n">ascii</span> 
		<span class="c1">// Operational artifacts </span>
		<span class="err">$</span><span class="n">cmd</span> <span class="o">=</span> <span class="s">"vssadmin.exe delete shadows /all /quiet"</span> <span class="n">ascii</span>
		<span class="c1">// Debug-related strings </span>
		<span class="err">$</span><span class="n">debug_1</span> <span class="o">=</span> <span class="s">"provide password with `--password` before start"</span> <span class="n">ascii</span> 
		<span class="err">$</span><span class="n">debug_2</span> <span class="o">=</span> <span class="s">"Cannot parse public key"</span> <span class="n">ascii</span>
		<span class="err">$</span><span class="n">debug_3</span> <span class="o">=</span> <span class="s">"45 seconds before encrypt"</span> <span class="n">ascii</span> 
		<span class="err">$</span><span class="n">debug_4</span> <span class="o">=</span> <span class="s">"Waiting for all encryption jobs to complete"</span> <span class="n">ascii</span>
		<span class="err">$</span><span class="n">debug_5</span> <span class="o">=</span> <span class="s">"File was encrypted with ChaCha20"</span> <span class="n">ascii</span> 
		<span class="err">$</span><span class="n">debug_6</span> <span class="o">=</span> <span class="s">"File was encrypted with AES-CTR"</span> <span class="n">ascii</span> 


	<span class="nl">condition:</span> 
		<span class="n">uint16</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mh">0x5A4D</span> <span class="n">and</span>
		<span class="n">uint32</span><span class="p">(</span><span class="n">uint32</span><span class="p">(</span><span class="mh">0x3c</span><span class="p">))</span> <span class="o">==</span> <span class="mh">0x00004550</span> <span class="n">and</span>
		<span class="n">filesize</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="n">MB</span> <span class="n">and</span> 
		<span class="n">any</span> <span class="n">of</span> <span class="p">(</span><span class="err">$</span><span class="n">rust_</span><span class="o">*</span><span class="p">)</span> <span class="n">and</span> 
		<span class="p">(</span>
			<span class="n">any</span> <span class="n">of</span> <span class="p">(</span><span class="err">$</span><span class="n">path_</span><span class="o">*</span><span class="p">)</span> <span class="n">or</span> 
			<span class="err">$</span><span class="n">cmd</span> 
		<span class="p">)</span> <span class="n">and</span> 
		<span class="mi">2</span> <span class="n">of</span> <span class="p">(</span><span class="err">$</span><span class="n">debug_</span><span class="o">*</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Because Qilin samples are frequently distributed in a UPX-packed form, static detection alone may not always be sufficient, particularly when adversaries modify or repackage the payload. For this reason, host-based telemetry should complement signature-based detection strategies. Behavioral indicators such as the deletion of the shadow copies, the termination of backup and database services, mass file modifications, and the creation of ransomware notes can provide high-fidelity detection opportunities.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">title</span><span class="pi">:</span> <span class="s">Qilin ransomware - shadow copies deletion</span>
<span class="na">id</span><span class="pi">:</span> <span class="s">27ab652e-909d-486f-966a-f9d7460e3c78</span>
<span class="na">status</span><span class="pi">:</span> <span class="s">experimental</span>
<span class="na">description</span><span class="pi">:</span> <span class="s">Detects the usage of vssadmin.exe to delete the shadow copies</span>
<span class="na">author</span><span class="pi">:</span> <span class="s">Andrea Naspi</span>
<span class="na">date</span><span class="pi">:</span> <span class="s">2026-10-28</span>
<span class="na">logsource</span><span class="pi">:</span>
  <span class="na">product</span><span class="pi">:</span> <span class="s">windows</span>
  <span class="na">category</span><span class="pi">:</span> <span class="s">process_creation</span>
<span class="na">detection</span><span class="pi">:</span>
<span class="err">	</span><span class="na">selection_img</span><span class="pi">:</span>
<span class="err">		</span><span class="na">Image|endswith</span><span class="pi">:</span>
<span class="err">			</span><span class="pi">-</span> <span class="s1">'</span><span class="s">\powershell.exe'</span>
<span class="err">			</span><span class="pi">-</span> <span class="s1">'</span><span class="s">\cmd.exe'</span>
<span class="err">			</span><span class="pi">-</span> <span class="s1">'</span><span class="s">\wmic.exe'</span>
<span class="err">			</span><span class="pi">-</span> <span class="s1">'</span><span class="s">\vssadmin.exe'</span>
<span class="err">			</span><span class="pi">-</span> <span class="s1">'</span><span class="s">\diskshadow.exe'</span>
<span class="err">	</span><span class="na">selection_cli</span><span class="pi">:</span>
<span class="err">		</span><span class="na">CommandLine|contains|all</span><span class="pi">:</span>
<span class="err">			</span><span class="pi">-</span> <span class="s1">'</span><span class="s">shadow'</span>
<span class="err">			</span><span class="pi">-</span> <span class="s1">'</span><span class="s">delete'</span>
  <span class="na">condition</span><span class="pi">:</span> <span class="s">selection_img and selection_cli</span>
<span class="na">level</span><span class="pi">:</span> <span class="s">high</span>
<span class="na">falsepositives</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="s">Legitimate administrator deletes Shadow Copies using operating systems utilities for legitimate reason</span>
<span class="na">tags</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="s">tlp.green</span>
  <span class="pi">-</span> <span class="s">attack.impact</span>
  <span class="pi">-</span> <span class="s">attack.t1490</span>
</code></pre></div></div>]]></content><author><name>Andrea Naspi</name></author><category term="Malware Analysis" /><summary type="html"><![CDATA[Over the past year, Qilin, also known as Agenda and AgendaCrypt, has established itself as one of the most prominent ransomware operations in the threat landscape. Operating under a Ransomware-as-a-Service (RaaS) model, the group has demonstrated a steady evolution in both its malware capabilities and affiliate ecosystem, allowing it to target organizations across multiple sectors and geographies.]]></summary></entry><entry><title type="html">PHP2Shell: Wrong Turn, Right Shell</title><link href="https://0xkeval.github.io/vulnerability%20analysis/PHP2Shell/" rel="alternate" type="text/html" title="PHP2Shell: Wrong Turn, Right Shell" /><published>2026-10-24T00:00:00+00:00</published><updated>2026-10-24T00:00:00+00:00</updated><id>https://0xkeval.github.io/vulnerability%20analysis/PHP2Shell</id><content type="html" xml:base="https://0xkeval.github.io/vulnerability%20analysis/PHP2Shell/"><![CDATA[<p><strong>PHP2Shell</strong> is a family of critical vulnerabilities in core PHP, tracked as <a href="https://nvd.nist.gov/vuln/detail/cve-2026-109618">CVE-2026-109618</a> and <a href="https://nvd.nist.gov/vuln/detail/cve-2026-109619">CVE-2026-109619</a>, that were recently patched with severity scores reaching CVSS 9.2. These flaws can allow unauthenticated attackers to achieve remote code execution or disclose sensitive process memory. The issues are particularly significant because PHP remains the dominant server-side language on the web, powering roughly 70% of websites with a known server-side technology, making the potential attack surface exceptionally large.</p>

<p><strong>CVE-2026-109618</strong> is a critical remote code execution vulnerability in PHP’s out-of-memory handling. Under specific conditions, memory exhaustion can interrupt request initialization and leave internal data structures in an inconsistent state, ultimately leading to memory corruption and potential code execution.</p>

<p><strong>CVE-2026-109619</strong> is a remote code execution vulnerability caused by stale request state persisting after its associated memory has been freed. When a subsequent request reuses the same worker, these dangling references can trigger a use-after-free condition, potentially resulting in memory disclosure, memory corruption, and remote code execution.</p>

<p>The official <a href="https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp">PHP security advisory</a> identifies the following affected versions:</p>
<ul>
  <li>8.2 releases before 8.2.35</li>
  <li>8.3 releases before 8.3.36</li>
  <li>8.4 releases before 8.4.27</li>
  <li>8.5 releases before 8.5.12</li>
</ul>

<p>Every SAPI that serves web requests is affected: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed.</p>

<h1 id="cve-2026-109618">CVE-2026-109618</h1>

<p><a href="https://nvd.nist.gov/vuln/detail/cve-2026-109618">CVE-2026-109618</a> is a critical memory-safety vulnerability in PHP’s request lifecycle. When PHP encounters an out-of-memory condition, it uses <code class="language-plaintext highlighter-rouge">longjmp()</code> through <code class="language-plaintext highlighter-rouge">zend_bailout()</code> to immediately abort the current execution context. However, certain request-processing paths can expose partially initialized internal structures before they are fully constructed. If an allocation fails at exactly that point, execution is aborted prematurely, leaving request state in an inconsistent condition. During request shutdown, PHP later treats this corrupted state as valid, resulting in memory corruption that can ultimately lead to remote code execution.</p>

<p>Instead of unwinding the stack normally, <code class="language-plaintext highlighter-rouge">longjmp()</code> transfers control directly to a recovery point. While this allows PHP to recover quickly from fatal conditions such as OOM errors, it also means that the intermediate cleanup logic is skipped and partially initialized structures are not rolled back.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Request startup
    |
    +--&gt; Allocate structure A
    |
    +--&gt; Partially initialize structure A
    |
    +--&gt; Another allocation fails
             |
             +--&gt; zend_bailout()
                     |
                     +--&gt; Skips remaining initialization
                     |
                     +--&gt; Request shutdown executes
                                 |
                                 +--&gt; Uses structure A
                                      believing it is valid
</code></pre></div></div>

<p>The problem is, request-owned memory can be reachable before it is fully initialized. If an allocation fails during that window (for example while the multipart parser is building request state), the <code class="language-plaintext highlighter-rouge">longjmp()</code> leaves that memory in a half-initialized, invalid condition. Request shutdown then runs and reads or branches on that invalid state. Because an attacker can steer which allocation fails (by tuning <code class="language-plaintext highlighter-rouge">memory_limit</code> against a crafted request body), the “invalid state” becomes attacker-influenced, and that is the corruption primitive.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* php/php-src/Zend/zend_alloc.c - PHP 8.4.4 (vulnerable code) */</span>
<span class="k">static</span> <span class="n">ZEND_COLD</span> <span class="n">ZEND_NORETURN</span> <span class="kt">void</span> <span class="nf">zend_mm_safe_error</span><span class="p">(</span><span class="n">zend_mm_heap</span> <span class="o">*</span><span class="n">heap</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">format</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">limit</span><span class="p">,</span> <span class="cm">/* ... */</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">heap</span><span class="o">-&gt;</span><span class="n">overflow</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
    <span class="n">zend_try</span> <span class="p">{</span>
        <span class="n">zend_error_noreturn</span><span class="p">(</span><span class="n">E_ERROR</span><span class="p">,</span> <span class="n">format</span><span class="p">,</span> <span class="n">limit</span><span class="p">,</span> <span class="cm">/* ... */</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
    <span class="p">}</span> 
	<span class="n">zend_catch</span> <span class="p">{</span>
    <span class="p">}</span>  <span class="n">zend_end_try</span><span class="p">();</span>
    <span class="n">heap</span><span class="o">-&gt;</span><span class="n">overflow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">zend_bailout</span><span class="p">();</span>
    <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The danger is the <code class="language-plaintext highlighter-rouge">zend_bailout()</code> on a stack where request memory is only partially set up. The jump skips the code that would have finished initializing or validating that memory, and later shutdown consumes it.</p>

<p>According to the <a href="https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp">PHP security advisory</a>, researchers identified several ways to trigger memory exhaustion during multipart HTTP request processing:</p>
<ul>
  <li>Multipart requests without a usable Content-Length</li>
  <li>Excessive multipart headers</li>
  <li>Empty file-upload controls and nested fields</li>
</ul>

<h1 id="cve-2026-109619">CVE-2026-109619</h1>

<p>While <a href="https://nvd.nist.gov/vuln/detail/cve-2026-109618">CVE-2026-109618</a> is about partially initialized state caused by OOM bailouts, <a href="https://nvd.nist.gov/vuln/detail/cve-2026-109619">CVE-2026-109619</a> is about stale state surviving after its memory has been freed.</p>

<p>PHP workers are long-lived processes that maintain global state across multiple requests, some of which temporarily reference request-specific memory. <a href="https://nvd.nist.gov/vuln/detail/cve-2026-109619">CVE-2026-109619</a> occurs when this state is not properly cleared, either because fatal errors bypass the normal cleanup process or because shutdown routines inadvertently restore previously reset data. As a result, global references can persist after the underlying request memory has been freed, leaving behind dangling pointers that may later be dereferenced by subsequent requests, resulting in a use-after-free condition.</p>

<p>When the same worker later processes a new request, those stale references may be dereferenced before normal request initialization has an opportunity to rebuild or clear them. This can occur in several early-execution code paths, including the <code class="language-plaintext highlighter-rouge">fatal_error_backtraces</code> functionality in PHP 8.5. As a result, PHP may access memory that no longer belongs to the original request, triggering a use-after-free vulnerability.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Request A
    |
    +--&gt; Allocate request memory
    |
    +--&gt; Global state references request data
    |
    +--&gt; Request ends
    |
    +--&gt; Request memory freed
    |
    +--&gt; Global reference survives
           (dangling pointer)
                  |
                  v
Request B
    |
    +--&gt; Reuses same PHP worker
    |
    +--&gt; Accesses stale global state
    |
    +--&gt; Use-after-free
    |
    +--&gt; Memory disclosure / corruption
    |
    +--&gt; Potential RCE
</code></pre></div></div>

<p>According to the <a href="https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp">PHP security advisory</a>, researchers identified two distinct way to trigger the use-after-free vulnerability:</p>
<ul>
  <li>Fatal error backtraces (in PHP 8.5 against Apache mod_php while <code class="language-plaintext highlighter-rouge">fatal_error_backtraces</code> is enabled)</li>
  <li>Session upload progress (against Apache mod_php and PHP-FPM)</li>
</ul>

<h1 id="proof-of-concept-poc">Proof of Concept (PoC)</h1>

<p>Multiple exploitation techniques have been developed for PHP2Shell, demonstrating that both vulnerabilities can be weaponized through different code paths and runtime conditions. For researchers interested in understanding the original disclosure and exploitation methodology, the first publicly released proof-of-concept was published by <a href="https://x.com/acd421">@acd421</a> and <a href="https://x.com/ArchKnight23">@Archknight23</a> at <a href="https://jackalsyn.com/posts/php-up-2026.html">https://jackalsyn.com/posts/php-up-2026.html</a>.</p>

<p><a href="/assets/images/php2shell/poc.jpg" class="full"><img src="/assets/images/php2shell/poc.jpg" alt="1" /></a></p>

<p>While subsequent research has produced more reliable and mature exploitation techniques, a more recent and stable implementation can be found in the Metasploit Framework module at <a href="https://github.com/rapid7/metasploit-framework/pull/22036">https://github.com/rapid7/metasploit-framework/pull/22036</a>, which serves as a useful reference for defenders and security researchers studying the practical impact of these flaws.</p>

<h1 id="mitigation-and-detection-strategies">Mitigation and Detection Strategies</h1>

<p>The first priority would be to identify every PHP server in the environment and, where a system is vulnerable, patch it immediately (version 8.5.12, 8.4.27, 8.3.36 and 8.2.35). Both vulnerabilities are exploitable without authentication, and some attack chains require no application-level flaw, so a single unpatched or forgotten host is enough to give an attacker a foothold.</p>

<p>Asset discovery should extend beyond production web servers:</p>
<ul>
  <li>Bare-metal and virtual hosts running Apache mod_php or PHP-FPM</li>
  <li>Container images and base layers, including outdated tags that remain deployed</li>
  <li>Third-party and self-hosted applications built on PHP, such as CMS platforms, admin panels and ticketing systems</li>
</ul>

<p>An high fidelity scanner to identify such vulnerable applications have already been published by <a href="https://www.slcyber.io/research/high-fidelity-detection-mechanism-for-php2shell-cve-2026-109618-and-cve-2026-109619">Searchlight Labs</a> at <a href="https://github.com/assetnote/php2shell-scanner">https://github.com/assetnote/php2shell-scanner</a>.</p>

<p>Configuration changes reduce exposure but don’t remove the bug. The memory corruption behind <a href="https://nvd.nist.gov/vuln/detail/cve-2026-109618">CVE-2026-109618</a> lives in the Zend engine itself. If you can’t patch today, apply these as a stopgap:</p>

<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">session.upload_progress.enabled</span> <span class="p">=</span> <span class="s">Off</span>
<span class="py">session.use_only_cookies</span> <span class="p">=</span> <span class="s">On</span>
</code></pre></div></div>

<p>Regarding detection strategies, the quickest control is to check and block suspicious network communications with unexpected fields like the presence of <code class="language-plaintext highlighter-rouge">PHP_SESSION_UPLOAD_PROGRESS</code> or <code class="language-plaintext highlighter-rouge">PHPSESSID</code> (usually set as a <code class="language-plaintext highlighter-rouge">Cookie</code> header) in <code class="language-plaintext highlighter-rouge">POST</code> bodies.</p>

<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">alert</span> <span class="n">http</span> $<span class="n">EXTERNAL_NET</span> <span class="n">any</span> -&gt; $<span class="n">HOME_NET</span> <span class="n">any</span> ( \
    <span class="n">msg</span>:<span class="s2">"PHP2Shell exploitation attempt - multipart request with PHP_SESSION_UPLOAD_PROGRESS in POST body."</span>; \
    <span class="n">flow</span>:<span class="n">established</span>,<span class="n">to_server</span>; \
    <span class="n">http</span>.<span class="n">method</span>; <span class="n">content</span>:<span class="s2">"POST"</span>; \
    <span class="n">http</span>.<span class="n">content_type</span>; <span class="n">content</span>:<span class="s2">"multipart/form-data"</span>; \
    <span class="n">http</span>.<span class="n">request_body</span>; <span class="n">content</span>:<span class="s2">"PHP_SESSION_UPLOAD_PROGRESS"</span>; \
    <span class="n">sid</span>:<span class="m">1000001</span>; <span class="n">rev</span>:<span class="m">1</span>; \
    <span class="n">priority</span>:<span class="m">10</span>; \
    <span class="n">metadata</span>: <span class="n">tlp</span> <span class="n">green</span>, <span class="n">author</span> <span class="n">Andrea</span> <span class="n">Naspi</span>, <span class="n">created_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>, <span class="n">updated_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109618</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109619</span>;
)

<span class="n">alert</span> <span class="n">http</span> $<span class="n">EXTERNAL_NET</span> <span class="n">any</span> -&gt; $<span class="n">HOME_NET</span> <span class="n">any</span> ( \
    <span class="n">msg</span>:<span class="s2">"PHP2Shell exploitation attempt - multipart request with PHPSESSID in POST body."</span>; \
    <span class="n">flow</span>:<span class="n">established</span>,<span class="n">to_server</span>; \
    <span class="n">http</span>.<span class="n">method</span>; <span class="n">content</span>:<span class="s2">"POST"</span>; \
    <span class="n">http</span>.<span class="n">content_type</span>; <span class="n">content</span>:<span class="s2">"multipart/form-data"</span>; \
    <span class="n">http</span>.<span class="n">request_body</span>; <span class="n">content</span>:<span class="s2">"name=|22|PHPSESSID|22|"</span>; \
    <span class="n">sid</span>:<span class="m">1000002</span>; <span class="n">rev</span>:<span class="m">1</span>; \
    <span class="n">priority</span>:<span class="m">10</span>; \
    <span class="n">metadata</span>: <span class="n">tlp</span> <span class="n">green</span>, <span class="n">author</span> <span class="n">Andrea</span> <span class="n">Naspi</span>, <span class="n">created_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>, <span class="n">updated_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109618</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109619</span>;
)
</code></pre></div></div>

<p>As discussed during the <a href="https://nvd.nist.gov/vuln/detail/cve-2026-109618">CVE-2026-109618</a> technical analysis, extra checks with a lower severity can be added to monitor and block possible attempts to trigger the OOM bypass like checking for abnormally long filenames during <code class="language-plaintext highlighter-rouge">PHP_SESSION_UPLOAD_PROGRESS</code> requests or checking for missing <code class="language-plaintext highlighter-rouge">Content-Length</code> fields.</p>

<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">alert</span> <span class="n">http</span> $<span class="n">EXTERNAL_NET</span> <span class="n">any</span> -&gt; $<span class="n">HOME_NET</span> <span class="n">any</span> ( \
    <span class="n">msg</span>:<span class="s2">"PHP2Shell exploitation attempt - multipart PHP_SESSION_UPLOAD_PROGRESS request with abnormally long filename."</span>; \
    <span class="n">flow</span>:<span class="n">established</span>,<span class="n">to_server</span>; \
    <span class="n">http</span>.<span class="n">method</span>; <span class="n">content</span>:<span class="s2">"POST"</span>; \
    <span class="n">http</span>.<span class="n">content_type</span>; <span class="n">content</span>:<span class="s2">"multipart/form-data"</span>; \
    <span class="n">http</span>.<span class="n">request_body</span>; <span class="n">content</span>:<span class="s2">"PHP_SESSION_UPLOAD_PROGRESS"</span>; \
    <span class="n">http</span>.<span class="n">request_body</span>; <span class="n">content</span>:<span class="s2">"filename=|22|"</span>; \
    <span class="n">isdataat</span>:<span class="m">10000</span>,<span class="n">relative</span>; \
    <span class="n">sid</span>:<span class="m">1000003</span>; <span class="n">rev</span>:<span class="m">1</span>; \
    <span class="n">priority</span>:<span class="m">5</span>; \
    <span class="n">metadata</span>: <span class="n">tlp</span> <span class="n">green</span>, <span class="n">author</span> <span class="n">Andrea</span> <span class="n">Naspi</span>, <span class="n">created_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>, <span class="n">updated_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109618</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109619</span>;
)

<span class="n">alert</span> <span class="n">http</span> $<span class="n">EXTERNAL_NET</span> <span class="n">any</span> -&gt; $<span class="n">HOME_NET</span> <span class="n">any</span> ( \
    <span class="n">msg</span>:<span class="s2">"PHP2Shell exploitation attempt - missing Content-Length field."</span>; \
    <span class="n">flow</span>:<span class="n">established</span>,<span class="n">to_server</span>; \
    <span class="n">http</span>.<span class="n">method</span>; <span class="n">content</span>:<span class="s2">"POST"</span>; \
    <span class="n">http</span>.<span class="n">content_type</span>; <span class="n">content</span>:<span class="s2">"multipart/form-data"</span>; \
    <span class="n">http</span>.<span class="n">header</span>; <span class="n">content</span>:<span class="s2">"Transfer-Encoding"</span>; <span class="n">content</span>:<span class="s2">"chunked"</span>; \
    <span class="n">sid</span>:<span class="m">1000004</span>; <span class="n">rev</span>:<span class="m">1</span>; \
    <span class="n">priority</span>:<span class="m">5</span>; \
    <span class="n">metadata</span>: <span class="n">tlp</span> <span class="n">green</span>, <span class="n">author</span> <span class="n">Andrea</span> <span class="n">Naspi</span>, <span class="n">created_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>, <span class="n">updated_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109618</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109619</span>;
)
</code></pre></div></div>

<p>Obviously, it’s also possible to check for the <a href="https://nvd.nist.gov/vuln/detail/cve-2026-109618">CVE-2026-109618</a> OOM bypass attempts based on the server responses and checking for OOM-related errors like “Allowed memory size of %zu bytes exhausted”.</p>

<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">alert</span> <span class="n">http</span> $<span class="n">HOME_NET</span> <span class="n">any</span> -&gt; $<span class="n">EXTERNAL_NET</span> <span class="n">any</span> ( \
    <span class="n">msg</span>:<span class="s2">"PHP2Shell OOM bypass attempt."</span>; \
    <span class="n">flow</span>:<span class="n">established</span>,<span class="n">to_client</span>; \
    <span class="n">http</span>.<span class="n">response_body</span>; <span class="n">content</span>:<span class="s2">"Allowed memory size"</span>; \
    <span class="n">content</span>:<span class="s2">"exhausted"</span>; <span class="n">distance</span>:<span class="m">0</span>; <span class="n">within</span>:<span class="m">100</span>; \
    <span class="n">sid</span>:<span class="m">1000004</span>; <span class="n">rev</span>:<span class="m">1</span>; \
    <span class="n">priority</span>:<span class="m">10</span>; \
    <span class="n">metadata</span>: <span class="n">tlp</span> <span class="n">green</span>, <span class="n">author</span> <span class="n">Andrea</span> <span class="n">Naspi</span>, <span class="n">created_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>, <span class="n">updated_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109618</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109619</span>;
)

<span class="n">alert</span> <span class="n">http</span> $<span class="n">HOME_NET</span> <span class="n">any</span> -&gt; $<span class="n">EXTERNAL_NET</span> <span class="n">any</span> ( \
    <span class="n">msg</span>:<span class="s2">"PHP2Shell OOM bypass attempt."</span>; \
    <span class="n">flow</span>:<span class="n">established</span>,<span class="n">to_client</span>; \
    <span class="n">http</span>.<span class="n">response_body</span>; <span class="n">content</span>:<span class="s2">"Session object destruction failed"</span>; \
    <span class="n">sid</span>:<span class="m">1000005</span>; <span class="n">rev</span>:<span class="m">1</span>; \
    <span class="n">priority</span>:<span class="m">10</span>; \
    <span class="n">metadata</span>: <span class="n">tlp</span> <span class="n">green</span>, <span class="n">author</span> <span class="n">Andrea</span> <span class="n">Naspi</span>, <span class="n">created_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>, <span class="n">updated_at</span> <span class="m">2026</span><span class="err">_</span><span class="m">10</span><span class="err">_</span><span class="m">24</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109618</span>; \
    <span class="n">reference</span>:<span class="n">cve</span>,<span class="m">2026</span>-<span class="m">109619</span>;
)
</code></pre></div></div>

<p>In conclusion, network-level detection should be complemented by host-based telemetry, since exploitation attempts that evade or bypass perimeter controls will still leave traces on the system. The priority would certainly be to monitor for shells spawned by PHP processes itself: an attacker can abuse an exploited Apache mod_php or PHP worker to spawn a shell as a child process for subsequent remote code execution activities.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">title</span><span class="pi">:</span> <span class="s">PHP2Shell post-exploitation - shell through PHP process</span>
<span class="na">id</span><span class="pi">:</span> <span class="s">aef58c14-c269-401f-871b-4735d37eee49</span>
<span class="na">status</span><span class="pi">:</span> <span class="s">experimental</span>
<span class="na">description</span><span class="pi">:</span> <span class="s">Detects a shell spawned as a child process of a PHP worker</span>
<span class="na">author</span><span class="pi">:</span> <span class="s">Andrea Naspi</span>
<span class="na">date</span><span class="pi">:</span> <span class="s">2026-10-24</span>
<span class="na">logsource</span><span class="pi">:</span>
  <span class="na">product</span><span class="pi">:</span> <span class="s">linux</span>
  <span class="na">category</span><span class="pi">:</span> <span class="s">process_creation</span>
<span class="na">detection</span><span class="pi">:</span>
  <span class="na">selection_php</span><span class="pi">:</span>
    <span class="na">ParentImage|endswith</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/php-fpm'</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/php-cgi'</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/php'</span>
  <span class="na">selection_rce</span><span class="pi">:</span>
    <span class="na">Image|endswith</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/sh'</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/bash'</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/python'</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/perl'</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/ruby'</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/nc'</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/ncat'</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/curl'</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">/wget'</span>
  <span class="na">condition</span><span class="pi">:</span> <span class="s">selection_php and selection_rce</span>
<span class="na">level</span><span class="pi">:</span> <span class="s">high</span>
<span class="na">falsepositives</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="s">PHP applications that legitimately exec shell commands (cron jobs, image processing)</span>
<span class="na">tags</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="s">tlp.green</span>
  <span class="pi">-</span> <span class="s">attack.execution</span>
  <span class="pi">-</span> <span class="s">attack.t1059</span>
</code></pre></div></div>

<p>Another good coverage for the host-based telemetry to directly spot PHP log patterns associated with the PHP2Shell exploitation attempts is available through the official <a href="https://github.com/SigmaHQ/sigma">SigmaHQ repository</a> at <a href="https://github.com/SigmaHQ/sigma/pull/6506">https://github.com/SigmaHQ/sigma/pull/6506</a>.</p>]]></content><author><name>Andrea Naspi</name></author><category term="Vulnerability Analysis" /><summary type="html"><![CDATA[PHP2Shell is a family of critical vulnerabilities in core PHP, tracked as CVE-2026-109618 and CVE-2026-109619, that were recently patched with severity scores reaching CVSS 9.2. These flaws can allow unauthenticated attackers to achieve remote code execution or disclose sensitive process memory. The issues are particularly significant because PHP remains the dominant server-side language on the web, powering roughly 70% of websites with a known server-side technology, making the potential attack surface exceptionally large.]]></summary></entry></feed>