Cairn AI Agent Intrusions: Hunt the PHP Uploader Shells


What this means for your clients: criminals are now letting AI agents spend a day probing online shops at what NorForge estimates is a few dollars per attempt, and the file they leave behind can look like an ordinary upload form.
Take a popular online store with enough traffic to make an attacker's shortlist. Before any agent touches it, a script checks that the store really takes orders. Then a set of AI agents gets one goal: find a way to run code on the site without logging in. They try login forms, file uploads, unauthenticated endpoints and deserialization, write down what they learn and try again. NorForge estimates roughly one project in ten succeeds across the clusters it saw. When one does, the agents on average finish in a little under a day, leave a PHP upload form on the server and mark the goal as met.
That is the pattern NorForge describes in "Inside Cairn," published on October 19, 2026. NorForge found more than 20 exposed Cairn panels it judged likely malicious, and those panels showed the targets, the tasks and the results.
How Cairn works
Cairn is an open-source agent harness, a general goal-seeking engine rather than a tool built for attacks. Its author, who posts as le1xia0, wrote on X, as quoted by Reuters, that the platform "was not designed for hacking attacks." Each project gets an origin and a goal. The agents post facts and their next intents to a shared blackboard, and a human can add hints along the way.
NorForge sorts what it saw into three clusters. AIA0001, the largest, is Chinese-language, with 14 panels and more than 1,100 projects, aimed at shops in the US, Canada, Japan and Australia. Its targets were fed in automatically, ranked by traffic between 200,000 and 1.5 million, and pre-checked with Playwright, the browser automation framework, to confirm that orders could be placed.
AIA0002 is English-language, with 10 panels focused on card and crypto theft across payment, gray-market and pharmacy sites. AIA0003 had a single panel and 59 projects, and NorForge rates it malicious only with low confidence. All three looked financially motivated, with no obvious state activity.
The AIA0001 task NorForge published asks for unauthenticated code execution through SQL injection, file upload, deserialization, authentication bypass, template injection or request forgery. Success means landing an uploader shell, a plain HTML form that saves files with PHP's move_uploaded_file, and confirming code execution with whoami or id output. AIA0002 tasks asked for a web shell in a hidden directory deep inside the site, named something ordinary such as confirm.php. In NorForge's hardware parts vendor case, by the agent's own account, the chain combined unauthorized write access to a memcached session store with unsafe PHP object deserialization in legacy Zend Framework components.
Patience is now cheap
Successful AIA0001 projects took a little under 23 hours from start to goal on average, with about 140 facts recorded per project, and one ran for more than five days. NorForge puts the overall success rate around 10% and cautions that the clusters are not directly comparable. It estimates the average task costs about $5 once failed projects are counted, warns that long projects could pass $100, and calls the uncertainty considerable. Snorre Fagerland, NorForge's principal threat researcher, estimated to Reuters that the Chinese-speaking operator's campaign used about $5,000 worth of tokens.
A full day of skilled probing is a lot to spend on a mid-sized shop. With agents, NorForge estimates about $5 per attempt on average, counting the many that end early, and Fagerland told Reuters the campaign's roughly $5,000 in tokens works out to about $50 per successful hack. That is cheap enough to queue more than 1,100 projects. The uploader shell left behind is plain on purpose. NorForge notes the attackers can swap it for something worse at any time.
Autonomous agents do not need a new bug class. Most of what NorForge shows is familiar web attack work, from upload forms to deserialization, though Fagerland told Reuters some of it was "not script kiddie stuff." If you look after a few client storefronts, even the smaller ones are now worth a day of an attacker's effort.
Who was hit, according to Reuters
NorForge did not name victims. Reuters says the busiest operator's agents had attempted more than 1,200 sites and that websites belonging to more than 100 companies were breached, naming Deere, SharkNinja and Cummins. Reuters reports that Deere took "necessary remediation actions" and has "no indication that sensitive information was accessed." SharkNinja said a standalone product-support site was affected and contained. Cummins is investigating a potential attack on a site run by a third-party vendor. Reuters says the extent of any data extraction has not been determined.
NorForge itself fetched one claimed shell at a large hardware parts vendor and found it serving an uploader web shell, and it validated one compromise at a very large US retailer. It says it is working with Reuters to notify victims and is seeking panel takedowns.
The open panels are a second problem
The panels sat open on the internet, and the admin controls appeared open as well, though NorForge did not test them. They exposed target lists, found weaknesses and harvested credentials. NorForge ran Trufflehog over the data and found hundreds of secrets, with 11% verified valid.
NorForge also found what looked like legitimate red team panels on the open internet with real client tests inside. If you hire a pentest firm that uses AI harnesses, ask where the dashboard lives and who can reach it. Any secret you ever handed a tester belongs on your rotation list.
What to change this week
Patch the shop platform, its plugins and its themes, whether that is WordPress, Magento or something else, and remove upload features you do not use.
Block PHP execution in upload, image and cache folders at the web server.
Keep memcached and other session stores off the internet and listening only on localhost or a private network.
If you run Magento, apply Adobe's StyleSmuggler CVE-2026-75650 hotfix. NorForge saw a proof of concept in a worker folder, with no evidence it was used in these intrusions.
Rotate any credential the site holds or that you ever shared with a testing vendor, starting with SMTP, payment and API keys.
Six hunts to run (test first)
These are our own threat hunting templates built from NorForge's findings, and we have not run them on live customer data. Replace each YOUR_* placeholder, confirm field names in your own data and start the window on September 1, 2026. Reuters says the busiest operator began on September 25, so that date leaves some margin. The table after the hunts separates noise from real hits.
Many small shops run on shared hosting with no EDR and no central logs, so the web root and the access logs are the best evidence, which is why Hunt 1 runs on the host. An empty result does not prove a site is clean.
Hunt 1 on the web host: small PHP files that save uploads (test first)
Search 1: small PHP files changed since September 1 that handle uploads
WEBROOT="YOUR_WEBROOT"
find "$WEBROOT" -type f -name '*.php' -newermt '2026-09-01' -size -20k \
-exec grep -lE 'move_uploaded_file|\$_FILES' {} + 2>/dev/nullSearch 2: any PHP inside upload, image, cache or asset folders
WEBROOT="YOUR_WEBROOT"
find "$WEBROOT" -type f -name '*.php' \
\( -path '*/uploads/*' -o -path '*/images/*' -o -path '*/media/*' -o -path '*/cache/*' -o -path '*/assets/*' \) \
-printf '%TY-%Tm-%Td %p\n' 2>/dev/null | sortSearch 3: compare against known good code
(
cd "YOUR_WEBROOT" || exit 1
wp core verify-checksums
wp plugin verify-checksums --all
git status --porcelain 2>/dev/null
)On Windows and IIS, run Get-ChildItem -Path YOUR_WEBROOT -Recurse -Filter *.php | Where-Object { $_.LastWriteTime -ge '2026-09-01' } | Select-String -Pattern 'move_uploaded_file|\$_FILES' -List for the same check. Plugins and Magento modules legitimately call move_uploaded_file, so the question for each hit is whether a known package owns it.
Test first by creating a harmless small .php file in a lab copy that contains the string move_uploaded_file-test and confirming Search 1 finds it. On Magento, use git status or a fresh composer install for the comparison, since the WP-CLI lines only apply to WordPress. Run WP-CLI as the site user, or add --allow-root if you must run it as root.
Hunt 2 in Splunk: new PHP endpoints and the patient source (test first)
Search 1: first-seen PHP paths that receive POST
| tstats summariesonly=false count min(_time) as first_seen values(Web.src) as srcs values(Web.status) as statuses from datamodel=Web where earliest="09/01/2026:00:00:00" Web.http_method="POST" Web.uri_path="*.php" by Web.uri_path
| where first_seen >= relative_time(now(), "-30d")
| sort - first_seenSearch 2: one source touching hundreds of paths over a day or two
| tstats summariesonly=false count from datamodel=Web where earliest="09/01/2026:00:00:00" by _time span=1h Web.src Web.http_user_agent Web.uri_path
| bin _time as day span=1d
| stats dc(Web.uri_path) as paths min(_time) as first max(_time) as last by day Web.src Web.http_user_agent
| eval hours=round((last-first)/3600,1)
| where paths > 300 AND hours >= 6
| sort - pathsThese use the CIM Web data model fields Web.uri_path, Web.http_method, Web.src, Web.status and Web.http_user_agent, so confirm your access logs are mapped before you trust them. Search 1 lists PHP paths whose first POST since September 1 came in the last 30 days, which is where a planted upload form shows up. Search 2 looks at each source one day at a time, so a long run shows up on any day it crosses both thresholds. A run split across midnight can fall under them on both days, so lower the thresholds if your traffic is light. The 300 path threshold and the six hour floor follow the 23 hour pattern NorForge saw and are our tuning, so adjust them to your traffic. Search engines and uptime monitors will show up in Search 2, and a HeadlessChrome user agent alone is noise. Test first by sending a POST to a lab PHP page and confirming it appears in Search 1. If it does not appear, check the data model mapping before you trust an empty result.
Hunt 3 in Elastic and Kibana: POSTs and child processes (test first)
Search 1: POST requests to PHP files
http.request.method:POST and url.path:*.phpSearch 2: the web server starting shells or identity commands
event.category:process and process.parent.name:(php-fpm* or apache2 or httpd or nginx or "w3wp.exe" or "php-cgi.exe") and process.name:(whoami or id or uname or sh or dash or bash or "whoami.exe" or "cmd.exe" or "powershell.exe")These are ECS fields. Search 1 needs leading wildcards allowed in Kibana's advanced settings (query:allowLeadingWildcards), and it works best as a table grouped by url.path with the earliest @timestamp per path. Search 2 needs Elastic Defend or Auditbeat on the web host. PHP sites do run shells for image tools and backups, so name the job behind each row, but whoami or id under the web server account is rare outside authorized testing. Test first by running id from a lab PHP page. An empty result only counts once you know process events arrive from that host.
Hunt 4 in Falcon CQL: web server children (test first)
Search 1: identity and shell commands under the web server
#event_simpleName=ProcessRollup2
| ParentBaseFileName=/^(php-fpm.*|httpd|apache2|nginx|w3wp\.exe|php-cgi\.exe)$/i
| FileName=/^(whoami(\.exe)?|id|uname|sh|dash|bash|md\.exe)$/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])This uses Falcon sensor fields in Next-Gen SIEM. We left out a file-write search because the event name for script writes differs by platform, so check what your Linux sensors record before you add one. Falcon is often absent on shared web hosting, which leaves Hunt 1 as the main check. Test first with id from a lab PHP page, and treat an empty result as proof only of what the sensor sees.
Hunt 5 in Microsoft Defender for Endpoint KQL (test first)
Search 1: the web server running identity commands or shells
DeviceProcessEvents
| where Tmestamp >= ago(30d)
| where InitiatingProcessFileName in~ ("w3wp.exe", "php-cgi.exe", "php-fpm", "httpd", "apache2", "nginx") or InitiatingProcessFileName startswith "php-fpm"
| where FileName in~ ("whoami", "whoami.exe", "id", "uname", "cmd.exe", "powershell.exe", "sh", "dash", "bash")
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName, FileName, ProcessCommandLine
| order by Timestamp ascSearch 2: new PHP files written by the web server
DeviceFileEvents
| where Timestamp >= ago(30d)
| where ActionType in ("FileCreated", "FileRenamed", "FileModified") and FileName endswith ".php"
| where InitiatingProcessFileName in~ ("w3wp.exe", "php-cgi.exe", "php-fpm", "httpd", "apache2", "nginx") or InitiatingProcessFileName startswith "php-fpm"
| project Timestamp, DeviceName, FolderPath, FileName, InitiatingProcessFileName, InitiatingProcessAccountNameSearch 3: connections to the two published staging servers
DeviceNetworkEvents
| where Timestamp >= ago(30d)
| where RemoteIP in ("199.247.25.25", "199.247.27.2")
| project Timestamp, DeviceName, RemoteIP, RemotePort, InitiatingProcessFileName, InitiatingProcessAccountNameThese tables need Defender for Endpoint on the web host, and advanced hunting keeps 30 days, so the September start falls outside it. On Linux, php-fpm worker names can vary, so Searches 1 and 2 also match any initiating process whose name starts with php-fpm. Plugin updates write PHP files, so match Search 2 rows to a maintenance window before you clear them. The two IPs, 199.247.25[.]25 and 199.247.27[.]2, are AIA0002 staging servers that NorForge left unredacted; IPs rotate, so they carry little weight and the behavior searches matter more.
Hunt 6 on your own exposure (test first)
Check your external attack surface for anything you or your testers run with a web dashboard on TCP 8000 and no login, since every Cairn panel NorForge listed answered on that port. Ask your pentest vendor whether they use AI harness dashboards and how those are locked down, and rotate any credential ever shared for a test. Test first by confirming your scanner reports a known internal service on that port.
Interpret before you escalate
Finding | Benign read | Escalate when |
Upload form in an odd folder and the web server account running whoami or id | Authorized testing you scheduled | Treat the host as compromised: preserve it, remove the file, rotate every secret the site holds and find the entry bug |
New PHP file alone | Plugins and modules write PHP during updates | No package owns it, or it sits in an upload, image or cache folder |
One source touching hundreds of paths over a day or two | Search engines, uptime monitors, your own scanners | It also POSTs to a PHP path first seen in that window |
Your own dashboard answering on TCP 8000 with no login | A known internal tool you own | Anyone outside your team can reach it; lock it down and rotate what it holds |
HeadlessChrome user agent alone | Monitoring and testing tools | Only alongside other hits |
Traffic to either staging IP | None we know of | Always |
Empty across all six hunts | Nothing matched the data you have | Not proof: confirm the logs and sensors cover the web host |
Sources
NorForge, Inside Cairn: Open Windows into massive AI-Driven Cyber Operations (October 19, 2026): https://norforge.com/blog/inside_cairn
Reuters, How one hacker used AI agents and a few thousand dollars to break into scores of sites (October 19, 2026, via CNBC TV18 syndication): https://www.cnbctv18.com/technology/how-one-hacker-used-ai-agents-and-a-few-thousand-dollars-to-break-into-scores-of-sites-20015045.htm
SecurityWeek report on the Cairn intrusions (October 20, 2026, secondary, reporting Reuters): https://www.securityweek.com/ai-platform-cairn-abused-to-hack-over-100-organizations/
The Hacker News (October 20, 2026, secondary, reporting Reuters): https://thehackernews.com/2026/10/hackers-use-autonomous-ai-agents-to.html
Splunk, CIM Web data model: https://docs.splunk.com/Documentation/CIM/latest/User/Web
Elastic Common Schema, field reference: https://www.elastic.co/guide/en/ecs/current/ecs-field-reference.html
Microsoft Learn, DeviceProcessEvents table: https://learn.microsoft.com/en-us/defender-xdr/advanced-hunting-deviceprocessevents-table
Microsoft Learn, DeviceFileEvents table: https://learn.microsoft.com/en-us/defender-xdr/advanced-hunting-devicefileevents-table
Microsoft Learn, DeviceNetworkEvents table: https://learn.microsoft.com/en-us/defender-xdr/advanced-hunting-devicenetworkevents-table
What This Means for Your Team
If you run or manage online shops, put them on this week's hunt list, because these campaigns go after exactly that kind of site. Check the web roots for small upload forms, watch for the web server account running identity commands and rotate the secrets those sites hold. Investigate any hit that the interpret table above does not explain as a possible incident, and treat an empty hunt as a coverage question until you know the logs reached the host.
Inception Protection
Inception Protection is the Inception Security managed detection and response service, and it works with the Microsoft licenses you already have. We watch Defender and sign-in data in your Microsoft environment, dig into anything odd and work through containment with your team. An online shop usually sits outside that environment, and its hosting, patching and logs stay with you or your host.
Inception Foresight
A shop or marketing site lives outside your Microsoft tenant, but the SMTP passwords, Microsoft 365 app passwords and API keys it holds can reach back in. To find out whether your Microsoft environment would catch suspicious activity, try the free Inception Foresight M365 Assessment: https://www.inceptionsecurity.com/m365assessment.



