{"slug": "dirty-frag-a-failed-public-poc-did-not-mean-the-server-was-safe", "title": "Dirty Frag: a failed public PoC did not mean the server was safe", "summary": "A university login server at IIT Delhi that appeared secure after blocking a public Dirty Frag exploit was compromised in approximately 90 minutes using a DeepSeek-V4-Flash automated feedback loop. The attacker exploited a missed `pcbc(fcrypt)` kernel crypto path that remained accessible despite the server's mitigations, achieving root access and prompting a proper patch within an hour.", "body_md": "May 29, 2026\n\n# dirty frag field notes: from a patched server that was \"safe\"\n\na public Dirty Frag PoC failed, so the server looked safe. a cheap DeepSeek-V4-Flash feedback loop found the missed path -> fcrypt mismatch, nscd cache, and root in ~90 minutes.\n\n## the short version\n\ni got root on my university's shared login server. not because the sysadmins were asleep or because the box was some ancient forgotten machine. they were actually fast. they had read the CVE writeups, blocked the recommended kernel crypto interface, disabled unprivileged user namespaces, tested the public PoC, watched it fail, and moved on.\n\nreasonable response tbh. the problem is that public PoCs are not truth oracles. they only tell you one thing: this exact code path, as written, did not work on this exact run. that is not the same as \"the system is safe\".\n\nso i put [DeepSeek-V4-Flash](https://api-docs.deepseek.com/) in a boring shell feedback loop on a [Lightsail](https://aws.amazon.com/lightsail/) replica:\n\n``` php\ncompile -> run -> read error -> patch -> repeat\n```\n\nabout 90 minutes later, the exploit worked on the real server. i reported it, and they patched it properly within an hour. this is mostly a field-trip blog on the whole journey to get root access and how cheap intelligence has gotten if harnessed correctly.\n\n## the target\n\nthis was `ssh1.iitd.ac.in`\n\n, a shared login box for the electrical engineering department at IIT Delhi. my friend had gotten root on it last year when it was running Linux kernel 4 on Ubuntu 16. ancient era. this time it was not ancient anymore.\n\ninitial state:\n\n| thing | value |\n|---|---|\n| kernel | `Linux 6.8.0-111-generic` , built April 11 2026 |\n| distro |\n|\n\n`kernel.unprivileged_userns_clone = 0`\n\n[rules](https://man7.org/linux/man-pages/man8/modprobe.8.html)`modprobe`\n\nimportant bit: `AF_ALG`\n\nwas blocked, but `pcbc(fcrypt)`\n\nwas still registered in `/proc/crypto`\n\n. foreshadowing...\n\n## background, quickly\n\n[Dirty Frag](https://github.com/V4bel/dirtyfrag) is a Linux kernel privilege escalation from May 2026. it has two main paths: [CVE-2026-43284](https://nvd.nist.gov/vuln/detail/CVE-2026-43284) -> xfrm ESP path, and [CVE-2026-43500](https://nvd.nist.gov/vuln/detail/CVE-2026-43500) -> RxRPC path.\n\nboth get to a page-cache corruption primitive during kernel crypto work. the public exploit uses that to temporarily modify `/etc/passwd`\n\n, blank root's password, then `su`\n\nto root. very funny family of exploits.\n\n[ AF_ALG](https://www.kernel.org/doc/html/latest/crypto/userspace-if.html) is the kernel's userspace crypto socket API. most writeups said: block\n\n`AF_ALG`\n\n, block the algif modules, you're good until you patch. this is a really good patch as it stops the public poc from working.## first attempt\n\ni first tried [Copy Fail](https://nvd.nist.gov/vuln/detail/CVE-2026-31431), mostly because it had dropped around the same time and looked like the obvious thing to test. it died immediately:\n\n```\nsocket(AF_ALG, ...) = -1 EAFNOSUPPORT\n```\n\nfair enough. mitigation worked.\n\nthen i tried Dirty Frag.\n\nESP path -> blocked because unprivileged user namespaces were disabled.\nRxRPC path -> got further, because creating an `AF_RXRPC`\n\nsocket caused `rxrpc`\n\n, `fcrypt`\n\n, and `pcbc`\n\nto auto-load. but it still failed at the checksum step because the public PoC expected to use `AF_ALG`\n\n.\n\nat this point the obvious conclusion was:\n\n``` php\nboth cves blocked -> public poc failed -> server safe\n```\n\nmost people will probably stop there. but `pcbc(fcrypt)`\n\nwas still in `/proc/crypto`\n\n, so the question became: if the kernel can still use the algorithm internally, why is userspace `AF_ALG`\n\nthe final blocker?\n\n## the loop\n\nthis is where deepseek v4 flash, the cheapest model known to mankind, did the useful work.\n\nthe loop was boring:\n\n``` php\ncompile -> run -> read stderr + dmesg + return code -> patch code -> repeat\n```\n\ni love boring loops coz they work and i can track them.\n\nalso slightly cursed realization: this is just control engineering. this semester i was studying [ELL 225: Control Engineering](https://web.iitd.ac.in/~psrivast/teaching/ell225/25-26_2/index.html). i did not expect any of that to make my prompting better, but it did.\n\nLLM in a harness feels like a controller: goal prompt -> setpoint shell/tool environment -> plant stderr/dmesg/tests -> sensor code edits -> control input repeated runs -> feedback loop.\n\n## what the agent found\n\n### 1. public PoC fcrypt != kernel fcrypt\n\nthis was the actual turn. within about 9 minutes, the agent noticed that the `fcrypt`\n\nimplementation in the public PoC did not match the kernel's `pcbc(fcrypt-generic)`\n\nimplementation. different round structure. different key mixing. byte order weirdness.\n\ni will be honest here, i had no idea about this and i was already far from my home waters. dipping my toes first time in cybersecurity.\n\n### 2. byte order in `fcrypt_user_setkey`\n\non the Lightsail replica, the agent fixed the byte order in `fcrypt_user_setkey`\n\nso the userspace fallback matched the kernel schedule. small and boring but important fix.\n\n### 3. `POC_NO_UNSHARE`\n\nthere was also a `POC_NO_UNSHARE`\n\npath already sitting in the codebase. using it got past the user namespace setup and moved the exploit from immediate failure to `rc=3`\n\n.\n\ni feel stupid for not checking this myself first.\n\n### 4. `nscd`\n\nfinal blocker was [ nscd](https://man7.org/linux/man-pages/man8/nscd.8.html). on Ubuntu 24.04,\n\n`nscd`\n\ncan cache passwd lookups. so even after the page-cache corruption modified `/etc/passwd`\n\n, PAM could still see the old cached `root:x:0:0:...`\n\nentry and reject the blank password. the exploit looked like it failed even when the file had already changed.fix:\n\n```\nsystemctl is-active --quiet nscd && nscd --invalidate passwd\n```\n\n## root and cleanup\n\nfinal run on the real server was around 05:24 IST on May 22. first shot failed because of nscd. patched that. second shot worked. root shell.\n\ncleanup was straightforward: restored original `/etc/passwd`\n\n, unloaded `rxrpc`\n\n, `fcrypt`\n\n, and `pcbc`\n\n, dropped caches, deleted the exploit binary, and checked syslog for the RxRPC unregister messages.\n\nreported to sysadmins within the hour. they patched properly within another hour by upgrading the kernel to Linux `6.8.0-117-generic`\n\n.\n\n## the actual failure\n\nthis is not a \"lol sysadmins bad\" post. they did the obvious mitigation and verified it against the obvious public exploit. problem is that the obvious exploit was not the full search space.\n\nthey treated `public PoC failed`\n\nsame as `systems are safe`\n\n.\n\nthose are not the same statement.\n\nthree things slipped through:\n\n- the RxRPC path auto-loaded modules the AF_ALG mitigation did not cover\n- the public PoC had an fcrypt mismatch, so its failure was partially a PoC bug\n- nobody iterated after the first failure\n\n## why this matters for agents\n\ndeepseek, and other chinese models like glm 5.1 are CHEAPP. like, stupid cheap compared to the american counterparts.\n\nfor this problem, raw model intelligence was not the bottleneck. it did not need to be a god model like mythos. it needed to compile code, run code, read errors, compare source, and try again. that's it.\n\nthis is why i think cheap subagents + feedback loops are underrated for most tasks. the useful question is often not:\n\n```\ncan this model solve the whole thing in one shot?\n```\n\nit is:\n\n```\ncan this model keep trying sane variants without getting bored?\n```\n\nmythos and other god-tier models are good at seeing the bigger chain. cheap subagents are good at grinding through the local search space once you know where to look.\n\n## mitigation\n\nreal fix: patch your kernel.\n\nupstream commits:\n\n-> ESP path`f4c50a4034e6`\n\n-> RxRPC path`aa54b1d27fe0`\n\nif you cannot patch immediately, don't only block `AF_ALG`\n\n. block protocol modules too:\n\n```\nprintf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\ninstall af_alg /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf\n\nrmmod esp4 esp6 rxrpc af_alg 2>/dev/null\nsync && echo 3 > /proc/sys/vm/drop_caches\n```\n\nand if you're testing a mitigation, don't stop at `public PoC failed`\n\n. run it in a staging environment through a loop. make the agent explain *why* it failed, then make it try the branch it thinks should still work.\n\n## timeline\n\n| phase | start (IST) | end | duration | active |\n|---|---|---|---|---|\n| Copy Fail attempt + AF_ALG discovery | May 21 23:38 | 23:45 | ~7 min | yes |\n| Dirty Frag pivot + first RxRPC test | 23:46 | 23:55 | ~9 min | yes |\n| fcrypt mismatch discovery | 23:56 | 00:05 | ~9 min | yes |\n| Lightsail testing + byte order fix | May 22 00:05 | 00:20 | ~15 min | yes |\n| gap / sleep / other things | 00:20 | 04:05 | ~3h 45m | no |\n| final test on real server | 04:05 | 05:24 | ~1h 19m | yes |\n| root + cleanup | 05:24 | 05:46 | ~22 min | yes |\n| damage assessment + report | 05:46 | 05:50 | ~4 min | yes |\n\ntotal: about 95 minutes of active agent work, about 10 minutes of my active time, about 90 minutes wall-clock from first prompt to root shell.\n\n## closing\n\ngod-tier models like mythos and cheap subagents are two entirely different beasts.\n\none is good at chaining different small pieces into a bigger exploit path. the other is good at exploring subspaces around a known exploit and checking whether the system is actually secure.\n\ncheap subagents may have a really good use case in defending systems against fresh CVEs:\n\n``` php\ncve reported -> agents check replica(s) of prod -> findings go to sysadmin -> mitigations get implemented if available\n```\n\nnot glamorous. probably useful.", "url": "https://wpnews.pro/news/dirty-frag-a-failed-public-poc-did-not-mean-the-server-was-safe", "canonical_source": "https://shauryaa.dev/blog/dirtyfrag-afalg-bypass-nscd-fix/", "published_at": "2026-05-29 01:10:05+00:00", "updated_at": "2026-05-29 01:46:23.368988+00:00", "lang": "en", "topics": ["ai-safety", "ai-research", "ai-tools", "ai-agents", "ai-products"], "entities": ["DeepSeek-V4-Flash", "Lightsail", "IIT Delhi", "Dirty Frag"], "alternates": {"html": "https://wpnews.pro/news/dirty-frag-a-failed-public-poc-did-not-mean-the-server-was-safe", "markdown": "https://wpnews.pro/news/dirty-frag-a-failed-public-poc-did-not-mean-the-server-was-safe.md", "text": "https://wpnews.pro/news/dirty-frag-a-failed-public-poc-did-not-mean-the-server-was-safe.txt", "jsonld": "https://wpnews.pro/news/dirty-frag-a-failed-public-poc-did-not-mean-the-server-was-safe.jsonld"}}