mirror of
https://github.com/uutils/shadow.git
synced 2026-06-10 16:14:57 -07:00
security: fix setuid-root privilege bypass (getuid vs geteuid)
Found by GitHub Copilot review on PRs #9, #10, #17. CRITICAL: is_root() used geteuid() which is ALWAYS 0 when passwd is installed setuid-root. Any unprivileged user could lock/unlock/delete passwords and skip PAM authentication. Fix: is_root() now uses getuid() (real UID) to check if the *caller* is actually root, not just running a setuid binary. Also: - get_current_username() uses getuid() (real UID) for same reason - Removed unused thiserror dependency from uu_passwd - Fixed SECURITY.md placeholder text
This commit is contained in:
+1
-1
@@ -19,7 +19,7 @@ reporting feature:
|
||||
2. Click "New draft security advisory"
|
||||
3. Fill in the details
|
||||
|
||||
Or email the maintainers directly (add contact email when established).
|
||||
If private advisory reporting is unavailable, open an issue tagged `security`.
|
||||
|
||||
## What to Include
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ clap = { workspace = true }
|
||||
libc = { workspace = true }
|
||||
nix = { workspace = true }
|
||||
shadow-core = { workspace = true, features = ["shadow", "login-defs"] }
|
||||
thiserror = { workspace = true }
|
||||
uucore = { workspace = true }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -500,14 +500,18 @@ fn resolve_target_user(matches: &clap::ArgMatches) -> Result<String, PasswdError
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the effective user is root.
|
||||
/// Check if the *real* user (caller) is root.
|
||||
///
|
||||
/// Uses `getuid()` (real UID), NOT `geteuid()` (effective UID).
|
||||
/// When passwd is installed setuid-root, euid is always 0 for all callers.
|
||||
/// The real UID tells us if the caller is actually root or a regular user.
|
||||
fn is_root() -> bool {
|
||||
nix::unistd::geteuid().is_root()
|
||||
nix::unistd::getuid().is_root()
|
||||
}
|
||||
|
||||
/// Return the current user's username (from euid).
|
||||
/// Return the current user's username (from real UID).
|
||||
fn get_current_username() -> Result<String, PasswdError> {
|
||||
let uid = nix::unistd::geteuid();
|
||||
let uid = nix::unistd::getuid();
|
||||
match nix::unistd::User::from_uid(uid) {
|
||||
Ok(Some(user)) => Ok(user.name),
|
||||
Ok(None) => Err(PasswdError::UnexpectedFailure(format!(
|
||||
|
||||
Reference in New Issue
Block a user