[ SEA-GHOST MINI SHELL]

Path : /proc/2/root/var/lib/zabbix/
FILE UPLOADER :
Current File : //proc/2/root/var/lib/zabbix/sys_acc_checker.pl

#!/usr/bin/perl

#
#System accounts checker
#Based on PCI DSS rules
#Written by Vitalii.C
#

use strict;
use warnings;
use utf8;
my ($PW, $SH, $GR, %PASSWD, %SHADOW, %GROUP, %UID, %UID_NAME, %GID, %GID_NAME, %CHECK);

my @PASSWD_FORMAT = ('user','pass','uid','gid','info','home','shell');
my @SHADOW_FORMAT = ('user','pass','last_changed','changed_before','must_changed','exp_warn','expires_in','disabled_since','reserved');
my @GROUP_FORMAT = ('group','pass','gid','members');

open $PW, '<', '/etc/passwd' or die('Can not open /etc/passwd');
open $SH, '<', '/etc/shadow' or die('Can not open /etc/passwd');
open $GR, '<', '/etc/group' or die('Can not open /etc/passwd');

foreach (<$PW>) {
  chomp;
  my %record;
  @record{@PASSWD_FORMAT} = split /:/;
  $PASSWD{$record{'user'}} = \%record;

#Ensure no duplicate user names exist
  if(defined $UID_NAME{$record{'user'}}){print "Duplicate user name: $record{'user'}\n"}
  else {$UID_NAME{$record{'user'}}=1};

#Ensure no duplicate UIDs exist
  if(defined $UID{$record{'uid'}}){print "Duplicate UID: $record{'uid'}\n"}
  else {$UID{$record{'uid'}}=1};
} 

foreach (<$SH>) {
  chomp;
  my %record;
  @record{@SHADOW_FORMAT} = split /:/;
  $SHADOW{$record{'user'}} = \%record;
}

foreach (<$GR>) {
  chomp;
  my %record;
  @record{@GROUP_FORMAT} = split /:/;
  $GROUP{$record{'group'}} = \%record;

#Ensure no duplicate group names exist
  if(defined $GID_NAME{$record{'group'}}){print "Duplicate group name: $record{'group'}\n"}
  else {$GID_NAME{$record{'group'}}=1};
  
#Ensure no duplicate GIDs exist
  if(defined $GID{$record{'gid'}}){print "Duplicate GID: $record{'gid'}\n"}
  else {$GID{$record{'gid'}}=1};
}
close $PW;
close $SH;
close $GR;

my %checks;
@checks{@ARGV} = @ARGV;
if (defined $checks{'help'} || keys( %checks ) == 0){$CHECK{'help'}->{'func'}->()}
elsif (defined $checks{'all'}){$CHECK{'all'}->{'func'}->()}
else {
  foreach (sort keys %checks) {
    if(defined($CHECK{$_})){
      $CHECK{$_}->{'func'}->();
    } else {print "$_ check not implemented\n"; exit 1;}
  }
}

INIT {
###PCI DSS checks
  %CHECK = ( 
  'pass_empty' => {
    'description' => 'Ensure password fields are not empty',
    'func' => sub {
      foreach my $user (keys %SHADOW){
        if($SHADOW{$user}->{'pass'} eq ''){print "$user has empty password\n"}
      }
    }
  },
  'legacy_passwd' => {
    'description' => 'Ensure no legacy "+" entries exist in /etc/passwd',
    'func' => sub {
      foreach my $user (keys %PASSWD){
        if($user eq '+'){print "Legacy '+' entry exists in /etc/passwd\n"}
      }
    }       
  },
  'legacy_shadow' => {
    'description' => 'Ensure no legacy "+" entries exist in /etc/shadow',
    'func' => sub {
      foreach my $user (keys %SHADOW){
        if($user eq '+'){print "Legacy '+' entry exists in /etc/shadow\n"}
      }
    }
  },
  'legacy_group' => {
    'description' => 'Ensure no legacy "+" entries exist in /etc/group',
    'func' => sub {
      foreach my $group (keys %GROUP){
        if($group eq '+'){print "Legacy '+' entry exists in /etc/group\n"}
      }
    }
  },
  'root_uid' => {
    'description' => 'Ensure root is the only UID 0 account',
    'func'  => sub {
      foreach my $user (keys %PASSWD){
        if($user ne 'root' && $PASSWD{$user}->{'uid'} eq '0'){print "Account $user has UID 0\n"}
      }
    }
  },
  'home_exists' => {
    'description' => 'Ensure all users home directories exist',
    'func' => sub {
      foreach my $user (keys %PASSWD){
        if($PASSWD{$user}->{'home'} eq ''){print "Home directory for user $user is not set\n"}
        elsif(! -d $PASSWD{$user}->{'home'}){print "Home directory for user $user does not exist\n"}
      }
    }
  },
  'forward_file' => {
    'description' => 'Ensure no users have .forward files',
    'func' => sub {
      foreach my $user (keys %PASSWD){
        if(-e "$PASSWD{$user}->{'home'}/.forward"){print "User $user has .forward file\n"}
      }
    }
  },
  'netrc_file' => {
    'description' => 'Ensure no users have .netrc files',
    'func' => sub {
      foreach my $user (keys %PASSWD){
              if(-e "$PASSWD{$user}->{'home'}/.netrc"){print "User $user has .netrc file\n"}
      }
    }
  },
  'rhosts_file' => {
    'description' => 'Ensure no users have .rhosts files',
    'func' => sub {
      foreach my $user (keys %PASSWD){
              if(-e "$PASSWD{$user}->{'home'}/.rhosts"){print "User $user has .rhosts file\n"}
      }
    }
  },
  'grp_consistency' => {
    'description' => 'Ensure all groups in /etc/passwd exist in /etc/group',
    'func' => sub {
      foreach my $user (keys %PASSWD){
        if(!defined($GID{$PASSWD{$user}->{'gid'}})){
          print "User $user has non-existent group number: $PASSWD{$user}->{'gid'}\n"
        }
      }
    }
  },
#Ensure users' home directories permissions are 750 or more restrictive
#Skipped
  'home_owners' => {
    'description' => 'Ensure users own their home directories',
    'func' => sub {
      foreach my $user (keys %PASSWD){
        if($PASSWD{$user}->{'uid'}>=500 && -d $PASSWD{$user}->{'home'}){
          my $owner = (getpwuid((stat $PASSWD{$user}->{'home'})[4]))[0];
          if($user ne $owner){print "Homedir of $user is owned by user '$owner'\n";}
        }
      }
    }
  },
  'shadow_empty' => {
    'description' => 'Ensure shadow group is empty',
    'func' => sub {
      if(defined $GROUP{'shadow'}->{'members'} && $GROUP{'shadow'}->{'members'} ne '' ){
        print "Group 'shadow' has members: $GROUP{'shadow'}->{'members'}\n"
      }
      foreach my $user (keys %PASSWD){
        if($PASSWD{$user}->{'gid'} == $GROUP{'shadow'}->{'gid'}){print "User $user is in group 'shadow'\n"}
      }
    }
  },
###Non PCI DSS checks
  'key_access' => {
    'description' => 'Ensure users don\'t have key-based access',
    'func' => sub {
      foreach my $user (keys %PASSWD){
        if( -s "$PASSWD{$user}->{'home'}/.ssh/authorized_keys"){
          print "User $user has non-empty authorized_keys file\n"
        }
      }
    }
  },
  'shell_users' => {
    'description' => 'List of users with shell access',
    'func' => sub {
      foreach my $user (keys %PASSWD){
        if(
          $PASSWD{$user}->{'shell'} ne '/usr/sbin/nologin' && 
          $PASSWD{$user}->{'shell'} ne '/sbin/nologin' &&
          $PASSWD{$user}->{'shell'} ne '/bin/false'
        ){ 
          print "User $user has shell $PASSWD{$user}->{'shell'}\n"; 
        }
      }
    }
  },
  'all' => {
    'description' => "\tPerform all available checks",
    'func' => sub {
      foreach (sort keys %CHECK){
        next if($_ eq 'all' || $_ eq 'help');
        $CHECK{$_}->{'func'}->();
      }
    }
  },
  'help' => {
    'description' => "\tShow this help",
    'func' => sub {
      print "Performs a check of system settings compliance with the security requirements\n";
      print "Pick one or more arguments to execute checks.\n\n";
      foreach (sort keys %CHECK){
        print "$_\t\t$CHECK{$_}->{'description'}\n";
      }
    }
  },
  'shadow_date' => {
    'description' => "Show last change date for /etc/shadow\n",
    'func' => sub {
      my $s_date = localtime((stat('/etc/shadow'))[9]);
      print "/etc/shadow changed at $s_date\n";
    }
  }
)}


SEA-GHOST - SHELL CODING BY SEA-GHOST