At 03:15:36 AEDT on 22 October 2026, a client at 94.154.43.7 made a GET request to one of our honeypots. About 1.4 seconds later, it sent a multipart POST to / on port 8080. The upload had 151 file entries with empty filenames. Their field names nested 60 bracket levels deep.
The timing stood out. PHP had disclosed two critical request-handling vulnerabilities the day before. Our capture ends before the upload finishes.
The request that reached one of our honeypots
The request arrived over plain HTTP. The client sent this user-agent string: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36. The TCP signature was 1460|7|1|1|64240|0x02. There was no TLS on this connection.
We saved the first 64 KB (65,536 bytes) of the request. It showed two fields, PHP_SESSION_UPLOAD_PROGRESS and PHPSESSID, plus 151 file entries with empty filenames. The first 150 files were complete and empty. The capture ended 25 bytes into the last file, before the closing multipart boundary. The application logger saved no body and reported a read error. A separate front-end observer saved the prefix.
On a PHP server, the parser still processes each part name and builds nested request data, even when a file is empty. Body structure can matter as much as body size. We classified this as a PHP2Shell-style probe.
Our WAF logs also showed upload-progress probes earlier that morning.
Why PHP request parsing matters
On 21 October, PHP released fixes in versions 8.2.35, 8.3.36, 8.4.27 and 8.5.12. CVE-2026-109618 concerns out-of-memory handling when request data is only partly initialized. CVE-2026-109619 concerns memory left over from an earlier request. PHP says an attack can happen before application code runs. Apache mod_php has the highest demonstrated risk. Other serving modes have different exposure. PHP's release notice recommends updating.
Upgrade to a fixed release or a vendor package confirmed to include the fixes, then restart PHP workers. PHP recommends updating as the complete remediation. Request-size and multipart limits can help while an update is arranged, but they do not replace it.
Reading multipart traffic carefully
Things to look out for
Compare multipart requests with the application's normal uploads. Many empty file entries, deeply nested field names, unusually many headers, or an upload-progress field can be worth investigating. A GET just before an upload can be useful context, but it does not prove intent.
Keep body captures bounded. Record how many bytes were saved, whether the body was complete, and whether parsing reached the fields a rule checks. The front end may save a prefix when the application logger cannot save the body. Keep those records distinct.
What your rules could miss
A rule for PHP_SESSION_UPLOAD_PROGRESS must match the name configured on the server. PHP uses this name by default, and administrators can change it with session.upload_progress.name. PHP documents the setting. Check the server's configuration before blocking the field.
Choose nesting and multipart thresholds that fit real uploads. Rules that inspect fields after body parsing cannot see parts that an earlier size or parser limit stopped. Keep parser errors visible. The PHP advisories also describe problems beyond upload progress, so a rule for one field cannot cover every case.
Watch for evolving attacks
This request combined an upload-progress field with many nested file entries. New scanner versions could change the field names, use different multipart layouts or target other PHP parsing paths. Watch for those changes as the tools develop. Changing a submitted field name alone does not turn on upload progress if PHP is configured to use another name.
Patch PHP first. Set body-size and multipart limits that fit the application. Review parser errors and keep enough bounded evidence to understand what reached PHP. Revisit the limits when the application or PHP configuration changes.
Connection fingerprints
We calculated these JA4H values from the saved HTTP headers using FoxIO's reference implementation. The final row is from the honeypot. The others are from WAF probes. TLS values are included where they were recorded.
| HTTP JA4H | HTTP header order | TLS JA4 seen in group |
|---|---|---|
po11nn060000_84bafeeaa541_000000000000_000000000000 |
Host, User-Agent, Connection, Content-Length, Accept, Content-Type | t13d131100_f57a46bbacb6_ab7e3b40a677 |
po11nn060000_4ea4093e6290_000000000000_000000000000 |
Host, User-Agent, Connection, Content-Length, Content-Type, Accept-Encoding | t13d131200_f57a46bbacb6_9249cab70c77 |
po11nn060000_5c15dc981d69_000000000000_000000000000 |
Host, User-Agent, Connection, Accept, Content-Type, Content-Length | t13d911100_0d5420ba6086_ec21bdc2dd35 |
po11nn050000_197af124696f_000000000000_000000000000 |
Host, User-Agent, Connection, Content-Type, Content-Length | t13d171200_ab0a1bf427ad_ecd0401ec68b |
po11nn060000_d09ed10a732b_000000000000_000000000000 |
Host, User-Agent, Accept, Content-Type, Transfer-Encoding, Connection | Not applicable; plaintext HTTP |
Probes from 160.187.210.214 and 169.58.51.5 used the same TCP settings as the honeypot request. Their HTTP fingerprints were different. TCP settings give us a broad grouping clue.
Some WAF records look like scanner checks. Several source addresses sent the same small body, headers and browser string. Another request used the user-agent Mozilla/5.0 (php2shell-check/1.0). These details help with log searches. Check each request before acting on its source address.
Observed source addresses
These addresses appeared in upload-progress probes between 00:00 AEDT on 21 October and 09:00 AEDT on 22 October 2026, or in the honeypot request at 03:15 AEDT on 22 October. Use them to search logs and review each request before blocking an address.
2.27.152.153 13.143.120.218 23.27.75.120 23.27.203.212
23.236.222.100 24.144.109.162 31.56.137.245 31.56.138.52
31.58.9.242 31.58.20.52 31.58.148.208 31.59.27.195
34.87.183.75 38.154.233.215 43.229.11.209 45.38.92.232
45.38.114.219 45.39.7.39 45.39.7.227 45.39.27.153
45.39.123.39 45.41.171.199 45.41.176.106 45.41.177.11
45.43.67.111 45.43.82.93 45.61.98.240 45.61.100.180
45.61.123.134 45.67.0.207 45.67.3.53 45.147.187.214
45.151.163.80 45.159.53.193 45.249.59.5 45.249.59.123
46.202.248.133 46.203.154.134 46.203.202.8 46.203.212.201
62.105.202.173 62.105.203.138 64.64.118.134 64.137.8.237
64.137.73.58 64.137.100.131 64.137.101.226 64.137.108.41
67.227.1.14 67.227.37.59 68.167.47.41 68.183.138.186
82.21.221.119 82.21.248.189 82.22.215.207 82.22.234.160
82.22.249.84 82.23.227.154 82.24.212.115 82.25.235.118
82.27.247.49 82.29.233.5 82.29.245.108 89.45.125.116
89.249.192.235 91.211.87.239 92.112.91.92 92.112.143.195
92.112.170.208 92.113.119.3 92.113.236.71 92.113.246.14
94.154.43.7 94.177.5.146 102.212.90.53 103.47.53.192
103.99.34.177 103.101.90.134 103.105.76.121 104.168.118.192
104.252.49.100 104.253.50.139 104.253.81.55 104.253.91.46
107.172.163.190 107.174.194.247 108.165.205.76 136.0.108.192
136.0.184.80 140.99.189.141 140.99.193.124 140.99.203.75
142.111.44.12 142.111.216.8 142.147.129.75 142.147.132.10
145.223.41.159 145.223.45.93 145.223.50.100 148.135.254.33
148.135.254.73 148.135.254.118 151.245.204.165 151.245.204.214
151.245.205.41 151.245.206.59 152.232.81.206 154.9.177.66
154.29.25.85 155.254.39.35 160.187.210.214 166.88.34.50
166.88.64.163 168.199.209.224 168.199.244.14 169.58.51.5
172.120.112.207 172.120.119.224 173.214.177.173 185.101.252.60
192.95.91.217 192.177.87.44 192.186.186.222 198.12.112.116
198.20.191.165 198.46.148.181 198.46.202.184 198.46.241.29
198.89.123.223 198.105.100.102 208.70.8.237 212.42.207.214
213.169.211.115 216.10.27.39 217.117.165.104