October 28, 2026
Monitoring Application Execution and Exploit Vigilance
Or: as if I wasn’t paranoid enough, AI had to start poking around in PHP

By Martin Ruppersburg
7 min read
Unless you're getting overtime or extra contract work, it's a bad time to be a PHP developer.
I've worked with a lot of SMEs. Not all have the time and resources to implement all the security they need.
I've had loosely coupled code to monitor potential intruders. Admitedly, without the resources behind it, this code was akin to deploying the Buzz Lightyear Room Guard. But something is better than nothing.
As developers, we don't always have the ability to change things, but we can try to work with a shift-left philosophy: consider security implementation in the first instance, not as an afterthought.
(For those using right-to-left languages… shift-right, else it'll look like I'm telling you it's the last thing you should think about)
Time to consolidate my code.
The Last Bastion
Even after implementing every security measure we can, including authentication, authorisation, and firewalls, there's still a chance that someone or something could find a way through.
Mrbr.Bastion watches and waits. It checks every application that runs and everything installed and saved on your server. If something is out of place, Bastion will warn you. Your predetermined responses could include killing and blocking anything that looks unfriendly. Define your policies before an incident. Have your business defences and continuity plans in place before any issues arise. Let your support team work on the issue, rather than run the gauntlet of deciding whether they need to take a server offline.
An application can be installed without running. Another can be running without appearing in the installed applications list. A perfectly legitimate application can also be persuaded to do something its developer would rather it did not, including starting another application with an entirely different set of ambitions.
A web server opening a command prompt, for example, deserves a little curiosity.
That gap between the software we think we have and the activity taking place on the machine is what interests me here.
tl;dr: I built Bastion to collect evidence about installed software, running applications, and reported parent/child process relationships on Windows. It brings those observations together with potential vulnerability exposure, so there is something concrete to investigate when software appears to be doing an unexpected job.
The source is available at github.com/mrbrirup/Mrbr.Bastion
Installed Applications
The first question is straightforward: what software is present?
Bastion reads Windows application registration information from the uninstall registry entries, covering the 32-bit and 64-bit views. Collection can include the current user's entries as well as the machine entries.
This provides a useful starting point, but it has a boundary. Software does not have to introduce itself to Windows through an installer.
A portable application can be extracted from an archive. A runtime can arrive inside another product. An old executable can remain in a deployment directory long after somebody has updated the application they remember installing.
The inventory therefore also supports explicitly configured file and archive scans. These work within chosen roots and limits, retain checkpoints, and inspect discovered files without executing them. Where available, executable metadata supplies product and version information; file hashes provide another way to identify the bytes observed.
I want to know where a finding came from. A registered application, a file found in an archive, and an executable observed through a running process provide different kinds of evidence. Treating them as interchangeable would make the list neater and the conclusions less useful.
An inaccessible directory or unreadable file also leaves a gap. Bastion records coverage problems so that an incomplete scan does not quietly become a reassuring empty result.
Running Applications
The next question is what software is running.
That changes the usefulness of the inventory. An old executable sitting in a folder and that same executable serving requests are different operational concerns. Both may deserve attention, but the running instance adds urgency and context.
Bastion takes periodic process inventories and inspects the executable behind a process where access permits. These observations can include its path, metadata, hash, and process start time.
Periodic inventory has an obvious weakness: things happen between visits.
A process can start, do its work, and disappear before the next scan. Shortening the interval helps, but it still leaves gaps between observations.
For live process activity, Bastion uses Event Tracing for Windows, usually shortened to ETW. The collector observes process lifecycle events, including starts and stops, and can take an initial view of processes already present when collection begins.
Live process events must be enabled explicitly in the inventory agent configuration. They are disabled in the example configuration, and kernel ETW collection requires an elevated process. A default periodic inventory should not be mistaken for continuous observation of process launches.
Even live collection has limits. A short-lived or protected process may disappear or deny access before its executable can be inspected. Collection queues can also fill. Those conditions belong in the evidence alongside the software observations.
Parent and Child Processes
Knowing that an application ran is useful. Knowing the reported parent of that process adds another question: how did it get here?
Consider this hypothetical Windows process chain:
php-cgi.exe
cmd.exe
powershell.exephp-cgi.exe
cmd.exe
powershell.exeThis illustrates a relationship worth investigating. Identifying a particular exploit would require further evidence.
Each executable may have a legitimate purpose. The question is whether this sequence belongs in the workload being observed. A deployment script, an administrative task, or an application feature may explain it. An unexpected launch from a service that normally has no reason to create a shell deserves closer examination.
The same reasoning applies beyond the immediate child. A shell may launch a utility, which may launch something else. Looking only at the last process name loses the context that made its appearance interesting.
Bastion retains known parent context with process observations, including identifiers, timestamps, names, and executable paths where available. It also distinguishes process lifetimes, because Windows can reuse a process ID after the original process has exited.
That detail matters when looking backwards. The process currently using PID 1234 may have nothing to do with the process that used PID 1234 earlier.
There are limits to reconstructing the relationship. A process already running when collection starts may have a recorded parent PID without enough evidence to bind it to a particular historical parent instance. Bastion leaves that context unresolved rather than attaching it to whichever process happens to hold the number now.
These are reported parent relationships. They provide investigation context; they do not, by themselves, establish the cause or legitimacy of an action.
Why PHP Makes the Question Immediate
The recent PHP vulnerabilities give this work a particularly relevant example.
On 21 October 2026, PHP disclosed two critical vulnerabilities, CVE-2026–109618 and CVE-2026–109619, which can allow unauthenticated remote code execution. The vendor advisory covers PHP installations serving web requests and describes the affected execution paths. PHP security advisory
CISA's corresponding guidance calls for organisations to inventory PHP, including instances embedded in other software, and monitor for suspicious activity such as PHP worker processes launching shells or downloading tools. CISA advisory
That connects the three areas directly:
- Find the software, including copies hidden inside another application's deployment.
- Establish whether a relevant executable has been observed running.
- Examine unexpected process launches and their reported parent context.
The example is useful because the work starts before the incident investigation. An organisation first needs to know whether the runtime is present and where it is being used.
Bastion's observations can help with those questions. Establishing that a particular vulnerability was exploited still requires further evidence. An attacker may also execute code inside an existing process without creating an obvious child process, so process relationships cover only part of the problem.
The PHP guidance has continued to change since the initial disclosure. Follow its current vendor announcements for patching guidance.
Potential Exposure
The software observations also feed vulnerability correlation.
Bastion uses reviewed mappings between observed software identities and Common Platform Enumeration identifiers, or CPEs. It then evaluates the available version and applicability information against cached vulnerability records from the National Vulnerability Database.
The review step matters. A similar product name is a weak basis for deciding that an application is affected. Even a matching product and version may leave configuration or environmental requirements unresolved.
The results preserve that uncertainty. They distinguish potential exposure, no match within the evaluated coverage, and unknown coverage. Stale inventory, unavailable version information, and incomplete intelligence affect the finding.
This also keeps two different questions separate. Potentially vulnerable software may be present before any breach. Suspicious runtime activity may be observed after an attacker has gained execution. Connecting the evidence helps an investigation, but neither observation automatically proves the other.
Why Last Bastion
Bastion is short for Last Bastion, the final defence behind the lines of system boundaries and firewalls.
The name reflects an uncomfortable possibility: by the time an unexpected process relationship attracts attention, somebody may already have crossed the boundary we hoped would keep them out.
That makes retaining the observations part of the job.
Bastion writes signed batches to durable local SQLite outboxes and supports delivery to a central receiver, which verifies the blocks and returns signed receipts. Hash chaining helps make changes to the retained sequence detectable. Pending evidence can wait locally through a receiver outage, within configured storage limits.
Those mechanisms protect specific evidence-handling boundaries. A signature authenticates a reporting key; it cannot establish that a compromised endpoint reported the whole truth. Likewise, the monitoring-health view describes the condition of the collection pipeline. It cannot certify that the machine is safe.
The project also collects file activity, which can provide supporting context around a process, such as the files it was observed reading or writing.
Where the Project Stands
The current release is a source-only developer MVP. The Windows collectors and inventory sources are implemented, along with central inventory views, retained parent context, and potential exposure findings. The build currently uses a pinned .NET 11 RC3 SDK.
The next investigation work includes better event search, parent/child navigation, and rules that can turn selected suspicious relationships into reviewable alerts. Automatic classification of unexpected child processes remains future work. The current system retains evidence for examination and provides monitoring-health and software-exposure alerts.
Collection is passive. Bastion does not terminate processes or quarantine applications. Unattended production use also needs further capacity, deployment, recovery, and security validation.
The project README, configuration guide , and functionality assessment describe the setup and remaining work.
The Next Security Question
My KeyManager and EncryptionManager work grew from concerns about protecting data and preparing for post-quantum cryptography. I still consider that work important.
For now, Bastion feels more immediately relevant to the conversations I want to have with organisations. The operational question is easier to put in front of somebody: can we identify the software running on our machines, and retain enough context to investigate an unexpected process?
As developers we have a duty of care to keep our systems as secure as possible. Not an easy task, there a myriad components in our encvrionment, different software, versions, configurations. Hopefully this project will help you either in part or in whole. Either way this latest exploit, with the potential to affect 70% of websites, and even though I haven't written PHP for many years, this gave me the impetus to consolidate a code collection into something more comprehensive.