Friday, October 22, 2010

Reset the root password to a random value

I recently began setting up some Linux servers at work and become concerned about access to the root user account. I have stressed the need for using SUDO, but the fact that people may know the root account was a gaping hole in accountability - if everyone logs in as root, how do I know who made what change?

I decided that a good method of enforcement would be to change the root password on a daily basis to a random string. The thinking is that anyone with SUDO access doesn't need the password, the password can be changed through the use of SUDO, and worst case scenario we can boot to a rescue disk and change it from there.

I did some searching on the net and found the below perl script at http://www.sunmanagers.org/pipermail/summaries/2005-May/006495.html. I put this script in the crontab for root and set it to run every day. Hopefully when I come back into the office, my root account password will have changed.

script:
#!/usr/bin/perl -w

use strict;

my $shadow="/etc/shadow";
my @Salt=("a".."z","A".."Z",0..9,".","/");

my ($uid,$gid)=(stat($shadow))[4,5];
(defined $uid) || die "$0: Failed to stat(\"$shadow\") - $!\n";

my $pass="";
map { $pass=$pass . sprintf("%c",int(rand(93))+33) } (1..8);
my $unx=crypt($pass,$Salt[int(rand($#Salt + 1))] . $Salt[int(rand($#Salt + 1))]);

open(OLD,$shadow) || die "$0: Failed to open $shadow for reading - $!\n";
open(NEW,">$shadow.new") || die "$0: Failed to open $shadow.new for writing - $!\n";
chmod(0600,"$shadow.new") || die "$0: Failed to 
chmod(0600,\"$shadow.new\") - $!\n";

while(<OLD>) {
 s/^(root):[^:]+:(.*)$/$1:$unx:$2/;
 print NEW $_;
}

if (!close(OLD)) {
 unlink("$shadow.new");
 die "$0: Failed to close file handle on $shadow - $!\n";
}
 if (!close(NEW)) {
 unlink("$shadow.new");
 die "$0: Failed to chown($uid,$gid,\"$shadow.new\") - $!\n";
}

if (!rename("$shadow.new",$shadow)) {
 unlink("$shadow.new");
 die "$0: Failed to rename(\"$shadow.new\",\"$shadow\") - $!\n";
}

exit 0;

No comments: