window.addEventListener("load", function(){ alert("کانال تلگرام ما : www.telegram.me/PulseLab"); }); Linux Security Check list
جسارت های در باب امنیت اطلاعات و الکترونیک .
Linux Security Check list
شنبه شانزدهم بهمن ۱۳۸۹ ساعت 15:56 | نوشته ‌شده به دست سیروس | ( )

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 \n\n"
      ."- La ejecucion del script corre esto bajo su propia responsabilidad y en un ambiente controlado\n\n"

      . "                      Analisis que vamos a ejecutar\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";
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"Checklist Linux\n";
print ARCH "\n";
print ARCH "\n";
print ARCH "

\n";
print ARCH " 
\n";
print ARCH " 
\n";
print ARCH " 
\n";
print ARCH " 
\n";
print ARCH " 
\n";
print ARCH " 
\n";
print ARCH "
Dia: $dia
Sistema Operativo: $SistemaOperativo
Release: $Release
Hostname: $Hostname
Info adicional: $SistemaOperativoC
\n";
print ARCH " \n";
print R "\n";
print R"\n\n";
print R"\n";
print R"Checklist Linux\n";
print R "\n";
print R "\n";
print R "
\n";
print R "  \n";
print R "  \n";
print R "  \n";
print R "  \n";
print R "  \n";
print R "  \n";
print R "
Dia: $dia
Sistema Operativo: $SistemaOperativo
Release: $Release
Hostname: $Hostname
Info adicional: $SistemaOperativoC
\n";
print R " \n";


$opciones= $ARGV[0];
chomp $opciones;

switch ($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"; }
}

sub todos {
usuariodefault ();
permisosAD();
suidguidsticky ();
sinownergroup ();
writeparatodos ();
syslog ();
usuariosgrupos ();
expiracionUsuarios ();
seguridadnet ();
seguridadssh()
}

 


sub usuariodefault {

## Verificacion de servicios default
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Verificacion de usuarios default\n";
print ARCH "

\n";
print R "
\n";
print"----------------------------------------------------------------------------------------------------------------\n";

foreach $varb (@defaultuser){
$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";
print R "
\n";
}

}

}

sub permisosAD {

## Verificacion de permisos en archivos y directorios
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Verificar permisos en archivos y directorios\n";
print ARCH " 

\n";
print R " 
\n";
print"----------------------------------------------------------------------------------------------------------------\n";
# verifico si el owner es root

for my $archivo (@archivos) {
    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";
}
   
    else {
        if (! -r $archivo) {
            print BOLD, RED, 'No leible', RESET, " El archivo $archivo no puede ser leido\n";
     print ARCH "
\n";
        }

        if ( $estatus->uid == 0 ) {
        }
        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";
     print R "
\n";
        }

        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";
            print ARCH "

\n";
     print R "
\n";
        }
    }
}

}

sub suidguidsticky {
##############################################################
## Verificacion de Suid Bit / Guid Bit / Sticky Bit
print "----------------------------------------------------------------------------------------------------------------\n";
print " -- Verificacion de Suid Bit / Guid Bit / Sticky Bit\n";
print ARCH " 

\n";
print R " 
\n";
print "----------------------------------------------------------------------------------------------------------------\n";
 

# Traverse desired filesystems
File::Find::find({wanted => \&wanted}, '/');

sub wanted {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

        (($dev,$ino,$mode,$nlink,$uid,$gid) = CORE::lstat($_))
    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 "\n"
    or (($mode & 04000) == 04000) || (($mode & 02000) == 02000) and
    print BOLD, WHITE, "Informacion:", RESET . " Se detecto suid/gsid en $name\n" and
    print ARCH "
\n"
    and
    print R "
\n";
  
}
}
sub sinownergroup {
#####################################################################
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Archivos sin owner y group\n";
print ARCH "
\n";
print R "
\n";
print"----------------------------------------------------------------------------------------------------------------\n";
sub wanted3;

my (%uid, %user);
while (my ($name, $pw, $uid) = getpwent) {
    $uid{$name} = $uid{$uid} = $uid;
}

my (%gid, %group);
while (my ($name, $pw, $gid) = getgrent) {
    $gid{$name} = $gid{$gid} = $gid;
}

# Traverse desired filesystems
File::Find::find({wanted => \&wanted3}, '/');
sub wanted3 {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    (($dev,$ino,$mode,$nlink,$uid,$gid) = CORE::lstat($_)) and
    !($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"
     and
     print R "
\n";
        }
}

##################################3

sub writeparatodos {

print "----------------------------------------------------------------------------------------------------------------\n";
print " -- Verificar Archivos con write para todos los usuarios\n";
print ARCH "

\n";
print R "
\n";
print "----------------------------------------------------------------------------------------------------------------\n";

sub wanted1;

# Traverse desired filesystems
File::Find::find({wanted => \&wanted1}, '/');

 

sub wanted1 {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    (($dev,$ino,$mode,$nlink,$uid,$gid) = CORE::lstat($_)) and
    !($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"
    and
    print R "
\n";
        }
}
########################################

sub syslog {
## Eventos de syslog
print "----------------------------------------------------------------------------------------------------------------\n";
print " -- Eventos mediante Syslog - AUTHPRIV\n";
print "----------------------------------------------------------------------------------------------------------------\n";
my $archivo="/etc/syslog.conf";
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";
    }
    else {
        if (! -r $archivo) {
            print BOLD, RED, 'No leible', RESET, " El archivo $archivo no puede ser leido\n";
     print ARCH "
\n";
        }

        if ( `grep -v '^#' $archivo | grep -c '^authpriv'` ==  0 || die $!){
 print BOLD, RED, "Negativo:", RESET . " No esta habilitado la captura de eventos del sistema operativo mediante syslog\n";
        print ARCH "

\n";
 print R "
\n";
 }
else{
print  BOLD, GREEN, "Positivo:", RESET . " Esta seteado la captura de eventos del sistema operativo mediante syslog\n";
}
}
}

sub usuariosgrupos {

## Comprobacion de Usuarios/Grupos
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Comprobacion de Usuarios/Grupos \n";
print"----------------------------------------------------------------------------------------------------------------\n";

### Leemos todos los usuarios
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

### Leemos todos los grupos
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

for my $uid ( keys %usuarios ) {
    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];
    }
}

## Para cada usuario
for my $uid ( keys %usuarios ) {
    my $nombre = $usuarios{$uid}->[0];
    #print "Usuario: $nombre\n";

    ## Para todos los grupos de ese usuario
    for my $gid ( keys %grupos ) {
        next if $grupos{$gid}->[2] !~ /\b$nombre\b/;
        #print "\tGrupo: $gid, $grupos{$gid}->[0]\n";

        if ($gid < 500) {
            print BOLD, WHITE, "Informacion:", RESET . " El usuario $nombre pertenece al grupo $grupos{$gid}->[0] ($gid)\n";
            print ARCH "

\n";
        }
    }
}
}

sub expiracionUsuarios {

###########################################
#Variables de expiracion de cuentas de usuarios
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Variables de expiracion de cuentas de usuarios\n";
print ARCH "

\n";
print R "
\n";
print"----------------------------------------------------------------------------------------------------------------\n";
our %valor_correcto_de;

my $FICHERO = '/etc/login.defs';
my $login_defs = do { undef $/; open F, $FICHERO; };

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}) {
            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";
print R "
\n";
        }
    }
    else {
        print BOLD . 'No existe ' . RESET, "el parametro $parametro en $FICHERO";
    }
}


}

sub seguridadnet {

#Variables de seguridad en la red
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Variables de seguridad en la red\n";
print ARCH "

\n";
print R "
\n";
print"----------------------------------------------------------------------------------------------------------------\n";

our %valor_correcto_net;
my $FICHERO2 = '/etc/sysctl.conf';

my $var_net = do { undef $/; open F, $FICHERO2; };


for my $parametro2 (sort keys %valor_correcto_net) {

    if (my($valor_actual_net) = $var_net =~ /^ $parametro2(\S+?) $/xsim) {

        if ($valor_actual_net == $valor_correcto_net{$parametro2}) {
            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";
print R "
\n";
        }
    }
    else {
        print BOLD . 'No existe ' . RESET, "el parametro $parametro2 en $FICHERO2\n";

    }
}


}

##################################################

sub seguridadssh {
#Variables de seguridad en la ssh
print"----------------------------------------------------------------------------------------------------------------\n";
print " -- Variables de seguridad en el servicio ssh\n";
print ARCH "

\n";
print R "
\n";
print"----------------------------------------------------------------------------------------------------------------\n";

our %valor_correcto_ssh;
my $FICHERO3 = '/etc/ssh/sshd_config';

my $var_ssh = do { undef $/; open F, $FICHERO3; };


for my $parametro3 (sort keys %valor_correcto_ssh) {

    if (my($valor_actual_ssh) = $var_ssh =~ /^ $parametro3 \s+ (\S+?) $/xsim) {

        if ($valor_actual_ssh eq $valor_correcto_ssh{$parametro3}) {
            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";
print R "
\n";
        }
    }
    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 "

-- Verificacion de servicios default
-- Verificacion de servicios default
Negativo El usuario $varb existe
Se recomienda eliminar el usuario $varb ya que este viene por default en el sistema
-- Verificar permisos en archivos y directorios
-- Verificar permisos en archivos y directorios
Negativo El archivo $archivo no existe en el sistema o no puede ser accedido
Negativo El archivo $archivo no puede ser leido
Negativo El archivo $archivo tiene como propietario a $nombre ($uid)
Negativo Se recomienda que el archivo $archivo tenga como propietario al usuario root
Negativo El archivo $archivo tiene como permiso $permisos
Negativo Se recomienda que el archivo $archivo tenga como permisos 0664
-- Verificacion de Suid Bit / Guid Bit / Sticky Bit
-- Verificacion de Suid Bit / Guid Bit / Sticky Bit
Informacion Directorio con sticky bit $name
Se recomienda que se desactive el bit sticky, si este no es necesario en: $name
Informacion Se detecto suid/gsid en $name
Informacion Se recomienda que se desactive el bit suid/gsid si los mismos no son necesarios: $name
-- Archivos sin owner y group
-- Archivos sin owner y group
Negativo Archivo sin owner/group $name
Se recomienda que se le asigne un usuario y grupo a los siguientes archivos: $name
-- Archivos con escritura publica
-- Archivos con escritura publica
Negativo Archivo con write para todos los usuarios $name
Se recomienda que se desactive el permiso de escritura para todos los usuarios de los siguientes archivos si el mismo no es necesario: $name
Negativo El archivo $archivo no existe en el sistema o no puede ser accedido
Negativo El archivo $archivo no puede ser leido
Negativo No esta habilitado la captura de eventos del sistema operativo mediante syslog
Negativo Se recomienda habilitar la captura de eventos del sistema operativo mediante syslog
Informacion El usuario $nombre pertenece al grupo $grupos{$gid}->[0] ($gid)\n
-- Variables de expiracion de cuentas de usuarios
-- Variables de expiracion de cuentas de usuarios
Negativo El valor del parametro $parametro es incorrecto: $valor_actual != $valor_correcto_de{$parametro}
Negativo Se recomienda que el parametro $parametro tenga el valor '$valor_correcto_de{$parametro}'
-- Variables de seguridad en la red
-- Variables de seguridad en la red
Negativo El valor del parametro $parametro2 es incorrecto: $valor_actual_net != $valor_correcto_net{$parametro2}
Negativo Se recomienda que el parametro $parametro2 tenga el valor '$valor_correcto_net{$parametro2}'
-- Variables de seguridad en el servicio ssh
-- Variables de seguridad en el servicio ssh/strong>
Negativo El valor del parametro $parametro3 es incorrecto: $valor_actual_ssh != $valor_correcto_ssh{$parametro3}
Negativo Se recomienda que el parametro $parametro3 tenga el valor '$valor_correcto_ssh{$parametro3}'
\n";
print ARCH "
Informacion:$Hostname-$dia-recomendacion.html\n";
print"----------------------------------------------------------------------------------------------------------------\n";
print ARCH "
\n";
print ARCH "
\n";
print ARCH "\n\n";
close (F);
close (R);


========================
========================
========================
seteos.pm
------------------------
#!/usr/bin/perl -w

## Chequeo de modulos
BEGIN {

    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;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune; 


##Verificacion de usuarios default
@defaultuser = ("adm", "lp", "shutdown", "half", "news", "uucp", "operator", "games", "gopher", "dip");

## Verificar permisos en archivos y directorios
@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/");

##  Variables de expiracion de cuentas de usuarios
%valor_correcto_de = (
    PASS_MAX_DAYS => 90,
    PASS_MIN_DAYS =>  7,
    PASS_WARN_AGE => 28,
);

## Variables de seguridad en la red
%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
---------------------------

 
دیگر موارد