Technical Analysis of Shared UID Implementation in *NIX Systems: Best Practices and Security Implications


2 views

When examining the behavior of shared UID accounts in Linux/Unix systems, we observe that the kernel fundamentally tracks processes and files by numeric UID rather than username. This explains why two entries in /etc/passwd with identical UID 5000 function as demonstrated:

# Example passwd entries
a1:$1$4zIl1:5000:5000::/home/a1:/bin/bash
a2:$1$bmh92:5000:5000::/home/a2:/bin/bash

The behavior remains consistent across major Unix-like systems including:

  • Linux (RHEL, Debian, etc.)
  • BSD derivatives (FreeBSD, OpenBSD)
  • Commercial Unix (AIX, Solaris)

However, some tools may exhibit edge-case behaviors:

# Sample output variation
$ ls -ln
-rw-r--r-- 1 5000 5000 0 Aug 10 10:00 file1
$ ls -l
-rw-r--r-- 1 a1 5000 0 Aug 10 10:00 file1

While the shared UID approach provides login auditing separation, it introduces these security nuances:

  • Process attribution becomes ambiguous in system logs
  • SELinux/AppArmor contexts may require special configuration
  • SUDO configurations need careful planning
# Example audit log entry
type=USER_AUTH msg=audit(1628607043.248:294): pid=12451 uid=0 auid=4294967295 
ses=4294967295 msg='op=PAM:authentication acct="a1" exe="/bin/su" hostname=?'

Appropriate scenarios for shared UID implementation include:

  • Service account separation with identical privileges
  • Multi-role administrative access requirements
  • Containerized environments needing UID namespace consistency

Example Dockerfile implementation:

FROM alpine:latest
RUN adduser -D -u 5000 service1 && \
    adduser -D -u 5000 service2
USER 5000

For modern systems, consider these alternatives to shared UIDs:

  • Linux capabilities (setcap)
  • Filesystem ACLs
  • Container user namespaces
  • RBAC implementations
# Using capabilities example
$ sudo setcap CAP_NET_BIND_SERVICE=+ep /usr/local/bin/myservice

When two Unix/Linux accounts share the same UID (like in your RHEL5 example with UID 5000), the system treats them as the same user from a permissions perspective. This isn't accidental behavior - it's a fundamental design characteristic of Unix-style systems where the numeric UID is the true identity, while usernames are just human-readable aliases.


# Example /etc/passwd entries demonstrating UID sharing
service_audit:x:5000:5000:Audit Account:/var/empty:/sbin/nologin
service_backup:x:5000:5000:Backup Account:/var/backup:/bin/bash

Key observations from your testing hold true across POSIX systems:

  • File ownership displays the first matching username from /etc/passwd (implementation-dependent)
  • All processes run under the shared UID have identical privileges
  • Password authentication remains separate per account

While the core behavior is standardized by POSIX, edge cases vary:


// BSD systems may handle getpwuid() differently
struct passwd *pwd = getpwuid(5000); // Returns first match

Solaris and AIX have historically shown quirks with NIS/YP integration when UIDs collide.

The practice is common for system accounts but carries risks:

  • Pros: Fine-grained audit trails through separate login mechanisms
  • Cons: Potential confusion in log analysis (both accounts appear identical in kernel logs)

Modern systems prefer SELinux/AppArmor contexts for better isolation.

Here's how you might properly implement this for a database system:


# /etc/passwd snippet
db_admin:x:5001:5001:DB Admin Account:/opt/db:/bin/bash
db_audit:x:5001:5001:DB Auditor:/opt/db:/bin/rbash

# /etc/shadow snippet
db_admin:$6$rounds=65536$salt$hash:18679:0:90:7:::
db_audit:$6$rounds=65536$diffsalt$diffhash:18679:0:90:7:::

Instead of shared UIDs, consider:

  1. Linux capabilities (setcap/getcap)
  2. Containerization with user namespace remapping
  3. Role-based access control systems

For legacy systems where shared UIDs are unavoidable, implement comprehensive monitoring of both accounts through tools like auditd.