ArunNetworkingPro
🚪

Linux+ Break Room · Case 05

Doors that open by themselves

Somewhere in this house, a voice whispers "I know you're there..."

Every night, doors in this server creak open on their own. Something is listening on a port nobody opened. You silence it, and a minute later it's back. The old séance board can be read by anyone who walks past. The caretaker's SSH door lets in root, passwords, even empty passwords. And there's a key on the caretaker's ring that belongs to someone called agatha@beyond. Seal the house without locking yourself out. Ghost, or Linux?

Case 05 of 10SecurityTroubleshootingNeeds sudo

⚠️ This case needs sudo

Get the case

Rule 4: read it before you run it, less breakroom-mission-05.sh, especially this one, because it runs as root. The comments list every sabotage.

curl -O https://arunnetworkingpro.com/labs/breakroom-mission-05.sh
sudo bash breakroom-mission-05.sh

At any point, ask the house how many ghosts are left:

sudo bash breakroom-mission-05.sh --check

Part A: who's knocking?

A1

Count the doors

How many ports are open on 10.66.6.6, and which numbers?

Hint

sudo ss -tlnp lists every listening TCP port: -t TCP, -l listening only, -n numbers instead of names, -p the process behind it (needs sudo). Pipe it through grep 10.66.6.6.

A2

Who's whispering?

nc -w 3 10.66.6.6 31337

Something answers. Find the systemd service behind port 31337. Its name tries very hard to look innocent.

Hint

ss -tlnp gave you a pid=. systemctl status <pid> tells you which unit that process belongs to.

A3

Silence it

Stop it, and make sure it doesn't start at boot. Then wait a minute and knock again.

Hint

sudo systemctl disable --now <unit> does both. Then sleep 70; nc -zv -w 3 10.66.6.6 31337. Did it stay dead?

A4

Who keeps summoning it?

It came back. Something is raising it on a schedule. Find the ritual and end it for good.

Hint

systemd has its own alarm clocks: systemctl list-timers --all. Disable the timer with --now, then stop the whisper once more. Or go nuclear: systemctl mask makes a unit impossible to start at all.

Part B: shut the doors

B1

Close every door but one

The séance board on port 8080 must keep running, but nobody may reach it. Only door 2222 stays open on 10.66.6.6. Build it with nftables, in your own table called haunted, and only ever match ip daddr 10.66.6.6, so your real network is never touched.

Panic button: sudo nft delete table inet haunted removes everything you added, instantly.

Hint

Start with sudo nft add table inet haunted and a chain: sudo nft add chain inet haunted input '{ type filter hook input priority 0; policy accept; }'. Then add rules in order: let replies through (ct state established,related accept), accept port 2222 to 10.66.6.6, drop everything else to 10.66.6.6. Test with nc -zv -w 3 10.66.6.6 8080 and 2222. If 2222 stops working too, think about the answers coming back to 10.66.6.6.

B2

Silence or a slammed door?

Time a knock on 8080: time nc -zv -w 5 10.66.6.6 8080. Now change your last rule from drop to reject and time it again. What changed, and which would you use facing the internet?

Hint

sudo nft -a list table inet haunted shows each rule's handle number. Delete one with sudo nft delete rule inet haunted input handle <n> and add the new one. Or flush the chain and add all three again.

Part C: exorcise the SSH door

C1

Read the curse

The haunted SSH server reads /etc/breakroom-05/sshd_config. Find the five settings that leave the door wide open.

Hint

Ask sshd what it will really use: sudo sshd -T -f /etc/breakroom-05/sshd_config. Look at root login, passwords, empty passwords, how many tries a guesser gets, and X11 forwarding.

C2

Break the curse

Fix all five, check the file, restart the haunted SSH service, then prove passwords are no longer offered:

ssh -p 2222 -o PubkeyAuthentication=no caretaker@10.66.6.6
Hint

Use sudo nano on the config. sudo sshd -t -f /etc/breakroom-05/sshd_config prints nothing when it's happy. Restart breakroom-05-sshd and give it a second. Won when the reply says Permission denied (publickey), with no password in the list.

C3

The stranger's key

The caretaker's authorized_keys holds a key from agatha@beyond. Nobody knows who that is. Remove it.

Hint

The file is /home/caretaker/.ssh/authorized_keys, one key per line; the comment at the end says whose it is. sudo nano it, or sudo sed -i '/agatha@beyond/d' the file.

C4

Your key, your door

Make yourself a key, add it to the caretaker's list, and log in with it:

ssh-keygen -t ed25519 -f ~/.ssh/breakroom_ed25519 -N ''
sudo tee -a /home/caretaker/.ssh/authorized_keys < ~/.ssh/breakroom_ed25519.pub
ssh -i ~/.ssh/breakroom_ed25519 -p 2222 caretaker@10.66.6.6 whoami

It still says no, even with the right key. Why? Fix it until the last command prints caretaker.

Hint

sshd writes down why it refused you: sudo journalctl -u breakroom-05-sshd -n 20. Look for "bad ownership or modes". sshd wants the .ssh folder at 700 and authorized_keys at 600, owned by the caretaker.

✅ How you know you won

sudo bash breakroom-mission-05.sh --check says Verdict: 7/7. Not a ghost. It was Linux all along. Case closed.

Answer key (no peeking until you've tried)

A1: three doors: 2222, 8080, 31337. A2: breakroom-05-whisper.service ("Totally normal system helper"). A3: sudo systemctl disable --now breakroom-05-whisper. It's back within a minute. A4: breakroom-05-summon.timer. sudo systemctl disable --now breakroom-05-summon.timer, then stop the whisper again (or mask it). B1: ct state established,related accept, then ip daddr 10.66.6.6 tcp dport 2222 accept, then ip daddr 10.66.6.6 drop. B2: drop hangs until the 5-second timeout; reject says Connection refused instantly. Drop for the internet, reject inside your own network. C1: PermitRootLogin yes, PasswordAuthentication yes, PermitEmptyPasswords yes, MaxAuthTries 10, X11Forwarding yes. C2: set them to no, no, no, 3, no, then sudo sshd -t -f ... and sudo systemctl restart breakroom-05-sshd. C3: delete the agatha@beyond line. C4: Authentication refused: bad ownership or modes. sudo chmod 700 /home/caretaker/.ssh and sudo chmod 600 /home/caretaker/.ssh/authorized_keys.

💥 Let it haunt you again

Run the script again. Every door creaks open again, fresh:

sudo bash breakroom-mission-05.sh

Now do it without the hints. (SSH will shout REMOTE HOST IDENTIFICATION HAS CHANGED, because every run makes a new host key: ssh-keygen -R '[10.66.6.6]:2222' forgets the old one.) Then try Part B with ufw or firewalld instead of raw nftables. And when you're done for good: sudo bash breakroom-mission-05.sh --clean.

🧠 The ghost, explained

Verdict: not a ghost. Every open door was a program listening on a port, every "resurrection" was a timer, and every way in was a line in a config file.

An open port is just a program listening. ss -tlnp shows every listener, its address, and the process behind it. Give the PID to systemctl status and it tells you which service owns it. That's how you go from "what is this?" to "who put it there?".

Things that come back from the dead have a reason. disable --now stops a service and stops it starting at boot, but anything can still start it on demand. Here it was a timer. On real servers it's timers, cron jobs, other services, or socket activation. systemctl list-timers is your first suspect. mask is the stake through the heart: nothing can start a masked unit.

Firewalls see the replies too. A rule that drops everything to an address also drops the answers coming back to it. That's why real rulesets start with ct state established,related accept: the firewall remembers conversations, so only the first knock of a new one gets judged.

Drop or reject? Drop is silence: the knocker waits and gives up, and learns nothing. Reject answers "go away" instantly. Drop suits the internet (give attackers nothing); reject is kinder inside your own network, where a fast "no" saves a colleague five confused minutes.

sshd config is where the doors really are. sshd -T prints the settings sshd will actually use, after defaults and includes, which is what you should audit rather than the file you think it reads. sshd -t checks a config before you restart, so a typo can't lock you out. And a restart is needed: a fixed file does nothing until sshd reads it.

authorized_keys is the guest list. Every line is a key that opens the door, no password asked. Old keys from people who left are one of the most common real-world holes. And StrictModes makes sshd ignore the whole list if anyone but the owner could edit it: that's why a 777 folder broke your login too.

Other families. Ubuntu's ufw and Red Hat's firewalld (firewall-cmd) both write nftables rules underneath, so what you learned here is what they do for you. On Red Hat, SELinux also stops sshd from listening on a non-standard port like 2222 until you label it with semanage port. That's a whole other ghost: Case 07.

← Case 04 · All cases · Case 06 → · Stuck, or found a better way? Email me

🎉 Got it, thank you!

Your comment just landed in my inbox. I read every one, and I'll reply by email.

🤔 That didn't go through

Something in the form looked off. Check your name, email and comment and try again, or just email me.

🐢 Whoa, slow down

That's a lot of comments in a short time, so the box is taking a breather. Try again later, or email me.

😴 The comment box is napping

My server is taking a quick break, so your comment couldn't be sent. Sorry! Please email me instead.

💬 Leave a comment

Stuck, found a better way, or just built it and want to brag? Tell me. It comes straight to my inbox (nothing is posted publicly), and I'll reply by email.

Your email is only used to reply to you. Never shared, never added to any list.