Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-60876 | Kitploit
Tools/GitHubGitHub/sirredbeard/cve-2025-60876
Static AnalysisVulnerability AnalysisExploitationWeb SecurityFuzzingPenetration TestingArchived
GitHubsirredbeard/cve-2025-60876

CVE-2025-60876

View Repository
12 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2025-60876: busybox wget request-target injection fix

A behavior-preserving fix for CVE-2025-60876, an HTTP header-injection vulnerability in BusyBox wget, plus the proof-of-concept that demonstrates it and the artifacts for submitting the fix upstream to BusyBox.

The vulnerability

BusyBox wget copies the URL path and query into the HTTP request line verbatim. A URL that carries a raw CR (0x0D), LF (0x0A), or other control byte can split the request line and inject attacker-controlled headers. A space (0x20) has the same effect: it breaks the METHOD SP request-target SP HTTP/1.1 framing.

Affected: BusyBox through 1.37.0 (the pkgver shipped on every in-support Alpine branch). Reported on the BusyBox mailing list in August 2025; CVE assigned as CVE-2025-60876 (NVD CVSS 6.5, Medium).

The fix

Two patches were already proposed upstream (Takeuchi Yuma, 2025-08; Radoslav Kolev, 2025-11). Both reject an offending URL and call bb_error_msg_and_die. That stops the injection, but it also rejects a plain space, so a URL like http://example.org/foo bar that used to work now errors. That regression is why the fix has not been picked up downstream. Alpine is holding its backport on it (work item 17872).

This fix handles the path and the host differently, matching how GNU wget and curl behave.

Path: percent_encode_target() in networking/wget.c percent-encodes control bytes (0x00 through 0x1f), space (0x20), and DEL (0x7f) in the request-target before the request line is built:

  • CR and LF can no longer reach the request line, so the injection is closed.
  • http://example.org/foo bar is sent as /foo%20bar, matching GNU wget and curl. No regression.
  • An existing % is left unchanged, so an already-encoded path is not double-encoded.

Host: the same bytes are rejected in the URL host. A hostname cannot legitimately contain control characters or a space, and percent-encoding is not defined for the authority component. This matters in proxy mode: the host is placed in the absolute-form request-target (GET http://host/path) and the Host: header but is not resolved locally, so a raw CR or LF in the host would otherwise inject. GNU wget (since CVE-2017-6508) and curl reject control characters in the host too.

The change is confined to networking/wget.c and adds one helper.

Out of scope: the FTP control channel (ftpcmd sends target->path and the user/password raw, an upstream-acknowledged TODO) is a separate injection class, not part of CVE-2025-60876, and is not addressed here. It should be tracked separately.

Validation

Built against BusyBox 1.37.0 with the same config Alpine uses (CONFIG_WERROR and CONFIG_TC off). A local listener captures the exact bytes wget puts on the wire.

Full capture: test/poc-output.txt. The four BusyBox testsuite/wget tests all pass against the patched build (test/testsuite-output.txt); the other full-suite failures noted there are unrelated (mount/taskset need root, and a few known restricted-container quirks). Size impact on aarch64 defconfig is +185 bytes (wget_main +142, .rodata +43, no symbols added or removed), measured with scripts/bloat-o-meter and recorded in cover-letter.txt.

Files

Reproducing the test

test/finalize.sh runs inside an alpine:edge container with Docker and reproduces everything (PoC, size, testsuite, patch):

root@kitploit:~
docker run --rm -v "$PWD:/work" alpine:edge sh /work/test/finalize.sh

It downloads BusyBox 1.37.0, builds it vanilla (showing the injection directly and via a proxy), applies the fix, rebuilds, replays the request cases above, runs bloat-o-meter and the wget testsuite, and writes the patch. test/driver.sh is a lighter PoC-only variant.

Upstream submission

BusyBox is a mailing-list project. The fix goes to [email protected] via git send-email, as a [PATCH v3] reply on Radoslav Kolev's November 2025 thread, crediting the prior reporters and reviewers. See cover-letter.txt. The fix is GPLv2, the same license as BusyBox.

References

  • CVE-2025-60876: https://www.cve.org/CVERecord?id=CVE-2025-60876
  • BusyBox ML, Kolev v2 (2025-11): https://lists.busybox.net/pipermail/busybox/2025-November/091840.html
  • BusyBox ML, Takeuchi report and patch (2025-08): https://lists.busybox.net/pipermail/busybox/2025-August/091710.html
  • Alpine work item 17872: https://gitlab.alpinelinux.org/alpine/aports/-/work_items/17872
  • Debian bug #1120795: https://bugs.debian.org/1120795
Download Tool
Input URLVanilla 1.37.0Patched
/x + CRLF + Evil: injectedEvil: injected arrives as a real header (vulnerable)GET /x%0D%0AEvil:%20injected HTTP/1.1, no injected header
/foo barsends a literal spaceGET /foo%20bar HTTP/1.1 (no regression)
/foo%20bar (already encoded)unchangedGET /foo%20bar HTTP/1.1 (not %2520)
/normalunchangedGET /normal HTTP/1.1 (unchanged)
proxy, host = h + CRLF + PInjected: 1PInjected: 1 arrives as a real header (vulnerable)dies with bad character in URL host, nothing sent
proxy, host = example.testnormalGET http://example.test/p HTTP/1.1 (unchanged)
FileWhat it is
wget-cve-2025-60876.patchThe fix as a git format-patch against BusyBox networking/wget.c, ready to send
commit-message.txtThe commit message (also the patch header)
cover-letter.txtThe [PATCH v3] mailing-list cover letter that revives the existing thread
apply_fix.pyGenerator that applies the change to a networking/wget.c (used to produce the patch)
test/serve_once.pySingle-connection listener that echoes the raw HTTP request
test/driver.shBuilds vanilla and patched BusyBox and runs the direct + proxy before/after PoC
test/finalize.shFull run: before/after PoC, bloat-o-meter, testsuite/wget, and regenerates the patch
test/poc-output.txtCaptured before/after request bytes (direct and proxy)
test/testsuite-output.txtBusyBox testsuite/wget results against the patched build