Adam Cassar

Co-Founder

7 min read

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