Correction ·
Revised 4 November 2026: replaced the archived roundup with reviewed historical analysis for the original reporting period.
A burst across administration formats
On 2026-09-02, 37 HTTP request-body records across 1 sensor in under 12 seconds contained a wget.sh download-and-shell sequence across 32 distinct captured input contents. The cohort ran from 01:02:06.184548 through 01:02:18.027670 UTC. This analysis examines captured HTTP request-body instructions from that sensor.
What changed, and what stayed constant
The wrappers changed; the requested work stayed recognizable. The inputs placed shell syntax in deviceName, hostname, SPECIFIC_SERVER and SYSLOGD_REMOTE_HOST, inside JSON login parameters and plugin_version, and in an XML IPAddress field. Variants requested ordinary wget, BusyBox wget or curl retrieval, followed by a shell invocation of wget.sh.
The 37 matching records comprise 22 form-style inputs, 6 JSON inputs, 2 XML inputs, 6 PHP inputs and 1 direct shell-style input. Literal ${IFS} appears in 10 raw input records; another 22 contain its percent-encoded representation. After 1 percent-decoding pass, 32 records contain ${IFS}. This shell whitespace expansion and the encoding layer explain why literal-space searches miss related inputs.
MITRE ATT&CK's Unix Shell technique provides investigation context for services that reach command interpreters: Unix shells support scripts and sequential command execution, and adversaries may abuse Unix shells to execute commands or payloads. Here, the actionable link is the administration input, the requested downloader and the named script passed to a shell. Primary-source document
The week's evidence
For 2026-08-31 through 2026-09-06, the bounded keyword-selected HTTP and HTTPS cohort contains 374 retained event records in 101 daily source/input groups. No daily source/input group rank reaches the cap of 64, so all group memberships are available. The selected 37 records are a subset of that cohort, and the 32 distinct retained input contents show repeated use of the same downloader sequence across changed inputs.
A rule tied only to hostname misses the other parameter names. A literal-space search can miss ${IFS}; a search for only one URL string or one parameter name can separate related variations. Normalize the representation first, then look for the download and interpreter references together. Group matching results by route, sensor, time and normalized command shape to see how broadly the same mechanism is being tried in local logs.
A local hunt and the next checks
Run this narrow filter against retained request bodies. It decodes 1 URL-encoding layer and normalizes ${IFS} before checking for both retrieval and shell invocation of wget.sh in the same body. Keep the original body alongside the normalized result.
def matches_admin_downloader(body):
import re
from urllib.parse import unquote
if not isinstance(body, str) or len(body.encode("utf-8")) > 65536:
return False
text = unquote(body).replace("${IFS}", " ")
download = re.search(r"\b(?:wget|curl)\b[^;\n]*\bwget\.sh\b", text)
invoke = re.search(r"\b(?:sh|bash)\s+wget\.sh\b", text)
return bool(download and invoke)
For a match, check the inbound route, affected parameter, caller, workload owner, requested operation and approved change or security-test record. Where host telemetry is available, correlate the request time with the web service spawning a shell or downloader, file changes involving wget.sh, and any outbound retrieval by that process tree. Authorized automation and testing can contain the same strings, so triage the local owner and requested operation before alerting.