Espero que esta sea una buena serie de articulos que les sirva de algo, si la quieren ver de nuevo pues manden mail pidiendola y me tomare el trabajo de escribir mas, si no...Esto ya es tiempo perdido.
Aclaro ademas que lo pongo en esta primera parte es: en parte traduccion y en parte cosas mias de "CASL for Linux Red Hat 5.x Programing Guide" que es un documento que viene acompañado por el programa.
-> ¨Que es CASL?
CASL es un lenguaje de scripting que
sirve para simular ataques de "bajo nivel" o "verificadores de recompilacion
de informacion" (no vi otra manera de traducirlo) en redes. Para hacer
scripts en CASL es necesario que construya los paquetes y los mande a un
host en una red, y los paquetes deben
ser iguales a los usados en un ataque
o un programa que consiga informacion. esto le permitira saber si el host
que se atacara es vulnerable a uno de los ataques mencionados anteriormente.
Lo otro que se necesita para hacer
programas en CASL es el interprete :)!
-> Requerimientos del Systema.
Esto es lo que usted necesita para
instalar el interprete de CASL:
-Red
Hat Linux 5.x (no necesriamente :)
-pentium
de 133
-32
en ram
-3
MB de espacio en el disco
-> Como se instala?
lo primero que se hace es bajar el
paquete del CASL que se debe, este viene con una extención tgz,
ahora le damos:
# tar xvzf archivo.tgz
esto sera descomprimido en un directorio
llamado casl-2.0 donde se pondran todos los archivos de configuracion,
etc, etc. leanse la instrucciones!
Ahora si empezamos, aclaro como dije antes que esto es sacado de una guia en ingles de CASL que viene con el programa lo que estoy haciendo es tomandome el trabajo de traducirla y agregar una que otra cosa.
Escribir programas que hagan o simulen
ataques de bajo nivel en los lenguajes de programacion tradicionales es
complicado y hay que saber mucho de ciertas cosas, pues para usar CASL
es bueno ser bueno es estos lenguajes de programacion aunque las cosas
se facilitan notablemente, pongamos un ejemplo:
El Tear Drop attack envia dos fragmentos
de paquetes a un servidor, estos dos gragmentos de paquetes se superponen
mutuamente lo que hace que windows nt y linux se caigan... la verdad
diciendolo es facil... pero esto no es facil en C y textualmente del manual
"impossible in COBOL" :)... el que me lo mande en cobol le doy un premio!...
La cosa es que esto en CASL no es tan complicado, mas bien facil.
Alguna de las ventajas que tiene el CASL es la "portabilidad de codigo" ya que un programa hecho en linux tambien se puede ejecutar (con su respectivo interprete de ordenes) en windows.
Esas son algunas de las caracteristicas principales de CASL.
-> Estructura de los programas en CASL.
Para escribir programas en CASL solo hace falta un editor de texto y por su puesto el interprete, ademas los programas deben tener lo siguiente:
- Elementos
- Variables
- Comentarios
- Paquetes
Los programas en CASL estan compuestos de declaraciones. Una declaracion va desde la una suma hasta leer un paquete udp. estas declaraciones actuan sobre variables. Las variables pueden ser:
- un caracter ASCII, que representa una sola expresion( ej, 'X')
- un numero que represente alguna de estas 2 opciones:
- un entero positivo o negativo.
- un numero entero en exdecimal que se representa con 0xNUMERO
- cadenas de caracteres de dos clases:
- sucesiones de caracteres (ej "hola Mundo")
- secuencias de control (ej. "\n")
- Un buffer, osea que agarre una recolentacion de datos, generalmente paquetes que salen.
- Una lista, osea que agarre una recolentacion de datos, generalmente paquetes que entran.
El CASL soporta comentarios que son ignorados por el interprete, esto en esta clase de programas en muy importante para ver que sale que entra etc, y para que el dia que se lo pases a alguien lo entienda o simplemente para que tu lo entiendas, los comentarios se notan muy parecido que en C puede ser "//" o "/*" para abrir "*/" para cerrar.
En CASL, uno puede crear packetes, que son unidades de datos de protocolo, desde cero. O se pueden usar los que CASL ya tiene predeterminados (muy comodo), definir un paquete en CASL requiere seleccionar el repectivo protocolo y poner los datos que iran en el paquete.
Ahora se a tomar un programa hecho en CASL y se explicara "step by step".
vamos a hacer TCP Stealth Port Scan, que es un escaneador de puertos que nos dice que puertos estan en espera de comunicacion pero nunca abre una de esta completamente...
El TCP Stealth Port Scan, funciona a groso modo de esta manera, manda un TCP SYN a la maquina en cuestion y espera una respuesta, la cual pude ser:
- un acknowledgment, lo cual indica que el puerto esta abierto o esperando para conexion.
- un reset, lo cual dice que no hay conexion por ese lado.
- o nada, indeca algo como un firewall.
**EL TCP Stealth Port Scan, no abre una conexion con el servicio si esta dispnible**
//**---------------------TCP Stealth
Port Scan--------------**
#include "tcpip.casl"
#include "packets.casl"
for(i =1;i <1023;i =i +1){
OurSYN = copy SYN;
OurSYN.tcp_source
= 10;
OurSYN.tcp_destination
= i;
OurIP = copy TCPIP;
OurIP.ip_source =
127.0.0.1;
OurIP.ip_destination
= 127.0.0.2;
OurPacket =[OurIP,OurSYN];
ip_output(OurPacket);
OurFilter = [ "src
host ", 127.0.0.2, " and tcp src port ", i ];
ReadPacket = ip_input(2000,
OurFilter);
if(!ReadPacket)
continue;
if(size(ReadPacket)
< size(IP) + size(TCP))
continue;
ReadIP=extract ip
from ReadPacket;
ReadTCP=extract tcp
from ReadPacket;
if(ReadTCP.tcp_ack
!= 1|| ReadTCP.tcp_syn != 1|| ReadTCP.tcp_rst == 1)
continue;
print("Port", i, "Alive");
}
//**---------------------TCP Stealth
Port Scan--------------**
ahora si la explicacion:
1- Para hacer un TCP Stealth Port Scan se necesita crear paquetes de TCP/IP. las cabeceras de los paquetes de TCP/IP ya estan incluidas en CASL. para poder accesarlas se usa:
#include "tcpip.casl"
#include "packets.casl"
2- Ahora se crea el TCP SYN que es el paquete que se envia al puerto para "arrancar" la conexion. Para crear el paquete TCP SYN se usa una cabecera de paquete TCP predeterminada, cambiando los parametros predeterminados por los apropiados. para crear el paquete se usa los siguiente:
OurSYN = copy SYN;
OurSYN.tcp_source = 10;
OurSYN.tcp_destination = 2049;
espero que se hallan tomado el trabajo de leer el codigo fuente para que no se confundan... aca se ve con se le asigna el puerto 10 al puerto de "fuente" (es un numero arbitrario) y al puerto destino se le asigna 2049 (puerto tcp nfs) a la cabecera del pauqete de tcp , esto ejemplifica un solo proposito. Estos puertos pueden ser cambiados como se quiera... mencione que hay que tener alguna idea de programar para seguir este texto???
3- lo que sigue es especificar el destino al que vamos a mandar el paquete TCP SYN. Lo que se hace es adherir una cabecera IP a la cabecera del TCP SYN, asi especificamos hacia donde vamos a mandar el paquete. para hacer lo anterior ponemos:
OurIP = copy TCPIP;
OurIP.ip_source = 127.0.0.1;
OurIP.ip_destination = 127.0.0.2;
las IP's puestas aca son solo para mostrar en el ejemplo pero cuando hagan el programa esten seguros de poner diereciones que sirvan para algo (y no estoy diciendo que las del ejemplo no sirvan)
4- ahora hay que combinar las las cabeceras del IP y el TCP SYN, esto pues... pa que esto sirva! no? quien dijo no! a ver!... ahora en serio, hay dos formas de hacer esto:
- una lista con varibles.
- lista con operadores.
para hacerlo con variables se pone de la siguiente manera:
PacketList = [ OurIP, OurSYN ];
lo anterior crea crea una lista llamada PacketList, con un operador para cada componenete de la lista, la categoria que abre empieza la lista y la categoria que cierra termina la lista, los valores individuales en la lista son separados por una coma (,).
ahora con operadores se hace de la siguiente manera:
PacketList = PacketList push OurSYN;
PacketList = PacketList push OurIP;
Este tambien crea un PacketList, pero con un operador separado para cada componente de la lista. las cabeceras TCP e IP son metidas por separado. El ultimo elemento adherido a la lista es el primer elemento escrito en la lista.
5- Sacar el paquete TCP SYN, esto se hace de la siguiente manera:
ip_output(PacketList);
6- Definir las conexiones a los puertos.
para encontrar los puertos pues hay que decirle al
programa cuales buscar para lo cual
usaremos un bucle "for" de la siguiente manera:
for (i = 1; i < 1023; i = i + 1)
{
//
}
aca lo que hay es un contador... todo el mundo lo entiende... espero... mejor lo explico:
- i=1 desde donde se empieza
-i > 1023 donde termina
- i = i+1 la cantidad que se cuenta
7- Ahora si la cosa completa, osea mandar el paquete al puerto:
For (i = 1; i < 1023; i = i + 1)
{
OurSYN = copy SYN;
OurSYN.tcp_source = 10;
OurSYN.tcp_destination
= i;
OurIP = copy TCPIP;
OurIP.tcp_source = 127.0.0.1;
OurIP.tcp_destination
= 127.0.0.2;
OurPacket =[OurIP,OurSYN];
ip_output(OurPacket);
}
8- Ahora vamos a leer las repuestas TCP.
Se usan rutinas ip_input() para verificar la respuesta de el host a la peticion de conexion hecha por el programa. Las rutinas ip_input() especifican el tiempo (em milisegundos) en que se atendio la conexion. ademas especifica los tipos de paquetes para ser leidos usando un tcp_dump filter.
para leer la respuesta del host a nuestro paquete usamos:
OurFilter = [ "src host ", 127.0.0.2, " and tcp src port ", i ];
donde i es igual a 103
ReadPacket = ip_input(2000, OurFilter);
si IP_INPUT() no lee completamente
el paquete devuelve un valor de cero (0), entonces cada vez que se use
ip_input() hay que comprobar el valor que devuelve con cero (0), para lo
cual
usamos:
if(!ReadPacket)
continue;
lo que hace el continue es hacer que el valor en el que va el bucle siga con el siguienteo, cuando el valor este completamente leido ip_input devorvera la respuesta con un paquete ip completo.
9- determinar los tipos de respuestas TCP. ahora lo que hay que determinar es si la respuesta es un tcp SYN-ACK que nos diria que el puerto esta escuchando y listo para recibir conexiones o si nos da un un TCP RST que nos diria que el puerto no esta disponible. esto se determina sabiendo el tamaño y la cabecera del paquete... ya explico...
primero se chequea el tamaño del paquete verificando que tenga cabeceras TCP e IP, para lo cual se usa:
if(size(ReadPacket) < size(IP) +
size(TCP))
continue;
esto le indica al interprete que se mueva hacia adelante en el bucle si el paquete IP es mas pequeño en tamaño que la suma de de cabeceras de TCP e IP. de lo contrario lo que haremos es estractar la cabecera del paquete entrante de la siguiente manera:
ReadIP = extract ip from ReadPacket;
ReadTCP = extract tcp from ReadPacket;
ahora los tenenmos divididos usando el operador "extract". ahora los compararemos individualmente para hacer las comprobaciones correspondientes. los SYN y ACK deben ser tenidos en cuenta mientras que los RST no. notese que si no son apropiados al condicional la coneccion podra ser hecha.
if(ReadTCP.tcp_ack != 1 || ReadTCP.tcp_syn
!= 1 || ReadTCP.tcp_rst == 1)
continue;
esta es una instruccion normal en C si no la entiende lo mejor es que se ponga a aprender algo de C antes de seguir leyendo, de hecho si no los entendio no se ni como llego hasta aca sin hartarse. lo que se dijo aca es que si el ack no existe o si un SYN no existe o si el RST si existe seguir con el bucle ya que el puerto no esta disponible, de lo contrario el puerto esta disponible.
10- Lo que sigue es virificar abrir la conexion... al fin! con la instruccion "print" damos las salidas... osea para mostrar lo que acabamos de hacer lo materializaremos en la pantalla para lo cual ponemos:
print("Port", i, "Alive");
si "i" es 1022, entonces: "Port 1022 Alive".
11- El programa completo, ahora si les va el programa como lo querian ver:
#include "tcpip.casl"
#include "packets.casl"
for(i =1;i <1023;i =i +1){
OurSYN = copy SYN;
OurSYN.tcp_source = 10;
OurSYN.tcp_destination
= i;
OurIP = copy TCPIP;
OurIP.ip_source = 127.0.0.1;
OurIP.ip_destination
= 127.0.0.2;
OurPacket =[OurIP,OurSYN];
ip_output(OurPacket);
OurFilter = [ "src host
", 127.0.0.2, " and tcp src port ", i ];
ReadPacket = ip_input(2000,
OurFilter);
if(!ReadPacket)
continue;
if(size(ReadPacket) <
size(IP) + size(TCP))
continue;
ReadIP=extract ip from
ReadPacket
ReadTCP=extract tcp from
ReadPacket
if(ReadTCP.tcp_ack !=
1|| ReadTCP.tcp_syn != 1|| ReadTCP.tcp_rst == 1)
continue;
print("Port", i, "Alive");
}
esto lo escriben en un editor de texto
y lo prueban (obviamente haciendo los cambios del caso, ya saben cuales)
y a probar!
Bueno creo que con lo que hay aca ya se puede empezar a jugar, la verdad pienso que si a esto se le saca un maximo provecho pues las cosas pueden ir muy bien y muy sensillas.
ya que esta es la primera parte... pues esperate a la segunda que ya me dio pereza sequir escribiendo, pero para la 2a perte esperen:
-> estructuras de los programas.
-> listas.
-> cabeceras de paquetes.
-> subrutinas.
y ya que no es mas pero tan poco menos
hasta aca llegamos por hoy, no oviden mandar sus mails diciendo si quieren
la 2a parte a -tcdiaries@uole.com- por que no me voy a poner a escribir
algo que nadie lee...
Mas informacion en HTTP://www.roses-labs.com,
HTTP://www.securityfocus.com
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
traducciones,
comentarios y burradas varias
por
Flameboy / TrenchCoat Legion.