ENGINEERING

Fragnesia (CVE-2026-46300): check your Linux servers for tampering before you reboot them

On October 28 CISA added CVE-2026-46300, a Linux kernel bug called Fragnesia, to its Known Exploited Vulnerabilities catalog, with a due date of October 31 for federal agencies.

The bug isn’t new. The fix went to the kernel’s networking list on May 13, and Ubuntu and Red Hat shipped fixed kernels months ago. However, the exploit is now being used in the wild. On October 27, Dream reported attackers chaining it with PHP2Shell (the PHP bugs from my earlier post) to get root on about 25 servers, mostly firewall appliances, including machines on a US government-affiliated network. PHP2Shell got them a shell as the web server’s user, and this Fragnesia exploit turned that into root. Their backdoor was a changed /etc/pam.d/su that lets anyone su to root.

The backdoor only exists in memory

Fragnesia lives in the kernel’s ESP-in-TCP code (IPsec). A local user that can create a user namespace can use it to change files they’re only allowed to read, like /etc/pam.d/su or /usr/bin/sudo. It doesn’t touch the file on the disk. It changes the page cache, which is the copy of the file the kernel keeps in memory and gives to every program that opens it.

So, when the attackers rewrote /etc/pam.d/su, every program on the machine saw the rewritten version, while the disk still held the original. This has two consequences:

That’s why the order matters. The usual fix is to install the new kernel and reboot, and that reboot is exactly what destroys the evidence. Check for tampering first, then patch.

Check one machine

Run these as root, before you reboot anything.

Tampering. This compares each file’s in-memory copy (a normal read) with its disk copy (an O_DIRECT read, which bypasses the page cache). They only differ if something changed the in-memory copy without writing it to disk:

sudo bash -c 'for f in /etc/pam.d/* /etc/sudoers /etc/shadow $(find /usr/bin /usr/sbin -xdev -perm -4000 -user root -type f); do cmp -s "$f" <(dd if="$f" iflag=direct bs=1M status=none) || echo "DIFFERENT: $f"; done'

No output means nothing differs. And the specific backdoor from the report:

grep -E '^\s*auth\s+sufficient\s+pam_permit' /etc/pam.d/su /etc/pam.d/sudo /etc/pam.d/login /etc/pam.d/sshd

That should print nothing. (Debian and Ubuntu have a normal auth required pam_permit.so line in common-auth. That one’s fine; sufficient is the problem.)

If either finds something, don’t reboot. Copy the changed files with cat (that reads the in-memory version, which is the evidence), capture memory if you can, and treat the machine as rooted: rebuild it rather than clean it.

Is the running kernel fixed. Go by your distribution’s changelog, not the version number, because distributions backport the fix into their own kernels. On Ubuntu:

zgrep -c CVE-2026-46300 /usr/share/doc/linux-modules-$(uname -r)/changelog.Debian.gz

On RHEL, Rocky and Alma:

rpm -q --changelog kernel-core-$(uname -r) | grep -c CVE-2026-46300

Anything above 0 means the kernel you’re running has the fix. Both of my lab machines did (Ubuntu 26.04 on 7.0.0-38, Rocky 9.8 on 5.14.0-687.56.1). Ubuntu lists the fixed kernels as 7.0.0-22.22 for 26.04, 6.17.0-35.35 for 25.10, 6.8.0-124.124 for 24.04 and 5.15.0-181.191 for 22.04, and 20.04 and older aren’t affected. Upstream, it’s fixed in 7.0.10, 6.18.33, 6.12.91, 6.6.141, 6.1.174 and 5.15.208.

If the fixed kernel is installed but the machine hasn’t rebooted into it yet, it’s still running the old one. uname -r shows the kernel that’s actually running.

How I tested the tampering check

I couldn’t use the real exploit on my lab machine, so I made the same mismatch the other way round. I created a setuid test file, read it so it was cached, then wrote different bytes straight to its blocks on the disk device, underneath the filesystem. The page cache still held the old bytes and the disk held the new ones. Here’s RFF’s check on that Ubuntu VM:

RFF job output: TAMPERED, the in-memory copy of a test file differs from disk, with the instruction not to reboot or drop caches

I deleted the test file afterwards. On the same machine without it, every file matched.

If you can’t reboot yet

Red Hat’s bulletin gives two mitigations and both have a cost:

Ubuntu 24.04 and later already restrict what unprivileged user namespaces can do through AppArmor. I haven’t tested whether that alone stops this exploit, so I wouldn’t count on it.

Neither mitigation undoes tampering that already happened. Run the check first.

Doing this across a fleet

The RFF Script Library has two new Linux entries:

Here’s the block on the Rocky 9.8 VM:

RFF job output on Rocky 9.8: esp4 and esp6 blocked from loading, verified with modprobe

If you’re running PHP on Linux, the PHP2Shell checks from the earlier post are the other half of this chain.

RFF is free for your first 100 endpoints: getrff.com.

Sources

Comments

Comments use GitHub Discussions, so you'll need a GitHub account to post. Corrections are especially welcome.