## https://sploitus.com/exploit?id=B92A9C2C-94E7-5F15-9902-66C07923632E
# glibc-static-nss-poc
Proof of Concept demonstrating how statically linked glibc binaries (`-static`) can still trigger runtime dynamic loading (`dlopen`) through the NSS (Name Service Switch) subsystem, enabling arbitrary code execution via `LD_LIBRARY_PATH` hijacking.
**Tested on:**
- Fedora 44 (glibc 2.43, ARM64)
- Debian 10 Buster (glibc 2.28, ARM64)
## The Vulnerability
When compiling with `gcc -static`, the resulting binary reports as self-contained (`not a dynamic executable` per `ldd`). Starting with glibc 2.34, the standard `dns` and `files` NSS modules were made builtin to eliminate the runtime overhead of repeated `dlopen`/`dlclose` cycles.
However, modern Linux distributions configure `/etc/nsswitch.conf` to use additional external NSS modules:
```text
hosts: files myhostname mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns
```
When a static binary calls `getaddrinfo()`, glibc's NSS dispatcher walks this chain and `dlopen`s the external modules:
- `libnss_myhostname.so.2` (systemd)
- `libnss_mdns4_minimal.so.2` (Avahi/mDNS)
- `libnss_resolve.so.2` (systemd-resolved)
- `libnss_dns.so.2` / `libnss_files.so.2` (on glibc &1 | grep -E "openat.*\.so"
openat(AT_FDCWD, "/lib64/libnss_myhostname.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib64/libnss_mdns4_minimal.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib64/libnss_resolve.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 # Cascaded dynamic libc
openat(AT_FDCWD, "/lib/ld-linux-aarch64.so.1", O_RDONLY|O_CLOEXEC) = 3 # Cascaded dynamic linker
```
**Key observation:** The "static" binary loads the entire dynamic linker infrastructure (`libc.so.6`, `ld-linux.so`) and multiple NSS modules at runtime, breaking the isolation contract of `-static`.
### 2. Payload Execution
Placing a malicious NSS module in the current directory and setting `LD_LIBRARY_PATH` causes the `__attribute__((constructor))` payload to trigger during the `dlopen()` phase:
```bash
$ LD_LIBRARY_PATH=. ./gateway
[+] Gateway started. Resolving blog.jarpex.com...
[-] Resolution failed: Name or service not known
$ cat /tmp/pwned.txt
=== PWNED BY NSS ===
uid=1000(fedora) gid=1000(fedora) groups=1000(fedora),10(wheel)
```
The payload executes during library load, regardless of whether DNS resolution ultimately succeeds.
Full terminal logs for modern (Fedora 44 / glibc 2.43) and legacy (Debian 10 / glibc 2.28) environments are available in the [`examples/`](examples/) directory.
## Mitigation: musl libc
The reliable way to enforce true static isolation on Linux is replacing glibc with **musl**, which implements name resolution natively without NSS plugin support:
```bash
$ strace ./gateway_musl 2>&1 | grep -E "openat.*\.so"
# (no output โ zero shared libraries loaded)
$ strace ./gateway_musl 2>&1 | grep -E "openat.*/etc/"
openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
```
No external shared libraries are loaded. The binary reads configuration files directly and performs DNS resolution internally. The `Makefile` builds this hardened variant automatically when `musl-gcc` is available.
## Technical Analysis
This is an **architectural limitation** of glibc's NSS dispatcher, not a memory corruption vulnerability:
- No buffer overflows, ROP chains, or heap spraying required.
- Compile-time mitigations (ASLR, NX, stack canaries, RELRO) have no effect โ the code is loaded through a legitimate runtime facility.
- The `dlopen` is invoked by the NSS dispatcher as designed.
- Persists across glibc versions via different modules: `dns`/`files` pre-2.34, `resolve`/`mdns`/`myhostname` post-2.34.
## Requirements
**For exploitation:**
- GCC or Clang
- glibc-based Linux distribution
**For mitigation demonstration:**
- `musl-gcc`
- Debian/Ubuntu: `sudo apt install musl-tools`
- Fedora/RHEL: `sudo dnf install musl-gcc`
- Alpine: `apk add musl-dev` (native)
## License
MIT
## Disclaimer
This code is provided for educational and security research purposes only. Use responsibly and only on systems you own or have explicit permission to test.