4. Conexiones de red
Arpmap
Todo administrador de una red grande basada en TCP/IP se topará tarde o temprano con que algún usuario que cree saber lo que hace ha modificado su dirección IP. Esto puede llevar al caos, imposibilitándonos saber qué computadora está causando choques de direcciones o dónde está determinada dirección. Este programa nos ayuda tomando fotografías de la red en determinado momento, para que podamos compararla con fotografías futuras.
Funcionamiento general
El programa es invocado dándole la interfaz sobre la cual trabajar - recuerden que arp es un protocolo no ruteable. El programa obtiene la configuración de la red del comando definido en $ifconfigCmd. Para guardar los resultados abre el archivo indicado en $filename, y si este ya existe lee los datos ya existentes para no volver a buscar direcciones ya resueltas. Posteriormente, revisa todo el segmento (funciona únicamente con redes clase B o clase C). Sugiero correr el programa a través de cron cada media hora por un par de días para encontrar también a las computadoras apagadas a la hora de la ejecución.
Funcionamiento: Obteniendo la configuración de la red
arpmap utiliza ampliamente la capacidad de encontrar patrones de Perl. Al llamar a ifconfig itera sobre el arreglo resultante, buscando primero que nada una línea que calce con ^[\w\d:]+ indicando el nombre de una interfaz de red. Si no especificamos al llamar al programa, pregunta cuál de las interfaces es la que nos interesa. Después de esto, asigna la siguiente línea a $ip y a $mask, para seleccionar en ambas únicamente la porción que nos interesa, reduciéndolas a cadenas [\d.]+
Funcionamiento: Resolviendo las direcciones
Para poder resolver una dirección IP hacia su MAC correspondiente tenemos que tenerla ya en el cache del kernel, es por ello que corremos $findCmd, que típicamente será un ping. Después de esto preguntamos por la IP utilizando $arpCmd, y buscamos en el resultado calzar con el patrón /Address.*HWtype/ (indicando una dirección encontrada) o /incomplete/ (indicando falla, usualmente por ser la dirección local). Para guardar la dirección utilizamos print a secas, dado que en la función &openFile tenemos un select(OUT), enviando toda salida estándar al archivo.
Reporte de resultados
El resultado de ejecutar este script es un archivo
con un formato como el siguiente:
192.168.1.1 - 00:50:DA:66:DB:5C
192.168.1.3 - 08:00:20:AE:C9:0C
192.168.1.6 - 00:50:DA:1F:00:7C
192.168.1.7 - 00:50:DA:66:DB:60
192.168.1.8 - 00:50:DA:0D:12:F2
192.168.1.9 - 00:A0:24:16:92:CA
192.168.1.10 - 00:60:97:60:60:50
192.168.1.20 - 00:50:DA:60:9A:E2
192.168.1.22 - 00:01:02:60:3B:EA
192.168.1.25 - 00:A0:24:16:93:BD
192.168.1.29 - 00:50:04:01:3D:A7
192.168.1.31 - 00:60:08:48:C2:5B
192.168.1.32 - 00:A0:24:C3:F9:49
192.168.1.33 - 08:00:20:76:8D:98
192.168.1.38 - 00:60:08:C7:5B:FB
192.168.1.41 - 00:60:08:C7:5C:00
192.168.1.44 - 00:A0:24:16:93:65
192.168.1.45 - 00:60:08:C6:77:3F
192.168.1.47 - 00:A0:24:1B:51:79
192.168.1.49 - 00:A0:24:15:97:D5
(...)
donde nos indica cada dirección IP localizada y su dirección
MAC correspondiente.
#!/usr/bin/perl -w
#
Maps the IP addresses on your local Ethernet to their ARP equivalents
#
REQUIRES: Being run by any user authorized to run ping, arp and ifconfig
use strict; use vars qw($ifconfigCmd $findCmd $arpCmd $interactive %done); my ($ip,$mask,$class,$filename);
———configuration area——–
Path to the ifconfig binary
$ifconfigCmd = ‘/sbin/ifconfig’;
Command to run to find a host
(a simple ping will do, just take care not to
execute an eternal ping)
#
Put %ip% where the IP should be given.
$findCmd = ‘/bin/ping -c 1 %ip%’;
Path to the arp binary
$arpCmd = ‘/sbin/arp’;
filename for output. If the file already exists, it
will be checked, in order not to repeat the whole
process.
If left empty, output will go to STDOUT.
if ($ARGV[1]) { $filename=$ARGV[1]; } else { $filename = ‘arpmap.txt’; }
—–end of configuration area—–
#
Run in interactive mode if called with no arguments
$interactive = ($#ARGV==-1);
($ip,$mask) = &findIp();
$class=&checkMask($mask);
&openFile($filename) if (defined $filename && $filename ne ‘’);
$|=1;
&getArp($ip,$class);
close(OUT) if (defined $filename && $filename ne ‘’);
exit 0;
sub openFile {
my ($filename);
$filename=$[0];
&readFile($filename) if (-f $filename);
open (OUT,”»$filename”) or die “Could not open $filename for output”;
select(OUT);
}
sub readFile {
my ($filename,@in,$line,$ip,$mac);
$filename=$[0];
open (IN,$filename) or die “Could not open $filename for input”;
@in=
spam
Todos nosotros odiamos el spam. ¿Cómo consiguen nuestras direcciones los spammers? Buscándolas por Web. Cualquiera de nuestros correos aparece casi seguramente en al menos una página. Ahora… Si tan solo pudiéramos alimentar con basura a los recolectores de direcciones para que su trabajo fuera inútil… ¡Pero podemos! Podemos darles cantidades ilimitadas de direcciones falsas… Eso es lo que hace este script. Gracias a Jason Costomiris por el escribirlo y publicarlo en http://www.jasons.org, de donde lo bajé.
Consideraciones de seguridad
Este CGI es bastante sencillo y está programado con cuidado. Sin embargo, hay algunos puntos a considerar:
- La página tiene una liga que conduce de vuelta a sí misma, lo cual -con un robot recolector suficientemente rápido- puede llevar a una negación de servicio. No olviden que levantar un CGI cuesta bastante tiempo.
- El levantar un CGI nos obliga doblemente a estar al día en problemas que pueda presentar nuestro servidor Web y el mismo Perl, dado que abrimos al mundo entero una ventana que permite ejecutar código -aunque sea nuestro- en el servidor. Si aparece algún método para explotar al servidor a través de CGIs, o algún problema con Perl, seremos vulnerables.
Funcionamiento general
Es un script muy sencillo. Después de crear dos arreglos, uno con las 26 letras del alfabeto y uno con varios top-level domains. Genera hasta 500 direcciones consistentes de hasta ocho letras para login y hasta 10 letras mas el TLD para el dominio, presentándolas en un CGI como ligas (<a href=”mailto:…“>). Por último, genera una liga hacia el mismo script, para que un robot recolector de direcciones sin mucha inteligencia caiga en un ciclo infinito de recolección de direcciones.
#!/usr/bin/perl -T
Copyleft 1997 Jason Costomiris (whois:JC1011).
Rights? You had rights? When I was a kid……
require 5.003; use strict; use CGI; my ($i, $j, $k); my @abc = (‘a’..’z’); my @tld = (‘com’, ‘net’, ‘org’, ‘mil’, ‘gov’, ‘hey-dork’, ‘spam-sucks’); my $fodder = new CGI; print $fodder->header; print $fodder->start_html(-title=>’Spam fodder’, -BGCOLOR=>’#FFFFFF’); print “<a href="mailto:abuse\?subject=I am a spamming luser">abuse</a><br/>\n”; srand; my $number = int(rand(500)); for ($i = 0 ; $i <= $number ; $i++) { my $name = “”; my $domain = “”; my $num_name = int(rand(8)); for ($j = 0 ; $j <= $num_name ; $j++) { $name .= $abc[int(rand($#abc))]; } my $num_domain = int(rand(10)); for ($k = 0 ; $k <= $num_domain ; $k++){ $domain .= $abc[int(rand($#abc))]; } my $tld = $tld[int(rand($#tld))]; my $address = $name . ‘@’ . $domain . ‘.’ . $tld; print “<a href="mailto:$address\?subject=I am a spamming luser">$address</a><br/>\n”; } #
Now that we’ve given lots of bad addresses to them, let’s put them in an
endless loop
#
print “\n<pgt;\n<a href="$ENV{SCRIPT_NAME}">endless loop of these pages for spam-spiders. Yay.</a>\n”;
print $fodder->end_html;
</code>
honeypot
Tras un ataque a nuestro sitio es muy importante analizar qué hizo el atacante - No sólo los pasos que siguió para penetrar en nuestro sistema, sino que también qué hizo una vez dentro. Muchas veces quisiéramos poder analizar qué intentos de intrusión ha habido, o frustrarlos dando al posible atacante información falsa. Para esto podemos crear sistemas trampa, que aparenten dar cierto servicio pero en realidad no lo estén dando, y sólo estén registrando todo lo que reciban. Perl es ideal para esto, dada su facilidad para la programación en red.
Consideraciones de seguridad
- Estamos ante un atacante. Si bien nuestro programa no debe tener ninguna característica que pueda comprometer al sistema, es importante que no lo corramos como root sino que como un usuario sin ningún privilegio, posiblemente desde inetd.conf
- El uso de estos sistemas es un tanto controversial - Por un lado, porque al dar información falsa estamos practicando seguridad por obscuridad, lo cual nunca sirve de mucho, y por otro lado, porque si un atacante se da cuenta de que está atacando a un sistema trampa, puede reaccionar empeñándose más en lograr penetrar el sistema.
Funcionamiento general
Hay varios servicios que son muy sencillos de emular, y que pueden no ser necesarios para nuestro sistema. Los ejemplos más clásicos son finger, SMTP, POP3 y HTTP. Claro, el juzgarlos innecesarios depende de cada sitio. Nuestro programa emulará respuestas válidas de estos servicios, registrando en syslog cualquier uso que el atacante intente hacer de ellos. Como todos estos servicios pueden ser iniciados desde inetd.conf, no nos preocuparemos de los sockets, manejando toda entrada y salida por las vías estándar.
Funcionamiento: Interacción con la red
La interacción será manejada por el demonio inet
, lo cual nos simplifica mucho la tarea: Toda entrada y salida la manejamos con STDIN
y STDOUT
.
STDIN
puede ser manejado como un socket, y lo hacemos en la función connData, donde obtenemos la dirección y puerto de la cual procede la comunicación.
Funcionamiento: Registro
Con un sistema trampa querremos registrar todo lo que el posible atacante intente hacer. Para hacerlo, utilizamos el Syslog
, utilizando el módulo Sys::Syslog
que viene incluído con la distribución estándar de Perl. Inicializamos el servicio con las siguientes líneas:
use Sys::Syslog qw(:DEFAULT setlogsock);
setlogsock('unix');
openlog('honeypot','cons,pid','honeypot');
y registramos cada línea recibida a través de la función logger
que simplemente hace:
syslog('info',join(' ',@_));
Funcionamiento: Lo implementado
En este script están implementados emuladores de tres populares protocolos: Finger, SMTP y POP3. Finger es un protocolo suficientemente sencillo como para poder sido emulado por completo con sólo un par de líneas. Cuando recibe una solicitud sobre cualquier usuario -válido o no- responde algo que aparenta éxito, al reportar conexiones marca que no hay nadie conectado, y al solicitar una redirección la niega.
POP3 responde en un formato similar al del servidor imapd
incluído en muchas distribuciones de Linux; reporta siempre éxito al recibir nombre de usuario y error al recibir la contraseña.
SMTP aparenta ser un sendmail. La implementación es muy sencilla, tal vez demasiado simple (no olviden que estos scripts son sólo ejemplos, no deben ser utilizados sin ser estudiados y modificados por el administrador): Responde exitosamente a cualquier HELO/EHLO
, y marca error a cualquier MAIL FROM
. Es importante responder siempre así, pues de no hacerlo un usuario podría legítimamente enviarnos un correo y nunca llegaría a su destino.
#!/usr/bin/perl -T
#
This script should be run from /etc/inetd.conf as follows:
#
(port) stream tcp nowait (user) (path-to-script) (script) (argument)
#
for example:
finger stream tcp nowait nobody /usr/local/sbin/honeypot.pl honeypot.pl finger
pop3 stream tcp nowait nobody /usr/local/sbin/honeypot.pl honeypot.pl pop3
#
IMPORTANT NOTE
Having a honeypot system does NOT make it any safer. In fact, it makes
it a GREAT target for attacks. An attacker might get angry at you laughing
at him and attack with greater strength. Even if you enhance its behavior,
it is not hard to notice you are not talking to a real server. Use this
ONLY at machines DEDICATED to network monitoring and information
gathering. Most important, USE AT YOUR VERY OWN RISK.
use strict; use Sys::Syslog qw(:DEFAULT setlogsock); use IO::Socket; use vars qw($hostname);
Set to the hostname you want to tell the clients
$hostname = ‘asdf.qwerty.org’;
$|=1;
setlogsock(‘unix’);
openlog(‘honeypot’,’cons,pid’,’honeypot’);
&connData;
if ($ARGV[0] eq ‘finger’) {
&finger;
} elsif ($ARGV[0] eq ‘pop3’) {
&pop3;
} elsif ($ARGV[0] eq ‘smtp’) {
&smtp;
} else {
&logger(“ERROR - $ARGV[0] not defined\n”);
}
exit 0;
sub pop3 {
# emulates a POP3 connection, accepting every username and
# denying every password. It honors the ‘quit’ command, in
# case a legitimate client tries to connect and refuses to
# leave unpolitely. Everything else is denied.
my ($request);
print “+OK POP3 $hostname v4.76 server ready\n”;
while ($request=
ProtoWrap
Concepto general:
Para evitar ataques a diferentes servicios, ProtoWrap envuelve la comunicación, permitiendo que pase únicamente lo que sea validado como correcto. Consultar http://www.gwolf.org/seguridad/wrap