TCP Port Knocking!
Port Knocking (PK) es una forma bastante ingeniosa y cuestionablemente segura de establecer una comunicación entre dos hosts mediante puertos cerrados. Tambien puede decirse que es una forma de “seguridad por oscuridad” pero yo particularmente no comparto esa visión.
Imaginen esta situación: Queremos acceder a un lugar que tiene 65536 puertas en su fachada. Golpeamos una puerta para nos abran y poder entrar pero no recibimos respuesta. Lo mismo ocurre con cualquier puerta que golpée. Del lado de adentro hay un conserje con instrucciones precisas que le indican que:
“Vas a abrir la puerta número 22 unicamente si alguien golpea primero las puertas 12865, 53271, 14780, 6912, 37312 y 43976″
El conserje se queda todo el dia prestando atención a que puertas golpea la gente que quiere ingresar y en que secuencia lo hace. Solo abre la puerta 22 si alguién previamente toca en la 12865, 53271, 14780,…etc. Simplemente ignora a todas las personas que no toquen en estas puertas en la secuencia correcta.
La técnica de PortKnocking consiste exactamente en el ejemplo anterior pero en lugar de edificio tenemos un host, en lugar de puertas tenemos puertos tcp y en lugar de conserje hay un daemon escuchando los SYN enviados para iniciar una coneccion tcp encargado de manejar un firewall. Cuando estos SYN llegan a los puertos indicados, que el cliente deberia conocer de antemano, el daemon se encarga de bajar el firewall que previamente bloqueaba todas las entradas.
Este método no reemplaza ningún otro mecanismo de autentificación pero puede servir para confundir un poco más a los posibles atacantes. La implementación no podria ser más simple. Basta con un programa que vigile los logs del firewall y en el momento que detecte la combinación correcta de tcp SYNs crea una regla para permitir el paso a un determinado puerto desde la IP que origino la secuencia de SYNs. Del lado del cliente alcanza con un script que, armado de un programa tipo nc, automatice la secuencia de intentos de conexiones al host destino. Tiempo atras, en mis epocas de BOFH, habia hecho una implementacion en PERL muy minimalista que espero poder encontrar y compartirla acá.
Existen muchas implementaciones dando vueltas por internet, algunas más avanzadas que otras, pero todas mantienen la misma filosofía. Más información en www.portknocking.org
Rentas, Patentes y RegExp
Introducción
Esto es una historia real que me ocurrio hace unos instantes. No sabia si postearlo acá pero como es mi blog hago lo que quiero. Hace un rato queria ver cuanto debía del impuesto de patente de mi auto. Por motivos que no es prudente comentar acá hacia tiempo que no me llegaban las boletas y no reclamaba asi que quise ver si internet me daba una solución. Vaya si me dio una solución… Por prudencia no voy a poner la dirección donde pueden encontrar las páginas que destriparé en los párrafos siguientes, confio en que sabrán googlear
Prolegómenos
Sin problemas encontré que en la página web de rentas de la ciudad autónoma de buenos aires es posible consultar el estado de la deuda con tan solo poner el número de patente. Sin embargo es necesario ingresar un “digito verificador” por motivos que, estimo, tienen que ver con salvaguardar la información del deudor. Dicho digito se encuentra impreso en la boleta pero como comente mas arriba, hace tiempo que no la tengo.
La página presentaba dos cuadros de texto donde introducir la patente y el digito verificador (se llama digito verificador a pesar de estar formado por Dos digitos). Puse la patente de mi auto y tire algunos digitos al azar. Naturalmente, no acerte con el digito verificador pero me llamó poderosamente la atención de que la validación se hacia instantaneamente y un hermoso alert() se encargaba de avisarnos de nuestro error. Algo olía a Javascript.
En pleno siglo XXI cuesta creer que alguien use javascript para realizar este tipo de validación, sin embargo las tecnicas de ofuscación de codigo a veces confunden a ciertas personas. Digo las confunde porque a veces se olvidan de ofuscar su código… asi que, firebug mediante, pude hacerme con el código de validación que comparto en este link.
Años atras, cuando el tiempo libre era algo que me sobraba, curioseando por ahí habia podido comprobar en incontables veces lo patético que son los emprendimientos informaticos del estado, sobretodo en lo referente a seguridad, desde el servicio meteorológico de las fuerzas aereas hasta el ministerio de educacion. Más cerca en el tiempo habia sufrido con las aplicaciones de rentas y los tramites via web de la afip. Sabía de las limitaciones del estado. Pero no sabia que se habian vuelto a superar…
Tratamiento
Todo empieza con una curiosa función titulada ValidarDigitoPatente() la cual, increiblemente, valida nuestra patente y el digito verificador. Efectivamente la lógica que hace la validación esta del lado del cliente y el codigo no esta ofuscado… bueno… no a la manera tradicional porque se las ingeniaron para que cueste entenderlo
Lo primero que hace esta función es validar que la patente ingresada sea valida (para los hermanos latinoamericanos en argentina las patentes, ó matriculas, de los autos tienen 3 letras seguidas de 3 digitos. ABC 123, DFG 167 y UIO 654 son ejemplos de patentes validas. Antiguamente se usaba una codificación formada por una letra y 7 numeros). El codigo que se encarga de hacer esto, contengan las risas, es el siguiente:
if (EsLetra(n.charAt(0))) {
if (n.length == 8 &&
isDigit(n.charAt(1)) &&
isDigit(n.charAt(2)) &&
isDigit(n.charAt(3)) &&
isDigit(n.charAt(4)) &&
isDigit(n.charAt(5)) &&
isDigit(n.charAt(6)) && isDigit(n.charAt(7))) {
Javascript posee una de las implementaciones mas lindas de expresiones regulares que existen. Los estatales argentinos, sin embargo, no saben usarlas. Esa maraña de código para chequear la validez de una patente se puede reducir a:
if(n.match('[a-zA-z]{3}[0-9]{3}')) {
Esta bien, no seria taaaaan grave que no dominen el arte oscuro de las expresiones regulares. Sucede que hay patentes de otro tipo de vehiculos, e incluso las patentes que se usaban antiguamente, que tienen otro formato. ¿Como hacen para evaluar los otros formatos? Facil, seguimos enmarañando el código.
if (isDigit(n.charAt(0))) {
if (n.length > 1 && isDigit(n.charAt(1))) {
if (n.length > 2 && isDigit(n.charAt(2))) {
if (n.length == 6 &&
EsLetra(n.charAt(3)) &&
EsLetra(n.charAt(4)) && EsLetra(n.charAt(5))) {
Más alla de esto lo que nos importa es poder averiguar el bendigo digito, que son dos, verificador. Para eso se valen de una enigmatica funcion Codigo(). Esta función recibe una letra y devuelve un número de dos cifras aparentemente asignados al azar, no soy un criptoanalista ni mire muy detenidamente la serie, pero esos numeros me parecen familiares. Bueno, con un array asociativo devolvemos como value dos digitos a partir de una letra que usamos como clave y listo. No necesariamente…
function Codigo(letra) {
if (letra == "a" || letra == "A") {
return "14";
} else if (letra == "b" || letra == "B") {
return "01";
} else if (letra == "c" || letra == "C") {
return "00";
//asi hasta el infinito y mas allá...
Detalles… detalles… ¿Pero como funciona la funcion validadora? Para seguir con la tradicion de los digitos del CUIT vamos a hacer un par de cuentitas con los valores que devuelve esta funcion y a otra cosa. En el caso de la patente de mi auto, con tres letras y tres digitos, el codigo verificador se evalua de esta forma:
//la patente esta en n
var a = new String(Codigo(n.charAt(0)) + Codigo(n.charAt(1)) + Codigo(n.charAt(2)) + n.charAt(3) + n.charAt(4) + n.charAt(5));
//quedaria a como un string de 9 digitos ya que cada letra se cambia por dos numeros y los ultimos 3 numeros quedan igual.
document.frmLogin.chapa_patente_copia.value = n;
//se copia la patente original (WTF?)
var digitos_impares = new String(a.charAt(0) * 1 + a.charAt(2) * 1 + a.charAt(4) * 1 + a.charAt(6) * 1 + a.charAt(8) * 1);
//aca empieza lo bueno: se castean los digitos en las posiciones pares de a y se suman entre ellos.
var digitos_pares = new String(a.charAt(1) * 1 + a.charAt(3) * 1 + a.charAt(5) * 1 + a.charAt(7) * 1);
//se hace lo mismo pero para las posiciones impares del string a
if (digitos_impares.length == 2) {
digitos_impares = new String(digitos_impares.charAt(0) * 1 + digitos_impares.charAt(1) * 1);
}
if (digitos_pares.length == 2) {
digitos_pares = new String(digitos_pares.charAt(0) * 1 + digitos_pares.charAt(1) * 1);
}
if (digitos_impares.length == 2) {
//aca es donde el agua nos empieza a tapar...
digitos_impares = new String(digitos_impares.charAt(0) * 1 + digitos_impares.charAt(1) * 1);
}
if (digitos_pares.length == 2) {
digitos_pares = new String(digitos_pares.charAt(0) * 1 + digitos_pares.charAt(1) * 1);
}
//aca es donde nos tapo el agua.
var digito_verificador = new String(digitos_impares + digitos_pares);
Con el agua al cuello puede darse la ¿casualidad? de que los benditos digitos_pares una vez sumados den una cifra de dos digitos, como 39, por lo que volvemos a sumarlos para obtener uno solo… aunque 3+9 da 11… deberiamos repetir el procedimiento y llegariamos como resultado a 2. No comprobe como se comportan los digitos que devuelve la funcion Codigo() para ver si podria darse el caso de llegar a situaciones que requieran volver a sumar los digitos del resultado hasta alcanzar un valor final de un solo digito. Los personajes de rentas aparentemente ya agotaron estas arduas cuestiones metafisicas y parece que con dos sumas siempre se llega a un resultado de un digito ¿maravilloso verdad? Para hacer esto no usaremos recursion, ni closures, ni un miserable ciclo while. Hacemos copy&paste del codigo y le prendemos una vela a los santos agradecidos por haber inventado el hardcoding.
Conclusión
Uno se encuentra con cosas raras en las operaciones informáticas de la administración pública. No puedo evitar reflexionar sobre estas cuestiones cada vez que tengo que hacer una declaracion jurada via internet en la pagina de la afip, o llenar un formulario de arba. Creo que la información de las personas es uno de los bienes más sensibles y deben ser manejados de la mejor forma por nuestras autoridades.
Lo importante resulto ser que el “digito verificador” de mi patente es el 43, uno más que el sentido de la vida, el universo y todo lo demás. Finalmente si alguien quiere saber cuanto debo de patentes esta es la respuesta que obtuve en el sitio de rentas:
ERROR DE COMUNICACION: INTENTE MAS TARDE.
Para todos los que llegan buscando como sacar su numerito de la suerte les dejo algo para que lo usen con fines beneficos solamente. Escriban la patente en el cuadro presionen en el boton, crucen los dedos y quiza se hagan con el numerito
Los 7 pasos a subversion
svn sin tunneling ni cosas raras en CentOS:
1) # yum install subversion
2) crear un directorio donde guardar los repos (ie: /home/svn/repositories)
3) crear un usuario/grupo svn para ejecutar el server.
4) iniciar el servidor svn con svnserve --daemon --root=/home/svn/repositories
5) crear un repositorio con:
#cd /home/svn/repositories
#sudo svn svnadmin create miRepo
6) editar el archivo /home/svn/repositories/miRepo/conf/svnserve.conf agregando
[general]
password-db = usuarios
realm = miRealm
auth-access=write
7) editar el archivo /home/svn/repositories/miRepo/conf/usuarios agregando
[users]
miusuario = mipassword
miusuario2 = miotropassword
8 ) enjoy!