Severity Daily

IT and AI security incidents, checked against the primary source

Tag: BIG-IP

  • F5 BIG-IP APM rootkit injects a PHP web shell that never touches disk; 795 hosts still vulnerable

    F5 BIG-IP APM rootkit injects a PHP web shell that never touches disk; 795 hosts still vulnerable

    Sophos published a teardown of a Linux implant on F5 BIG-IP APM appliances that rewrites what Apache sees in memory rather than writing a web shell to disk — on a vulnerability whose federal remediation deadline came and went on March 30, 2026.

    What happened

    On Tuesday, September 8, 2026, Sophos published “Dissecting a PHP web server rootkit,” a technical teardown of a Linux implant found on F5 BIG-IP Access Policy Manager appliances. Sophos detects the sample as Linux/Agnt-IC. During the work, Sophos learned that ESET had analyzed the same malware independently and named it PoisonedRefresh. Help Net Security carried a summary on Wednesday, September 9. The initial access vector Sophos points to is CVE-2025-53521, the BIG-IP APM flaw CISA added to the Known Exploited Vulnerabilities catalog in March.

    The mechanism is the story. Sophos describes the second stage this way: it “hides key operational strings with RC4, gains execution before the host application main() function is invoked by intercepting __libc_start_main, targets Apache’s PHP module by hooking the Apache Portable Runtime (APR) module loader (apr_dso_load), and injects a PHP web shell into memory.” The implant also hooks apr_time_now, and it intercepts mmap() so that when Apache maps three specific BIG-IP APM files — apm_css.php3, full_wt.php3, and webtop_popup_css.php3 — the process receives attacker PHP that is not present in the file on disk.

    That is the part worth restating plainly. The files on the appliance do not change. Their hashes do not change. A file integrity check, a scheduled malware scan, or a support-account diff against a known-good image all come back clean, because the substitution happens between the kernel and the running process, not on the filesystem.

    Sophos published artifacts. The second-stage sample is SHA-256 26bd5b0722d1dbab5db749a063c49bc8638653ac2addfead7a9cb3d6d57bccc9. String obfuscation uses RC4 with the hardcoded key TrswBWIl90Z5e38n. Alongside the HTTP path, the implant opens a local UNIX socket backdoor at /run/bigtlog.pipe gated by the token Kzwd6jM5. The injected web shell keys on the magic prefix BSOHAzPB with the key wSLjN1beuR, and answers with HTTP 201 and Content-Type: text/css; charset=utf-8 — a 201 on a stylesheet request is an odd enough pair to hunt for in proxy logs.

    On attribution, Sophos is explicit: “While we do not have sufficient evidence to attribute this malware to a specific threat actor, the targeting and implementation suggest operational sophistication.” No actor name, no country, and this page does not supply one.

    The underlying vulnerability has an awkward history. NVD shows CVE-2025-53521 published on October 15, 2025, with the description “When a BIG-IP APM access policy is configured on a virtual server, specific malicious traffic can lead to Remote Code Execution (RCE)” and CWE-121, a stack-based buffer overflow. That is not how the advisory started. Arctic Wolf, writing on March 31, 2026, records F5’s original October 2025 advisory as a medium-severity denial-of-service issue, revised on March 28, 2026 to a critical remote code execution flaw, with F5 stating the flaw was “being exploited by unauthenticated remote threat actors to deploy web shells.” F5’s own article, K000156741, did not render for us (see the sourcing note).

    Why it matters

    Three things about this record are worth separating out, because they push in different directions.

    First, the scoring in NVD comes from one place. Both CVSS vectors on the record are attributed to [email protected] and both are marked Secondary: CVSS v4.0 at 9.3 with the vector CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N, and CVSS v3.1 at 9.8. There is no primary NVD analysis score and no CISA-ADP enrichment on the record. Every number a scanner shows for this CVE traces to the vendor that first called it a denial of service. That is not an accusation — F5 revised the call itself, and the revised numbers are severe. It is a note about how thin the independent layer is on a vulnerability now confirmed to carry a rootkit.

    Second, CISA’s own fields, as NVD republishes them, name the bug differently than NVD’s description does. cisaVulnerabilityName reads “F5 BIG-IP Stack-Based Buffer Overflow Vulnerability.” NVD’s description leads with remote code execution. Both are true — the overflow is the mechanism, the RCE is the consequence — but an operator searching a catalog for “RCE” and an operator searching for “buffer overflow” will not surface the same set of records, and this publication has now seen that split on Citrix NetScaler, where a denial-of-service label sat on a bug that yielded a root shell.

    Third, the KEV entry carries a deadline that expired more than five months ago. cisaExploitAdd is 2026-03-27; cisaActionDue is 2026-03-30. That is a three-day clock, set months before BOD 26-04 made short clocks routine. The cisaRequiredAction field still reads: “Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.” BOD 22-01 was revoked by BOD 26-04 on June 10, 2026. NVD’s copy of this record was last modified on June 17, 2026, a week after the revocation, and still names the revoked directive. This is catalog-wide boilerplate rather than something specific to F5, but it is the text a federal operator reads when they look up what they are obliged to do, and it points at a directive that no longer exists.

    Then there is the exposure count, where the public numbers do not line up. The ShadowServer Foundation runs a tracker for BIG-IP APM systems vulnerable to CVE-2025-53521, and as reported on September 8 it showed 795 endpoints exposed online the previous day. Coverage from March 2026, when the reclassification landed, put the figure at more than 14,000 BIG-IP APM devices exposed online. Those are different denominators — ShadowServer’s tracker counts systems it assesses as vulnerable, while the March figure counted APM devices reachable from the internet — so the drop is not cleanly a patching rate, and we are not going to present it as one. What both numbers agree on is that the remaining population is small enough to be enumerated, which is exactly the population an operator with a working memory-resident implant would want.

    What to do

    Patch, if you have not. Per the Cyber Security Agency of Singapore’s April 6, 2026 alert, the affected branches are BIG-IP APM 15.1.0 through 15.1.10, 16.1.0 through 16.1.6, 17.1.0 through 17.1.2, and 17.5.0 through 17.5.1. Arctic Wolf gives the fixed builds as 15.1.10.8, 16.1.6.1, 17.1.3, and 17.5.1.3. Confirm against K000156741 before you schedule the window.

    Patching does not evict an implant that is already resident, so treat any internet-facing APM device that ran an affected build past March 2026 as needing a look, not just an upgrade. Hunt for requests to apm_css.php3, full_wt.php3, and webtop_popup_css.php3 that return HTTP 201, and for responses to those paths carrying Content-Type: text/css with a body that is not CSS. Check for /run/bigtlog.pipe. On the host, Sophos points at Apache processes reading /proc/self/maps and then changing memory permissions — an mprotect following a self-maps read is not normal for a web server.

    Because the on-disk files are untouched, file-hash comparison will not answer the question. Memory acquisition, or at minimum inspecting the mapped regions of the running Apache processes, is what answers it. If an appliance cannot be examined that way, rebuilding from vendor media is the shorter path.

    Federal operators should note that this CVE’s KEV deadline is long past rather than upcoming, and that the required-action text on the record refers to a revoked directive; the current obligation comes from BOD 26-04.

    Sourcing note

    Checked: Sophos’s “Dissecting a PHP web server rootkit” for the implant mechanics, indicators, and attribution language; the NVD record for CVE-2025-53521 for the description, CWE, both CVSS vectors and their sources, and CISA’s cisaExploitAdd, cisaActionDue, cisaVulnerabilityName, and cisaRequiredAction fields; the Cyber Security Agency of Singapore alert AL-2026-032 of April 6, 2026 for affected version ranges; Arctic Wolf’s March 31, 2026 write-up for the advisory revision timeline and fixed builds; and reporting by BleepingComputer on September 8 and Help Net Security on September 9 for the ShadowServer figure and the ESET naming.

    Could not reach: F5’s advisory K000156741 rendered only a loading state to automated fetching, so F5’s exact current wording, its own revision history, and its fixed-version table are reported here secondhand through Arctic Wolf and CSA Singapore rather than quoted from the vendor. cisa.gov returns 403 to automated fetching, so the KEV dates here come from NIST’s republication of CISA’s fields in the NVD API rather than from the catalog page. ESET’s own PoisonedRefresh publication was not located; the name is reported through Sophos, which credits ESET.

    Unresolved: the number of compromised appliances is not stated by Sophos or ESET, and no victim has been named. F5 has not, as far as we can find, published a statement about the rootkit specifically, as distinct from the March 2026 advisory revision. The relationship between ShadowServer’s 795 and the March figure of more than 14,000 is a difference in what is being counted, and neither source publishes a reconciliation. Attribution remains open, and Sophos says so.

  • F5 njs access control fails open on an exception; nginx-saml parses attacker XML before checking the signature

    F5 njs access control fails open on an exception; nginx-saml parses attacker XML before checking the signature

    F5 published seven CVE records on September 2, and the sharpest is an access-control module that lets the request through when its own code throws an exception.

    What happened

    Seven vulnerability records naming F5 as the assigning authority reached the National Vulnerability Database on Wednesday, September 2, 2026, timestamped 4:17 p.m. UTC. Six of them are new. The seventh, CVE-2026-63020, a 3.1-rated spoofed-error-message issue in the BIG-IP configuration utility, points back to an older knowledge-base article and appears to be a backfill rather than part of this release.

    Three of the six are in NGINX JavaScript, the scripting module usually written as njs, and all three are fixed in njs 1.0.1.

    The one worth reading first is CVE-2026-18329, scored 8.2 under CVSS v3.1 and 8.8 under CVSS v4.0 by F5’s own product security team, with the vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N — network reachable, no privileges, no user interaction. The record describes a js_access handler doing asynchronous request-body processing, where “an exception is thrown during asynchronous access-control evaluation before an explicit access denial is returned.” The consequence is stated plainly: the access phase can fail open. The njs 1.0.1 changelog is blunter, calling it an “Access control bypass in js_access.” Affected njs versions are 0.9.9 and 1.0.0.

    CVE-2026-78689 is a heap out-of-bounds write in njs’s XML module, reachable through xml.exclusiveC14n() when it parses a crafted namespace prefix list. What makes it more than a parser bug is where F5 says that parser sits: the record singles out the nginx-saml reference implementation, which processes untrusted InclusiveNamespaces/@PrefixList values before it validates the signature. Affected njs versions run from 0.7.10 up to 1.0.1.

    CVE-2026-78222, 7.5 and 8.7, crashes an NGINX worker. F5’s text: “A vulnerability exists in NGINX JavaScript where a malformed HTTP response received by ngx.fetch() can crash an NGINX worker when trusted JavaScript reads Response.statusText.” The njs changelog names the specific trigger — an upstream “status line with an empty reason phrase.” It is classified CWE-476, a null pointer dereference, and it reaches back to njs 0.5.1, the widest affected range in the batch.

    Two more are configuration-generator injection flaws, both CWE-76. CVE-2026-77180, 8.3 and 8.7, is in NGINX Ingress Controller: “Multiple user-controllable fields are written into the generated NGINX configuration without sanitization.” An attacker who can write Ingress annotations through the Kubernetes API can inject directives, touch files, or take the service down. Affected: 5.0.0 through 5.6.0, and the long-term-support line 2026-lts-r1 through 2026-lts-r5. F5 credits kodareef5. CVE-2026-66362, 8.1 and 8.6, is the same shape in NGINX Gateway Fabric running NGINX Plus as its data plane, where values “from the Authentication Filter Custom Resource Definition clientID or cookieName fields, or in the clientSecret field of a Secret referenced by an Authentication Filter, are rendered directly into NGINX configuration templates without sanitization or escaping.” Fixed in 2.6.8.

    The sixth is not NGINX at all. CVE-2026-66842, 8.8 and 8.7, is a BIG-IP privilege escalation: “BIG-IP has a vulnerability where an authenticated user of any role may be able to create administrative user accounts” through an undisclosed request to the Traffic Management User Interface. F5 lists no workaround. It is credited to Dan Stefan Alexandru of Pentest-Tools and also affects BIG-IQ’s TMOS module.

    F5 reports no exploitation for any of the seven, and none carries a CISA KEV entry.

    Why it matters

    A fail-open access control is a different category of defect from a bug in software that happens to be exposed. js_access exists for one purpose: to decide whether a request is allowed. When the thing that decides has a failure mode of “allow,” every deployment that leaned on it has been quietly weaker than its configuration said, and nothing in a log would necessarily show it. The attacker’s job is not to find a bypass but to make the handler throw, and the exception does not have to come from the security logic itself.

    The remediation guidance is worth reading closely for the same reason. Alongside the upgrade, F5’s workaround for CVE-2026-18329 tells operators to “wrap your logic in a robust try/catch block with a default strict deny policy that returns an HTML 403 Forbidden response code.” It is also an instruction to write the deny-by-default behavior yourself, in a module whose entire job was to provide it. Anyone who deployed js_access without thinking through what happens on an unhandled rejection was relying on a guarantee the module did not make.

    CVE-2026-78689 carries a second lesson about ordering. Parsing attacker-controlled XML before checking the signature that is supposed to establish trust is a recurring failure across SAML implementations, and it turns a memory-safety bug in a namespace parser into a pre-authentication one. The reference implementation being the named at-risk consumer matters, because reference implementations get copied.

    That CVE also shows something about how severity is being reported right now. F5 scored it 8.1 High under CVSS v3.1 with AC:H, and 9.2 Critical under CVSS v4.0 with AC:L/AT:P. Same flaw, same assigner, same record, two different bands. This is not carelessness — v4.0 moved the “there is a precondition” idea out of attack complexity into a separate Attack Requirements metric, so the condition that pushed the v3.1 score down is represented differently rather than dropped. But a team that filters on “Critical” sees this flaw and a team that filters on the v3.1 base score does not, and both are reading the same record. F5’s v3.1 vector also asserts C:H/I:H/A:H, full compromise, while the record’s own text puts code execution at possible and unconfirmed: the score grades the worst case, the prose does not.

    The two injection flaws land in a familiar place: the boundary between “can edit Kubernetes objects” and “can execute in the proxy.” Ingress annotations and custom-resource fields feel like configuration, not code, and they are handed to people well short of cluster administrator. Where a template renders those strings unescaped, the RBAC grant that looked like a routing permission is a proxy-configuration permission.

    There is an awkward wrinkle in the recommended compensating control. F5 suggests admission policy — naming Kyverno, OPA Gatekeeper, and ValidatingAdmissionPolicy — to reject resources containing special characters. That is the right instinct. It is also worth knowing that Kyverno had a policy-exception bypass record, CVE-2026-84200, published to NVD the day before this batch, which this site covered on September 1. Admission policy is still worth deploying. But a compensating control is only as good as its own patch level, and an organization reading only F5’s advisory would not learn that.

    What to do

    • njs: upgrade to 1.0.1. This closes CVE-2026-18329, CVE-2026-78689, and CVE-2026-78222. The ranges differ — 0.9.9 and 1.0.0 for the access bypass, 0.7.10 up for the XML write, 0.5.1 up for the worker crash — so an old njs is exposed to the last two even if it predates the first.
    • If you run js_access: do not wait on the upgrade to add the try/catch and explicit 403 deny default F5 describes. Audit any handler doing asynchronous body work for paths that can throw.
    • If you run nginx-saml or anything derived from it: treat this as pre-authentication reachable and prioritize accordingly.
    • NGINX Ingress Controller: upgrade to 5.6.0, or 2026-lts-r5 on the LTS line. Until then, tighten RBAC so that write access to Ingress annotations is limited to trusted administrators, and add an admission policy that rejects special characters in annotation values.
    • NGINX Gateway Fabric: upgrade to 2.6.8. Review who can create or edit Authentication Filter resources and the Secrets they reference.
    • BIG-IP: upgrade to 21.1.0.1, 21.0.0.3, 17.5.1.8, or 17.1.3.4 depending on branch; BIG-IQ to 8.4.2.1. There is no workaround, so management-interface exposure is the only lever until you patch. TMUI should not be reachable from user networks, and this record is the argument for checking rather than assuming.
    • If you use ngx.fetch(): F5’s guidance is to “restrict ngx.fetch() destinations to trusted servers and avoid reading Response.statusText for responses from attacker-controlled or attacker-influenced endpoints.”

    Sourcing note

    Every CVE identifier, score, vector, affected range, and quoted description here comes from the CVE Program record API at cveawg.mitre.org and from NVD, both read on September 2, 2026. F5’s product security team is the assigning authority for all seven, so the descriptions and both CVSS vectors are F5’s own language and F5’s own grading, republished — there is no independent NVD analysis on these records yet, and no CWE assigned by anyone but F5.

    F5’s own knowledge-base articles — K000162599, K000162600, K000162601, K000162602, K000162603, and K000162521 — could not be read. my.f5.com returns a page whose body is a loading state; the advisory text is assembled in the browser and is not available to a non-browser fetch. That is the same pattern this site documented in HPE’s support portal on September 1. The version and remediation detail above is therefore recovered from the CVE records rather than read from the vendor page, and anything F5 said only in those articles is not reflected here.

    The njs 1.0.1 changelog was read from the project’s GitHub releases and corroborates all three njs entries, including the empty-reason-phrase trigger for CVE-2026-78222. That listing returned inconsistent release years to automated fetching, so no date is taken from it; the September 2, 2026 publication dates come from the CVE records.

    Unresolved: whether F5 grouped these into a quarterly security notification, and under what number, is not determinable from the records. No KEV entry exists for any of the seven, checked against NVD’s CISA fields, which lag the catalog by hours. No exploitation is claimed by F5 or observed in public reporting as of publication.