checklist.pl
---------------------------
#!/usr/bin/perl -w
## Revisiones
## Script para verificar los lineamientos de seguridad - by situ
# 19/01/2011 = Se quitaron los
de mas del top de la pagina
# 19/01/2011 = Cambie la posicion de la impresion del dia.
# 19/01/2011 = Se elimino la verificacion del archivo /etc/rlogin.cfg
# 19/01/2011 = Se elimino el score
# 19/01/2011 = Se elimino el out
# 22/01/2011 = Los permisos y owner esta con el modulo file:stat
# 22/01/2011 = Se cambio la comprobacion de la config syslog
# 22/01/2011 = Se mejoro la performance del script, ya que antes hacia procedimientos iguales en muchas ocaciones
# 23/01/2011 = Busca arhivos con WRITE para todos los usuarios
# 23/01/2011 = Busca arhivos sin owner/grupo
# 23/01/2011 = Release nueva 2.0.2, todavia no subida al sitio: http://checklistlinux.sourceforge.net/
# 24/01/2011 = Se separaron las verificacion por funciones
# 26/01/2011 = Se quito el reporte
# 26/01/2011 = Se agrego la comprobacion de las variables de seguridad para net
# 27/01/2011 = Las variables mas relevantes se configuran en el archivo seteos.pm
# 28/01/2011 = Volvio el reporte HTML =) - me faltan arreglar algunas salidas
# 02/02/2011 = Se soluciono la comprobacion de los parametros de net,ssh
# 02/02/2011 = release 2.0.3
#Pua: La ejecucion del script corre esto bajo su propia responsabilidad y en un ambiente controlado
no warnings;
use File::Find ();
use File::stat;
use Switch;
use Term::ANSIColor qw(:constants);
use POSIX qw(strftime);
## Variables de identificacion del sistema
$SistemaOperativo=`uname`;
chomp $SistemaOperativo;
$Release=`uname -r`;
chomp $Release;
$Hostname=`hostname`;
chomp $Hostname;
$SistemaOperativoC=`uname -a`;
chomp $SistemaOperativoC;
$dia= strftime("%d-%m-%Y", localtime);
##Importo el archivo de configuracion de las variables mas relevantes
do 'seteos.pm';
if ( @ARGV != 1 ) {
die "\nUso: $0
."- La ejecucion del script corre esto bajo su propia responsabilidad y en un ambiente controlado\n\n"
. "
. " --usuariodefault Analizamos que los usuarios default del SO. no estan creados\n"
. " --permisosAD Analizamos los permisos de los archivos y directorios criticos del sistema\n"
. " --suidguidsticky Analizamos permisos especiales en todo el sistema\n"
. " --sinownergroup Buscamos en el sistema archivos/directorios sin owner\n"
. " --writeparatodos Buscamos en el sistema archivos/directorios con escritura para todos los usuarios\n"
. " --syslog Verificamos que este configurado un syslog externo\n"
. " --usuariosgrupos Asociamos los usuarios del sistema a sus respectivos grupos\n"
. " --expiracionUsuarios Verificamos las variables de expiracion de las cuentas de usuarios\n"
. " --seguridadnet Verificamos las variables de expiracion de las cuentas de usuarios\n"
. " --seguridadssh Verificamos las variables del servicio sshd\n"
. " --todos Ejecutamos todos los analisis\n"
;
}
print "----------------------------------------------------------------------------------------------------------------\n"; switch ($opciones) { sub todos { ## Verificacion de servicios default foreach $varb (@defaultuser){ } } sub permisosAD { ## Verificacion de permisos en archivos y directorios for my $archivo (@archivos) { if ( $estatus->uid == 0 ) { my $permisos = sprintf "%04o", $estatus->mode & 07777; if ( $permisos eq '0644' ) { } else { print BOLD, RED, "Negativo:", RESET, " El archivo $archivo tiene como permiso $permisos\n"; } sub suidguidsticky { # Traverse desired filesystems sub wanted { (($dev,$ino,$mode,$nlink,$uid,$gid) = CORE::lstat($_)) my (%uid, %user); my (%gid, %group); # Traverse desired filesystems (($dev,$ino,$mode,$nlink,$uid,$gid) = CORE::lstat($_)) and ##################################3 sub writeparatodos { print "----------------------------------------------------------------------------------------------------------------\n"; sub wanted1; # Traverse desired filesystems sub wanted1 { (($dev,$ino,$mode,$nlink,$uid,$gid) = CORE::lstat($_)) and sub syslog { if (! defined $estatus) { if ( `grep -v '^#' $archivo | grep -c '^authpriv'` == 0 || die $!){ sub usuariosgrupos { ## Comprobacion de Usuarios/Grupos ### Leemos todos los usuarios ### Leemos todos los grupos for my $uid ( keys %usuarios ) { ## Para cada usuario ## Para todos los grupos de ese usuario if ($gid < 500) { sub expiracionUsuarios { ########################################### my $FICHERO = '/etc/login.defs'; for my $parametro (sort keys %valor_correcto_de) { if (my($valor_actual) = $login_defs =~ /^ $parametro \s+ (\S+?) $/xsim) { if ($valor_actual == $valor_correcto_de{$parametro}) { sub seguridadnet { #Variables de seguridad en la red our %valor_correcto_net; my $var_net = do { undef $/; open F, $FICHERO2; if (my($valor_actual_net) = $var_net =~ /^ $parametro2(\S+?) $/xsim) { if ($valor_actual_net == $valor_correcto_net{$parametro2}) { } ################################################## sub seguridadssh { our %valor_correcto_ssh; my $var_ssh = do { undef $/; open F, $FICHERO3; if (my($valor_actual_ssh) = $var_ssh =~ /^ $parametro3 \s+ (\S+?) $/xsim) { if ($valor_actual_ssh eq $valor_correcto_ssh{$parametro3}) { } ################################################ ## Chequeo de modulos eval "use File::stat"; if ( $@ ) { warn "Error to load module: File::stat\n" . "Instalar Modulo:\n" . "\t\tcpan\n" . "\t\tcpan> install Unix::Uptime\n"; exit (); } } ## Seteos de las variables mas relevante del script Checklist-Linux-sinreprote.pl use vars qw/*name *dir *prune/; *name = *File::Find::name; ## Verificar permisos en archivos y directorios ## Variables de expiracion de cuentas de usuarios ## Variables de seguridad en la red );
print BOLD, YELLOW, "Sistema Operativo:", RESET . " $SistemaOperativo\n";
print BOLD, YELLOW, "Release del Kernel:", RESET . " $Release\n";
print BOLD, YELLOW, "Hostname:", RESET . " $Hostname\n";
print BOLD, YELLOW, "Datos Adicionales:", RESET . " $SistemaOperativoC\n";
open (ARCH,">> $Hostname-$dia.html");
open (R,">> $Hostname-$dia-recomendacion.html");
print ARCH "\n";
print ARCH"\n\n";
print ARCH"\n";
print ARCH"
print ARCH "\n";
print ARCH "\n";
print ARCH " \n";
\n";
print ARCH " \n"; \n";
print ARCH " Dia: $dia
print ARCH " \n";Sistema Operativo: $SistemaOperativo
print ARCH " \n";Release: $Release
print ARCH " \n";Hostname: $Hostname
print ARCH " \n";Info adicional: $SistemaOperativoC
print ARCH "
print ARCH " \n";
print R "\n";
print R"\n\n";
print R"\n";
print R"
print R "\n";
print R "\n";
print R " \n";
\n";
print R " \n"; \n";
print R " Dia: $dia
print R " \n";Sistema Operativo: $SistemaOperativo
print R " \n";Release: $Release
print R " \n";Hostname: $Hostname
print R " \n";Info adicional: $SistemaOperativoC
print R "
print R " \n";
\n";
$opciones= $ARGV[0];
chomp $opciones;
case "--usuariodefault" { usuariodefault(); }
case "--permisosAD" { permisosAD(); }
case "--suidguidsticky" { suidguidsticky(); }
case "--sinownergroup" { sinownergroup(); }
case "--writeparatodos" { writeparatodos(); }
case "--syslog" { syslog(); }
case "--usuariosgrupos" { usuariosgrupos (); }
case "--expiracionUsuarios" { expiracionUsuarios(); }
case "--seguridadnet" { seguridadnet(); }
case "--seguridadssh" { seguridadssh(); }
case "--todos" { todos(); }
else { print "----------------------------------------------------------------------------------------------------------------
Se a ingreso una opcion incorrecta\n"; }
}
usuariodefault ();
permisosAD();
suidguidsticky ();
sinownergroup ();
writeparatodos ();
syslog ();
usuariosgrupos ();
expiracionUsuarios ();
seguridadnet ();
seguridadssh()
}
sub usuariodefault {
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Verificacion de usuarios default\n";
print ARCH " \n"; -- Verificacion de servicios default
print R " \n"; -- Verificacion de servicios default
print"----------------------------------------------------------------------------------------------------------------\n";
$comando1 = (split ":",( qx(grep '^$varb' /etc/passwd ))[0] )[0];
chomp $comando1;
if ( "$comando1" ne "$varb" ){
}
else
{
print BOLD, RED, "Negativo:", RESET . " El usuario $varb existe\n";
print ARCH " \n";Negativo El usuario $varb existe
print R " \n";Se recomienda eliminar el usuario $varb ya que este viene por default en el sistema
}
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Verificar permisos en archivos y directorios\n";
print ARCH " \n"; -- Verificar permisos en archivos y directorios
print R " \n"; -- Verificar permisos en archivos y directorios
print"----------------------------------------------------------------------------------------------------------------\n";
# verifico si el owner es root
my $estatus = stat($archivo);
if (! defined $estatus) {
print BOLD, RED, 'No existe', RESET, " El archivo $archivo no existe en el sistema o no puede ser accedido\n";
print ARCH " \n";Negativo El archivo $archivo no existe en el sistema o no puede ser accedido
}
else {
if (! -r $archivo) {
print BOLD, RED, 'No leible', RESET, " El archivo $archivo no puede ser leido\n";
print ARCH " \n";Negativo El archivo $archivo no puede ser leido
}
}
else {
my ($nombre,$password,$uid,$gid,$quota,$comentario,$gcos,$dir,$shell,$expire) = getpwuid($estatus->uid);
print BOLD, RED, "Negativo:", RESET, " El archivo $archivo tiene como propietario a $nombre ($uid)\n";
print ARCH " \n";Negativo El archivo $archivo tiene como propietario a $nombre ($uid)
print R " \n";Negativo Se recomienda que el archivo $archivo tenga como propietario al usuario root
}
print ARCH " \n";Negativo El archivo $archivo tiene como permiso $permisos
print R " \n";Negativo Se recomienda que el archivo $archivo tenga como permisos 0664
}
}
}
##############################################################
## Verificacion de Suid Bit / Guid Bit / Sticky Bit
print "----------------------------------------------------------------------------------------------------------------\n";
print " -- Verificacion de Suid Bit / Guid Bit / Sticky Bit\n";
print ARCH " \n"; -- Verificacion de Suid Bit / Guid Bit / Sticky Bit
print R " \n"; -- Verificacion de Suid Bit / Guid Bit / Sticky Bit
print "----------------------------------------------------------------------------------------------------------------\n";
File::Find::find({wanted => \&wanted}, '/');
my ($dev,$ino,$mode,$nlink,$uid,$gid);
and !($prune |= ($dev != $File::Find::topdev))
and -d $_
and (($mode & 01000) == 01000)
and print BOLD . WHITE . "Informacion:" . RESET . " Se detecto sticky bit en $name\n"
and print ARCH " \n" and print R "Informacion Directorio con sticky bit $name \n"Se recomienda que se desactive el bit sticky, si este no es necesario en: $name
or (($mode & 04000) == 04000) || (($mode & 02000) == 02000) and
print BOLD, WHITE, "Informacion:", RESET . " Se detecto suid/gsid en $name\n" and
print ARCH " \n"Informacion Se detecto suid/gsid en $name
and
print R " \n";Informacion Se recomienda que se desactive el bit suid/gsid si los mismos no son necesarios: $name
}
}
sub sinownergroup {
#####################################################################
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Archivos sin owner y group\n";
print ARCH " \n"; -- Archivos sin owner y group
print R " \n"; -- Archivos sin owner y group
print"----------------------------------------------------------------------------------------------------------------\n";
sub wanted3;
while (my ($name, $pw, $uid) = getpwent) {
$uid{$name} = $uid{$uid} = $uid;
}
while (my ($name, $pw, $gid) = getgrent) {
$gid{$name} = $gid{$gid} = $gid;
}
File::Find::find({wanted => \&wanted3}, '/');
sub wanted3 {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
!($prune |= ($dev != $File::Find::topdev)) and
!exists $uid{$uid}
||
!exists $gid{$gid} and
print BOLD, RED, "Negativo:", RESET . " Archivo sin owner/group $name\n" and
print ARCH " \n"Negativo Archivo sin owner/group $name
and
print R " \n";Se recomienda que se le asigne un usuario y grupo a los siguientes archivos: $name
}
}
print " -- Verificar Archivos con write para todos los usuarios\n";
print ARCH " \n"; -- Archivos con escritura publica
print R " \n"; -- Archivos con escritura publica
print "----------------------------------------------------------------------------------------------------------------\n";
File::Find::find({wanted => \&wanted1}, '/');
my ($dev,$ino,$mode,$nlink,$uid,$gid);
!($prune |= ($dev != $File::Find::topdev)) and
-f _ and
(
(($mode & 02) == 02) and
! (($mode & 01000) == 01000)
) and
print BOLD,RED, "Negativo:", RESET . " Archivo con write para todos los usuarios $name\n" and
print ARCH " \n"Negativo Archivo con write para todos los usuarios $name
and
print R " \n";Se recomienda que se desactive el permiso de escritura para todos los usuarios de los siguientes archivos si el mismo no es necesario: $name
}
}
########################################
## Eventos de syslog
print "----------------------------------------------------------------------------------------------------------------\n";
print " -- Eventos mediante Syslog - AUTHPRIV\n";
print "----------------------------------------------------------------------------------------------------------------\n";
my $archivo="/etc/syslog.conf";
my $estatus = stat($archivo);
print BOLD, RED, 'No existe', RESET, " El archivo $archivo no existe en el sistema o no puede ser accedido\n";
print ARCH " \n";Negativo El archivo $archivo no existe en el sistema o no puede ser accedido
}
else {
if (! -r $archivo) {
print BOLD, RED, 'No leible', RESET, " El archivo $archivo no puede ser leido\n";
print ARCH " \n";Negativo El archivo $archivo no puede ser leido
}
print BOLD, RED, "Negativo:", RESET . " No esta habilitado la captura de eventos del sistema operativo mediante syslog\n";
print ARCH " \n";Negativo No esta habilitado la captura de eventos del sistema operativo mediante syslog
print R " \n";Negativo Se recomienda habilitar la captura de eventos del sistema operativo mediante syslog
}
else{
print BOLD, GREEN, "Positivo:", RESET . " Esta seteado la captura de eventos del sistema operativo mediante syslog\n";
}
}
}
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Comprobacion de Usuarios/Grupos \n";
print"----------------------------------------------------------------------------------------------------------------\n";
my %usuarios;
setpwent(); ## Inicio de acceso al fichero passwd
while ( my($nombre,$passwd,$uid,$gid) = getpwent() ) { ## Bucle por todos los usuarios
$usuarios{$uid} = [ $nombre, $passwd, $gid ];
}
endpwent(); ## Fin de acceso al fichero passwd
my %grupos;
setgrent(); ## Inicio de acceso al fichero /etc/group
while ( my($nombre,$passwd,$gid,$miembros) = getgrent() ) { ## Bucle para todos los grupos
$grupos{$gid} = [ $nombre, $passwd, $miembros ];
}
endgrent(); ## Fin de acceso al fichero /etc/group
my $gid = $usuarios{$uid}->[2];
my $miembros_del_grupo = $grupos{$gid}->[2];
if (!$miembros_del_grupo) {
$grupos{$gid}->[2] = $usuarios{$uid}->[0];
}
elsif ($gid !~ /\b$miembros_del_grupo\b/) {
$grupos{$gid}->[2] = join " ", $miembros_del_grupo, $usuarios{$uid}->[0];
}
}
for my $uid ( keys %usuarios ) {
my $nombre = $usuarios{$uid}->[0];
#print "Usuario: $nombre\n";
for my $gid ( keys %grupos ) {
next if $grupos{$gid}->[2] !~ /\b$nombre\b/;
#print "\tGrupo: $gid, $grupos{$gid}->[0]\n";
print BOLD, WHITE, "Informacion:", RESET . " El usuario $nombre pertenece al grupo $grupos{$gid}->[0] ($gid)\n";
print ARCH " \n";Informacion El usuario $nombre pertenece al grupo $grupos{$gid}->[0] ($gid)\n
}
}
}
}
#Variables de expiracion de cuentas de usuarios
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Variables de expiracion de cuentas de usuarios\n";
print ARCH " \n"; -- Variables de expiracion de cuentas de usuarios
print R " \n"; -- Variables de expiracion de cuentas de usuarios
print"----------------------------------------------------------------------------------------------------------------\n";
our %valor_correcto_de;
my $login_defs = do { undef $/; open F, $FICHERO;
print BOLD, GREEN, 'Positivo: ', RESET, "El valor del parametro $parametro es correcto\n";
}
else {
print BOLD, RED , 'Negativo: ', RESET, "El valor del parametro $parametro es incorrecto: ",
"$valor_actual != $valor_correcto_de{$parametro}\n";
print ARCH " \n";Negativo El valor del parametro $parametro es incorrecto: $valor_actual != $valor_correcto_de{$parametro}
print R " \n";Negativo Se recomienda que el parametro $parametro tenga el valor '$valor_correcto_de{$parametro}'
}
}
else {
print BOLD . 'No existe ' . RESET, "el parametro $parametro en $FICHERO";
}
}
}
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Variables de seguridad en la red\n";
print ARCH " \n"; -- Variables de seguridad en la red
print R " \n"; -- Variables de seguridad en la red
print"----------------------------------------------------------------------------------------------------------------\n";
my $FICHERO2 = '/etc/sysctl.conf';
for my $parametro2 (sort keys %valor_correcto_net) {
print BOLD, GREEN, 'Positivo: ', RESET, "El valor del parametro $parametro2 es correcto\n";
}
else {
print BOLD, RED , 'Negativo: ', RESET, "El valor del parametro $parametro2 es incorrecto: $valor_actual_net != $valor_correcto_net{$parametro2}\n";
print ARCH " \n";Negativo El valor del parametro $parametro2 es incorrecto: $valor_actual_net != $valor_correcto_net{$parametro2}
print R " \n";Negativo Se recomienda que el parametro $parametro2 tenga el valor '$valor_correcto_net{$parametro2}'
}
}
else {
print BOLD . 'No existe ' . RESET, "el parametro $parametro2 en $FICHERO2\n";
}
}
#Variables de seguridad en la ssh
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Variables de seguridad en el servicio ssh\n";
print ARCH " \n"; -- Variables de seguridad en el servicio ssh
print R " \n"; -- Variables de seguridad en el servicio ssh/strong>
print"----------------------------------------------------------------------------------------------------------------\n";
my $FICHERO3 = '/etc/ssh/sshd_config';
for my $parametro3 (sort keys %valor_correcto_ssh) {
print BOLD, GREEN, 'Positivo: ', RESET, "El valor del parametro $parametro3 es correcto\n";
}
else {
print BOLD, RED , 'Negativo: ', RESET, "El valor del parametro $parametro3 es incorrecto: $valor_actual_ssh != $valor_correcto_ssh{$parametro3}\n";
print ARCH " \n";Negativo El valor del parametro $parametro3 es incorrecto: $valor_actual_ssh != $valor_correcto_ssh{$parametro3}
print R " \n";Negativo Se recomienda que el parametro $parametro3 tenga el valor '$valor_correcto_ssh{$parametro3}'
}
}
else {
print BOLD . 'No existe ' . RESET, "el parametro $parametro3 en $FICHERO3\n";
}
}
print"----------------------------------------------------------------------------------------------------------------\n";
print BOLD, YELLOW, "Informacion:", RESET . " Se da por finalizado el proceso de chequeo\n";
print BOLD, YELLOW, "Informacion:", RESET . " El reporte fue salvado con el nombre: $Hostname-$dia.html\n";
print BOLD, YELLOW, "Informacion:", RESET . " Las recomendaciones fueron guardadas en el archivo: $Hostname-$dia-recomendacion.html\n";
print ARCH " \n";
\n";
print ARCH "Informacion:$Hostname-$dia-recomendacion.html\n";
print"----------------------------------------------------------------------------------------------------------------\n";
print ARCH "
print ARCH "
print ARCH "\n\n";
close (F);
close (R);
========================
========================
========================
seteos.pm
------------------------
#!/usr/bin/perl -w
BEGIN {
*dir = *File::Find::dir;
*prune = *File::Find::prune;
##Verificacion de usuarios default
@defaultuser = ("adm", "lp", "shutdown", "half", "news", "uucp", "operator", "games", "gopher", "dip");
@archivos = ("/bin/", "/boot/", "/etc/", "/etc/cron.daily/", "/etc/cron.hourly/", "/etc/crontab", "/etc/cron.weekly/", "/etc/exports", "/etc/fstab", "/etc/group", "/etc/hosts", "/etc/hosts.allow", "/etc/hosts.deny", "/etc/inetd.conf", "/etc/inittab", "/etc/ld.so.conf", "/etc/modules", "/etc/motd", "/etc/mtab", "/etc/passwd", "/etc/profile", "/etc/securetty", "/etc/syslog.conf", "/home/", "/lib/", "/mnt/", "/root/", "/sbin/", "/tmp/", "/usr/", "/usr/bin/", "/var/");
%valor_correcto_de = (
PASS_MAX_DAYS => 90,
PASS_MIN_DAYS => 7,
PASS_WARN_AGE => 28,
);
%valor_correcto_net = (
'net.ipv4.tcp_max_syn_backlog=' => 4696,
'net.ipv4.tcp_syncookies=' =>1,
'net.ipv4.conf.all.rp_filter=' => 1,
'net.ipv4.conf.default.rp_filter=' => 1,
'net.ipv4.conf.default.accept_source_route=' => 0,
'net.ipv4.conf.all.accept_source_route0' => 0,
'net.ipv4.conf.default.accept_redirects=' => 0,
'net.ipv4.conf.all.accept_redirects=' => 0,
'net.ipv4.conf.default.secure_redirects=' => 0,
'net.ipv4.conf.all.secure_redirects=' => 0,
'net.ipv4.icmp_echo_ignore_broadcasts=' => 1,
## Variables del sshd
%valor_correcto_ssh = (
Protocol => 2,
PermitRootLogin => 'no',
UsePrivilegeSeparation => 'yes',
);
===========================
===========================
===========================
===========================
===========================
End => SiroosOffline.BloGfa.com
---------------------------