Skip to content
EuroVPSEuroVPS

Why a compromised root account means rebuilding the server, not cleaning it.

A UID-0 account with no creation log wasn't created, it was written. How to find a hidden root account, and why root compromise means rebuild, not clean.

By EuroVPS EngineeringThe engine room

4 min read
In this article 5 sections

Every account on a Unix system has a birth certificate. A line in the authentication log that records who created it, when, and with what tool. An account with no such line was not created through any tool. It was written, by hand, straight into the user file. When that account also carries UID 0, the missing line is not a gap in your records. It is the evidence.

TL;DR
  • A hidden root account is the hardest backdoor to see, because on Unix, root is a number, not a name. Any account whose UID is 0 has full root. Give one such account a name a single character off a legitimate system daemon, and it survives a casual scan of the user list. The eye reads it as a typo, not a threat.
  • Two ordinary observations send a responder the wrong way: the disguised name looks like a misspelling of a real daemon, and an automated health check has already reported success. An all-clear.
  • The tell that cuts through both: there is no account-creation entry in the logs at all. The attacker never used the account-creation tool. The password hash was written straight into the user file, and into the user file, not the shadow file, which is a second indicator on its own.
  • The doctrine: scan for UID-0 accounts independently of creation logs, treat a hash in the wrong file as a finding, never treat a single automated check as proof, and when root was reachable for any window, rebuild from a verified-clean point from before the compromise. Do not scrub in place.

UID 0 is a number, not a name

Root is not the account named root. Root is any account whose user ID is 0. The kernel grants privilege on the number, and the name is decoration. So a backdoor does not need to touch the root account or guess a password. It needs one more line in the user file with a 0 in the third field.

Give that line a name a single character off a legitimate system daemon, and it disappears in plain sight. A user list is long, the names are cryptic by design, and a responder scanning it reads a known daemon, slightly misspelled, and moves on. The disguise is not sophisticated. It only has to survive a glance.

ROOT IS A UID, NOT A NAME
# Root is a UID, not a name. List every account with UID 0.
awk -F: '$3 == 0 { print $1 }' /etc/passwd

# Exactly one line should come back: root. Any second line is a
# full-privilege account, whatever it calls itself.

Two reasons to move on. Both wrong.

A good responder can be walked right past a hidden root account by two reasonable observations. Both are the kind of thing you nod at and move on. Neither survives a second look.

What it looks likeWhat it is
The account name reads as a typo of a legitimate system daemonA full UID-0 account, named to survive a glance, one character off a real daemon
An automated check reports success.One automated check is not proof.

“A single automated check is not proof. Confirm it with an independent scan.”

The account with no birth certificate

Every account created through the standard tools leaves a line in the authentication log: created by whom, when, with what command. A planted account has none. Not a deleted line, no line at all, because the attacker never used the tool. The password hash is written straight into the user file by hand, which is why there is nothing to log.

And it is written into the wrong file. On any modern Unix system the password field in the user file is delegated to the shadow file. It holds a placeholder, never a real hash. A genuine hash sitting in the user file is not a configuration choice or a legacy quirk you can wave off. It is the fingerprint of a manual edit, and it is an indicator on its own.

With no log line, the account's real creation time has to be reconstructed from side channels: file timestamps, and the records other events left around it. The absence of a birth certificate does not stop you from establishing the time of birth. It just means you work for it.

A HASH IN THE WRONG FILE IS A FINDING
# The password field in /etc/passwd should be a placeholder (x),
# never a hash. The real hash lives in /etc/shadow.
awk -F: '$2 != "x" && $2 != "*" && $2 != "!" { print $1 }' /etc/passwd

# A name that comes back here has its hash in the wrong file.
# That is a manual edit, not a managed account.

“A UID-0 account with no creation log wasn't created. It was written.”

When an update locks the attacker out by accident

The strangest thing about this failure mode is what a routine automatic update can do to it. An unattended update can rewrite a planted hash as a side effect and lock the attacker out of their own backdoor. The account stays. The access is gone. The backdoor can then sit dormant indefinitely: an unlocked door into a room whose key no longer turns. That looks like safety. It is not.

DORMANT IS NOT GONE

A backdoor that stopped working is not a backdoor that's gone. A dormant UID-0 account is still a UID-0 account someone planted. The presence is the compromise, not the login.

You don't clean it. You rebuild it.

The tempting close is 'delete the bad account, apply the patch, done.' Refuse it. Root access for any window, even a window that luck later slammed shut, means every byte on that machine is now suspect: binaries, cron jobs, libraries, and the very tools you would use to inspect it. You cannot audit your way back to trust on a system whose auditing tools you can no longer trust.

01

Scan for root independently of the logs

List every UID-0 account with awk. Do not rely on the creation log, a single automated check, or the user list looking normal.

02

Treat a hash in the wrong file as a finding

A real hash in the user file instead of the shadow file is a manual edit. Investigate it, do not explain it away.

03

Confirm every automated check independently

If an automated check says clean and your own scan finds an unexplained UID-0 account, chase the finding, not the reassurance.

04

Fix the time of compromise, not the time you noticed

Reconstruct the earliest plausible compromise from side channels. Your clean restore point must predate that, not the discovery.

05

Rebuild from a verified-clean point

Restore from a known-good image from before the compromise, rotate every credential the machine could touch, then re-verify. Do not scrub in place.

AN UNTRUSTED SYSTEM IS REBUILT, NOT CLEANED

Root for any window means an untrusted system. You do not clean an untrusted system. You rebuild it from a point you can prove was clean, from before the compromise, never after.

“Root for a minute is root until the rebuild. You don't clean that machine. You rebuild it from a point you can prove was clean.”

Straight answers

How do I find a hidden root account on Linux?+

List every account with UID 0, not just the one named root: awk -F: '$3 == 0 {print $1}' /etc/passwd. The kernel grants root by UID, not by name, so any second line is a full-privilege account whatever it calls itself. Scan for it directly. Do not rely on the user list looking normal or a single automated check reporting clean.

What does a password hash in /etc/passwd instead of /etc/shadow mean?+

On any modern Unix system the password field in /etc/passwd is a placeholder, usually x, and the real hash lives in /etc/shadow. A genuine hash sitting in /etc/passwd is not a normal configuration. It is the fingerprint of a manual edit to the user file, and it is an indicator of compromise on its own.

Why is there no log entry for an account that clearly exists?+

Because it was not created with the standard account tools, which is what writes the authentication log. If someone edits the user file by hand, the account exists with no creation record at all. A UID-0 account with no creation log was not created through any tool. It was written.

Can I just delete the malicious account and patch the server?+

No. Root access for any window means the whole system is untrusted: binaries, cron, libraries, and the tools you would inspect it with. Deleting the account and patching leaves you trusting a machine you can no longer verify. Rebuild from a restore point from before the compromise, rotate credentials, and re-verify.

The backdoor account looks inactive. Is it still a problem?+

Yes. A dormant or locked-out UID-0 account is still a full-privilege account that someone planted. Its presence is the compromise, not any login. An automatic update or config change can disable a backdoor by accident without removing the underlying breach. Treat presence, not activity, as the trigger.

A root account you can't explain?

If you have found a UID-0 account with no creation log, or you are not sure your last clean restore point predates the problem, do not scrub it in place. Talk to an engineer who will reconstruct the timeline from side channels and rebuild from a point you can prove was clean.

Talk to an engineer

You’ve reached the end.

Put the reading to work

What are
you running?

Tell us about the workload, traffic and recovery requirements. Start with the server builder, or talk through the details with an engineer.

Written by the engineers who build and run the infrastructure it describes.
Talk to an engineer
XIn

4 min left