Latest / Linux Server Admin with Fexingo: Sysadmin, Bash, and Server Engineering / Why Your Sudoers File Needs Hardening Now
Transcript
- Lucas: So I was auditing a monitoring server last week — nothing special, just a Prometheus node with a few exporters — and I found something that made me wince. Luna: What was it? Lucas: The sudoers file had a line that basically said: the deploy user can run ANY command as root, no password required. And it was the last line in the file, so it overrode all the earlier restrictions. Luna: Oh, the classic 'I'll just add this one wildcard rule to get stuff done and never come back to fix it' trap. Lucas: Exactly. And that server had been running for two years. So today I want to talk about why your sudoers file is probably more permissive than you think, and how to lock it down without breaking your workflow. Luna: Alright, walk me through it. Where do we start? Lucas: Let's start with the defaults. Most sudoers files I see in the wild have zero Defaults lines. And that's a problem because the default behavior of sudo is actually pretty loose. For example, by default sudo remembers your credentials for five minutes. That's the timestamp_timeout. Luna: So if I sudo once, I can run sudo again for five minutes without re-entering my password. That's convenient, but if I walk away from my terminal... Lucas: Right. Anyone who sits down at your unlocked session can sudo anything within that window. So one of the first hardening steps is to set a shorter timeout. I set mine to one minute. You can even set it to zero, which forces a password check every single time. Luna: Zero sounds painful for automation, but one minute seems reasonable. What else in Defaults? Lucas: Set env_reset to keep the environment clean — that prevents LD_PRELOAD attacks. Also set mail_badpass to yes, so you get an email whenever someone enters a wrong sudo password. That's a simple way to detect password-guessing attempts. Luna: And then there's the big one: NOPASSWD. I see people throw that tag around like candy. Lucas: Yeah, NOPASSWD is the single most dangerous tag in sudoers. It's appropriate for some automation accounts — like a backup script that needs to run a specific command — but for human users it should be the exception, not the rule. Luna: What's your rule of thumb? Lucas: If a human user needs passwordless sudo for more than one or two specific commands, you've probably got a design problem. I'd rather see people use timed credentials via a bastion host or use a privilege escalation tool like GateOne. Luna: Okay, so we lock down Defaults, we minimize NOPASSWD. What about the actual command rules? Lucas: Use command aliases. Instead of giving a user access to /bin/systemctl, create a Cmnd_Alias that lists exactly the systemctl subcommands they need. For example, Cmnd_Alias WEB_RESTART = /bin/systemctl restart nginx, /bin/systemctl restart apache2. Luna: That way they can't run systemctl status or systemctl stop some unrelated service. Lucas: Exactly. And use Runas_Alias to limit which users they can run commands as. Most people only need to run as root or as a specific service account, not any user. Luna: What about the ordering of rules? You mentioned earlier that the last matching rule wins. Lucas: That's critical. sudoers is parsed top-down, and the last match is the one that applies. So if you have a restrictive rule at the top and a permissive rule at the bottom, the permissive rule wins. I always put the most specific rules first, and then a catch-all deny at the bottom. Luna: So something like: user ALL= ALL, but with a Defaults requiretty to force interactive sessions. Lucas: Right. And you can combine that with a rule that says: if the command isn't in an approved alias, deny it. That's the principle of least privilege applied to sudo. Luna: But we also need to talk about logging, right? Because even with strict rules, you need to know what's happening. Lucas: Yes. sudo has built-in logging via syslog, but I prefer using sudo_logsrvd — it's a dedicated log server that was introduced in sudo 1.8. It sends all sudo events over TLS to a central log host. Luna: That's huge for incident response. If someone compromises a server and tries to cover their tracks, they can't just delete the local sudo logs. Lucas: Exactly. And you can configure sudo_logsrvd to log the full input and output of the sudo session, not just the command. So you get a keystroke-level replay of what happened. Luna: That sounds like a lot of data. Does it impact performance? Lucas: In my experience, the overhead is negligible on modern hardware. The bigger issue is storage — but you can rotate logs aggressively and set retention policies. I keep seven days of full I/O logs and thirty days of command-only logs. Luna: That's a good balance. Let's go back to the automation case. How do you handle CI/CD pipelines or scripts that need to run with elevated privileges? Lucas: For automation, I create dedicated service accounts with sudo rules that are scoped to exactly what the pipeline needs. And I use timed credentials that expire after the pipeline run. Tools like Vault can issue one-time sudo tokens. Luna: So the token is valid for, say, 10 minutes, and then it's gone. Lucas: Right. That way even if someone intercepts the token, it's useless after the pipeline finishes. That's much safer than embedding a password or a static sudo rule. Luna: I want to circle back to something you said earlier about the last matching rule. I've seen sudoers files that are hundreds of lines long with conflicting rules. What's your approach to keeping it maintainable? Lucas: I break it into multiple files in /etc/sudoers.d/. One file per role or application. That way I can disable a role by renaming the file, and I can see at a glance what permissions each group has. Luna: And you can use visudo to edit them safely. Lucas: Absolutely. visudo parses the file and locks it to prevent concurrent edits. And if you have a syntax error, it won't let you save. That's saved me more than once. Luna: Okay, let's talk about the monitoring angle. How do you know your sudoers file is actually secure? Lucas: I run a periodic audit with a script that parses the sudoers file and flags dangerous patterns: NOPASSWD for all commands, rules that match ALL hosts, rules that don't specify a command list. I also check for duplicate rules and rules that are commented out but still active. Luna: Do you have a tool for that, or is it a custom script? Lucas: I use a combination of sudo -l and a custom awk script. But there's also an open-source tool called sudo-rs that includes a linter. It's written in Rust and it's pretty fast. Luna: I'll have to check that out. So to summarize: tighten Defaults, minimize NOPASSWD, use command aliases, centralize logging with sudo_logsrvd, and audit regularly. Lucas: That's the core. And one more thing: test your sudoers changes in a staging environment before pushing to production. Even a syntax error can lock you out. Luna: This is exactly the kind of practical advice that makes this show valuable. And you know, it's also the reason we keep this podcast ad-free — we want to give you straight talk without any sponsor pressure. Lucas: Yeah, we're not here to sell you a cloud service or a monitoring tool. We just want to make you better at your job. If today's conversation gave you something usable, and you want to support that approach, the link is buy me a coffee dot com slash fexingo. Luna: It's a small way to keep this independent and focused on what matters: real sysadmin knowledge. Lucas: Alright, back to the tech. One final point: I also recommend setting the sudo lecture to always. That way every time someone uses sudo, they see a reminder about the security policy. Luna: That's a nice touch — keeps security top of mind. Lucas: Exactly. And combined with the logging, it creates a culture of accountability. You know that every sudo command is recorded and auditable. Luna: So the takeaway for our listeners: go check your sudoers file right now. Look for NOPASSWD, look for wildcard rules, and think about whether you really need them. Lucas: And if you find something scary, fix it today. A five-minute edit could save you from a breach tomorrow.