Bandit 27 → 28: localhost is wherever you're standing
After a run of levels that all lived inside the box, this one pushes you back out to your own machine. The password is in a git repository you clone over SSH — and the level’s own URL is the thing that breaks it, because it’s written from the box’s point of view and you’re told to run it from yours.
the goal
There is a git repository at
ssh://bandit27-git@localhost/home/bandit27-git/repovia the port2220. The password for the userbandit27-gitis the same as for the userbandit27. From your local machine (not the OverTheWire machine!), clone the repository and find the password for the next level.
the approach
I scripted the clone rather than typing it, so the working invocation would still
exist after the terminal was gone. First version, straight off the level page —
localhost, port in the URL, cloning into a scratch dir:
WORKDIR=$(mktemp -d /tmp/b27.XXXXXX)
cd "$WORKDIR"
git clone ssh://bandit27-git@localhost:2220/home/bandit27-git/repo
Cloning into 'repo'...
ssh: connect to host localhost port 2220: Connection refused
fatal: Could not read from remote repository.
Ran it again in case it was a blip. Same refusal, instantly — and instantly is
the tell. A firewall or a wrong port on a remote host makes you wait for a
timeout; Connection refused came back immediately because something local
answered and said no. Nothing is listening on port 2220 of my laptop.
Which is the whole level. localhost isn’t a place, it’s a pronoun — it means
this machine, resolved fresh wherever the command runs. The URL on the level
page is correct as written on the game server, where port 2220 is the box’s
own sshd. The instructions then tell you to run it from your local machine, and
the moment you do, localhost quietly re-points at you.
So the fix is just to say which host out loud. I already had a bandit entry in
my ssh config from every previous level, and it carries the port, so the URL
collapses to:
git clone ssh://bandit27-git@bandit/home/bandit27-git/repo
bandit27-git@bandit.labs.overthewire.org's password:
remote: Enumerating objects: 3, done.
Receiving objects: 100% (3/3), done.
The password it prompts for is bandit27’s — the level says so, and it’s the one I
already had. Three objects come down: a commit, a tree, and one file. The clone
lands a single README, and the password for the next level is sitting in it in
plain text (redacted here).
Worth noting what isn’t needed. There’s no history to dig through, no deleted file, no branch hiding anything — one commit, one file, password in the working tree. Git is the transport here, not the puzzle. That comes later.
the takeaway
localhost is resolved by whoever runs the command, not by whoever wrote it.
Copying a connection string from documentation into a different machine is one of
the easiest ways to waste ten minutes, and the error is unhelpful precisely
because it’s honest — nothing is listening on your own port 2220. When a host
in a URL was written from somewhere else’s perspective, replace it before you
replace anything else.
Two smaller bricks:
A git remote carries its port inside the URL. It’s
ssh://user@host:2220/path, not a -p flag — git clone has nowhere to put one,
because the port belongs to the SSH URL scheme, not to git. And if the host has an
ssh config entry, that entry’s Port applies here too, which is why the working
version has no port in it at all.
Connection refused and a hang mean different things. Refused is a machine
that answered and declined; a hang is a packet that went nowhere. The one that
comes back instantly is telling you that you reached something — usually
yourself.