Sitemap
Someone

Someone

Using medium as a progress tracker

Learning Cybersecurity from Scratch with Breachlab — Ghost Level 1: The File You Can’t Open by Its Name

Day 2 of my Breachlab Learning Journey | Why a filename that starts with a dash or contains a space breaks a perfectly normal command, and four ways to tell the shell exactly what you mean

7 min read2 days ago

--

Press enter or click to view image in full size
Dark Linux terminal at night showing a file listing, with one highlighted filename the command mistakes for an option
Ghost Level 1: the file is right there in the listing. The command just won’t see it

Disclaimer: This series is for educational purposes only. Everything here happens on Breachlab’s own practice targets, which exist to be attacked legally. Don’t try these techniques on systems you don’t own or don’t have written permission to test. Following Breachlab’s guidelines, I won’t share passwords, flags or a copy-paste solution. Every example below runs on a small practice folder you build yourself, so you learn the technique and still solve the real level on your own.

You log in. You run ls. The file you need is sitting right there, plainly listed.

You type cat and the filename, hit Enter, and... nothing. The cursor just blinks at you. Or you get an error saying the file doesn't exist, about a file you can literally see.

That was my first ten minutes on Ghost Level 1, and honestly it was a more useful lesson than any of the “find the hidden thing” levels. Nothing is hidden here. Nothing is locked. The only thing standing between you and the password is how your shell reads what you typed.

This is Day 2 of my Breachlab Learning Journey, where I’m working through Breachlab’s tracks level by level and documenting what each one actually teaches. On Day 1 (Ghost Level 0), the job was getting connected over SSH and learning to look around a box before touching anything. Today builds directly on that: you know how to find files, and now you find out that finding a file and naming it correctly are two different skills.

Today’s Topics

  • Why some filenames get mistaken for command options
  • Why a space in a filename quietly turns one argument into two
  • Four reliable ways to refer to an awkward file
  • A habit for spotting trouble before you hit Enter

First, Build a Practice Folder

I’m not going to walk you through the real level, so let’s build something with the same kinds of problems. On any Linux machine or VM, run this:

mkdir -p ~/lab/ghost1 && cd ~/lab/ghost1

echo "practice value one" > ./-
echo "practice value two" > ./-v
echo "practice value three" > "./field notes.txt"
ls -la

You now have three files whose names are deliberately annoying: one called just -, one called -v, and one with a space in it. The real level uses its own filename and its own twist, so treat these as training weights, not the answer.

Problem 1: The Filename That Looks Like an Option

Try reading the second file the obvious way:

cat -v

Your terminal just sits there. It hasn’t frozen; cat is waiting for you to type something. Press Ctrl + C to get out.

Here’s what happened. Almost every Linux command treats an argument starting with - as an option, a switch that changes how the command behaves. -v happens to be a real option for cat ("show non-printing characters"). So cat read your filename, decided it was a setting, found no actual file to read, and fell back to reading from your keyboard.

The lone - file trips you up in a similar way. By long-standing Unix convention, a single - on its own means "standard input": read from the keyboard or a pipe instead of a file. So cat - doesn't open the file named - either. It waits for you to type.

The file isn’t missing. The command just never looked for it, because it understood your filename as an instruction.

Problem 2: The Filename With a Space

Now the third file:

cat field notes.txt

This time you get two errors, one for field and one for notes.txt. Before cat even runs, your shell splits what you typed on spaces to decide where each argument starts and ends. So cat was handed two separate names, and neither exists.

The space is perfectly legal in a filename. Linux allows almost any character in one, but the shell has its own rules about what a space means on a command line, and those rules win unless you override them.

Press enter or click to view image in full size
Diagram showing a dash-prefixed filename routed to options, a filename with a space split in two, and four fixes below.
A leading dash turns a filename into an option, and a space splits one name into two. Four fixes remove the ambiguity.

Four Ways to Tell the Shell What You Mean

Every one of these fixes does the same thing in a different way: it removes the ambiguity, so the command can only read your argument as a filename.

1. Give it a path

cat ./-v
cat ./-

./ means "in the current directory." The argument now starts with a dot, not a dash, so no command will ever mistake it for an option. This is the fix I reach for first because it works everywhere, even with older or unusual tools.

2. Use the double dash

cat -- -v

A bare -- is a widely followed convention that means "options end here; everything after this is a filename." Most standard Linux tools honor it. It's very handy in scripts, but not every program supports it, so test it before you rely on it.

Get Someone’s stories in your inbox

Join Medium for free to get updates from this writer.

One catch: cat -- - still reads from standard input, because many tools treat a lone - as "stdin" even after --. For that particular name, the path fix is the reliable one.

3. Quote or escape it

cat "field notes.txt"
cat field\ notes.txt

Quotes tell the shell “this whole thing is one argument.” A backslash does the same for a single character, so \ means "a literal space, don't split here." Quoting fixes the space problem, but not the dash problem: cat "-v" still gets read as an option, because the quotes are removed before cat ever sees the text.

4. Redirect it in

cat < -

With <, the shell opens the file and feeds its contents to the command. The command never sees a filename at all, so it has nothing to misread. It's a neat trick, and it's useful to understand even when you don't need it.

A Habit Worth Building: Look Before You Type

Most of the pain on this level comes from assuming a filename is “normal.” Two small checks help you catch the weird ones before you hit Enter:

ls -Q        # wraps every name in quotes, so spaces and odd characters stand out
ls -b # shows escapes for special characters, like field\ notes.txt
file ./* # tells you what each file actually contains

And use Tab completion. Type the first character or two and press Tab; the shell fills in the name and adds whatever escaping it needs. Half the time, the shell is quietly showing you the answer to "how do I type this name safely?"

When you try the actual level, slow down at the ls step. Look at exactly what the filename is, work out which problem it causes (option? standard input? splitting? more than one?), then pick the fix that removes that ambiguity. That's the entire skill, and it's yours to apply.

Key Takeaway

A command line isn’t just text. It’s text the shell splits into arguments, which the command then sorts into options and files. Ghost Level 1 lives in the gap between those two steps. A leading dash makes a filename look like an option, a lone dash means standard input, and a space splits one name into two. Every fix (a ./ path, --, quotes or escapes, or < redirection) works by taking away the command's room to guess.

This matters well beyond one wargame level. When attacker-controlled filenames reach scripts that don’t handle them carefully, this exact confusion stops being a nuisance and becomes a vulnerability. I dig into that history, and the standards that explain why Linux behaves like this, in today’s theory companion:

Understanding Linux Command-Line Parsing — The Theory Behind Ghost Level 1

The Breachlab Journey Continues

One level at a time, this series works through Breachlab’s tracks, from Ghost’s Linux fundamentals toward post-exploitation, web, cloud and Active Directory. Each level gets a practical guide like this one and a theory companion explaining the “why.”

Breachlab is free and runs entirely on donations. If it’s teaching you something, you can support it here: breachlab.org/donate

Watch the concept in detail

Watch the deep dive

Follow along with the complete Breachlab playlist on YouTube: Breachlab playlist on Assert True. The channel is Assert True on YouTube.

GitHub Repository

My notes and progress for every level live here: github.com/Someone-anon-coder/Breachlab

Follow the complete series

My other learning series

Arbiter (Java) Guide · Arbiter (Java) Theory · Python Guide · Python Guide Theory · GoLang Guide · GoLang Guide Theory · My Progress — Matplotlib

What’s Next?

On Day 3, we move to Ghost Level 2: files that don’t show up in a normal listing at all, why Linux hides some names by default, and how to stop trusting the first ls you run.

Happy hacking! 🛡️

--

--