Have you tried to turn it off and on again?
Alguna vez se pusieron a pensar en cuántas veces aplicamos la metodología "apagar y prender de nuevo"? Y no solamente a computadoras, sino a cualquier artefacto eléctrico que se nos cruce por el camino y que en algún momento tiene una falla... Lo más maravilloso de todo, es la cantidad de veces que esto funciona!
Desde máquinas de hacer café hasta mainframes, en algún momento de su vida útil, si se presenta una falla que parece no tener solución, le damos al botón apagar y prendemos de nuevo para ver si mágicamente todo vuelve a funcionar como antes.
Constantemente viene a la mente el maldito Windows y sus cuelgues, donde no queda más remedio que "resetear" la máquina, pero la realidad es que, si bien Windows es el caso más recurrente, todo soft puede fallar, y también el hardware... aunque la solución apagar y prender no siempre nos salva la vida.
El soft suele causar excepciones que si no se encuentran bien capturadas, puede significar en que no halla vuelta atrás, pero que si lo iniciamos de nuevo, el problema desaparece (a menos que volvamos a causar la misma excepción una y otra vez).
Otro problema es que el hard envíe una señal que el soft no esté preparado para manejar, ya sea mal funcionamiento del hard, o por falla en el diseño del soft. Igualmente, los problemas de hard, si son causados por una anomalía recurrente, la solución mágica nos durará solo unos minutos...

El motivo del post de hoy, es por lo recurrente que escucho esta frase en soporte técnico, y más que nada, como una referencia a la sarcástica serie británica The IT Crowd, donde la mayoría de las veces solucionan los problemas apagando y prendiendo.

Si en la vida se nos presentase la posibilidad de apagar y prender y que todo se arregle, sería demasiado fácil, pero quién no lo haría! =D

Para terminar, les dejo un chiste, ya viejo y que pueden encontrar fácil en la red, pero que viene perfecto para el post. Sigan apagando y prendiendo, que muchas veces ahorra tiempo! =D
news: cracking paquetes invisibles
El mismo día leo dos interesantes noticias sobre cracking de algoritmos utilizados para la transmisión wireless, ambos con implicaciones muy graves.

Por un lado me encuentro con que científicos japoneses dicen haber desarrollado una forma de romper WPA en 60 segundos! Para el que no lo sepa WPA (Wi-Fi Protected Access) es un protocolo para la transmisión segura de datos a través de una red wireless creado para suplir el fiasco de su predecesor, don me rompo todo WEP (Wired Equivalent Privacy). Si bien ya se habían evidenciado problemas con WPA en noviembre del año pasado, los muchachos japoneses se encargaron de llegar más allá y romper todo... unos maestros.
Actualmente, el protocolo más seguro es WPA2, que un algoritmo basado en AES, el cual es considerado completamente seguro (por ahora...).
Así que están avisados, si van a comprar un Access Point o algún otro hard wireless, asegúrense que soporte WPA2 y no la porquería WEP o el próximamente desechable WPA.


Por otro lado, me encuentro con algo aún más interesante. En la reciente conferencia Hacking at Random (HAR), un hacker detalló sus planes para crackear el estándar de encripción para celulares utilizado en GSM, conocido como A5/1!... qué quiere decir ésto? bueno, que alguien con el equipamiento adecuado (no demasiado caro) podrá escuchar llamadas GSM... osea, nuestras conversaciones por celular! yeah muchachos, ya nada será privado y nos podrán espiar hasta cuando hablemos a escondidas... a aquellos que anden de trampa con algún amante, les sugiero dejar de usar el cel =P
Si bien ya existían varios hacks teóricos al protocolo, este sería el primero en volverse realidad y en menos de 6 meses podríamos tener gente robando números de tarjeta, información de empresas, o cualquier cosa que hablemos/mensajiemos por celular.
Cómo crear un corrector ortográfico
Mientras buscaba cosas para mi tesis de grado el año pasado, y me preguntaba cómo funciona el "did you mean" de google, me encontré con algo re loco, el código de un corrector ortográfico. Por qué digo re loco? bueno, resulta que el susodicho código requiere sólo de 21 líneas en python! Realmente no podía salir de mi asombro, algo tan eficaz que requiera de tan poco código. Por supuesto que no me iba a convencer así nomas, así que lo testié, y efectivamente, funciona perfecto!
Despues de jugar un rato con el programa y serenarme un poco, me puse a analizar la "magia" con un poco de cuidado y por supuesto, descubrí que no hay magia, es todo muy lógico.
Para no ponerme a divagar despues de un día largo, simplemente les transcribo las palabras que utilicé en mi tesis para describir el algoritmo:

La corrección de palabras se logra utilizando un algoritmo basado en la distancia Levenshtein, también conocida como edit distance, que es una métrica para medir la cantidad de diferencias entre dos palabras. Esta diferencia está dada por el mínimo número de operaciones necesarias para transformar una palabra en otra, donde las operaciones son inserción, borrado o sustitución de un carácter, y transposición de dos caracteres.
El algoritmo genera el conjunto de palabras que se encuentran a una distancia d de la palabra a corregir, de este conjunto descarta las que no pertenezcan al diccionario utilizado y entre las restantes, selecciona la de mayor frecuencia. Con una alta probabilidad la palabra elegida será la que se deseaba. Este algoritmo es la base de los correctores ortográficos utilizados por Google, Office, Mozilla, etc.

Por supuesto, para que el algoritmo funcione, necesitaremos de un diccionario de palabras. Todos los correctores funcionan así, por un lado tienen el corrector y por otro lado los diccionarios.

Como sé que se están muriendo por ver y utilizar ese código, me dejo de palabreríos. El código que les transcribo, pueden encontrarlo en su página original http://www.norvig.com/spell-correct.html junto con una explicación de probabilidad sobre por qué el algoritmo funciona tan bien. Para poder utilizar el algoritmo, necesitarán, o bien crear un diccionario de palabras propio (que se llame big.txt), o bien descargar el ejemplo incluído en la misma página big.txt.

import re, collections

def words(text): return re.findall('[a-z]+', text.lower())

def train(features):
model = collections.defaultdict(lambda: 1)
for f in features:
model[f] += 1
return model

NWORDS = train(words(file('big.txt').read()))

alphabet = 'abcdefghijklmnopqrstuvwxyz'

def edits1(word):
s = [(word[:i], word[i:]) for i in range(len(word) + 1)]
deletes = [a + b[1:] for a, b in s if b]
transposes = [a + b[1] + b[0] + b[2:] for a, b in s if len(b)>1]
replaces = [a + c + b[1:] for a, b in s for c in alphabet if b]
inserts = [a + c + b for a, b in s for c in alphabet]
return set(deletes + transposes + replaces + inserts)

def known_edits2(word):
return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)

def known(words): return set(w for w in words if w in NWORDS)

def correct(word):
candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
return max(candidates, key=NWORDS.get)


Dado que el código está pensado para ser usado dentro de otros programas, no le crearon un lector de argumentos, así que para probarlo, abran una consola python (simplemente ejecuten el comando python en linea de comandos), y pegen el código anterior. Luego ejecuten la función correct y pasenle como parámetro la palabra que quieran corregir.
Si por ejemplo tipeamos:
>>>correct('speling')
la función nos devolverá:
'spelling'


Como para mi tesis necesitaba un corrector en java, me puse a buscar una versión del código anterior y encontré ésta página, donde trasladan las funciones a java. Este código utiliza 35 líneas, pero sigue siendo espectacular. Al igual que en el anterior, se utiliza el archivo big.txt como diccionario de palabras.

import java.io.*;
import java.util.*;
import java.util.regex.*;

class Spelling {

private final HashMap nWords = new HashMap();

public Spelling(String file) throws IOException {
BufferedReader in = new BufferedReader(new FileReader(file));
Pattern p = Pattern.compile("\\w+");
for(String temp = ""; temp != null; temp = in.readLine()){
Matcher m = p.matcher(temp.toLowerCase());
while(m.find()) nWords.put((temp = m.group()), nWords.containsKey(temp) ? nWords.get(temp) + 1 : 1);
}
in.close();
}

private final ArrayList edits(String word) {
ArrayList result = new ArrayList();
for(int i=0; i < word.length(); ++i) result.add(word.substring(0, i) + word.substring(i+1));
for(int i=0; i < word.length()-1; ++i) result.add(word.substring(0, i) + word.substring(i+1, i+2) + word.substring(i, i+1) + word.substring(i+2));
for(int i=0; i < word.length(); ++i) for(char c='a'; c <= 'z'; ++c) result.add(word.substring(0, i) + String.valueOf(c) + word.substring(i+1));
for(int i=0; i <= word.length(); ++i) for(char c='a'; c <= 'z'; ++c) result.add(word.substring(0, i) + String.valueOf(c) + word.substring(i));
return result;
}

public final String correct(String word) {
if(nWords.containsKey(word)) return word;
ArrayList list = edits(word);
HashMap candidates = new HashMap();
for(String s : list) if(nWords.containsKey(s)) candidates.put(nWords.get(s),s);
if(candidates.size() > 0) return candidates.get(Collections.max(candidates.keySet()));
for(String s : list) for(String w : edits(s)) if(nWords.containsKey(w)) candidates.put(nWords.get(w),w);
return candidates.size() > 0 ? candidates.get(Collections.max(candidates.keySet())) : word;
}

public static void main(String args[]) throws IOException {
if(args.length > 0) System.out.println((new Spelling("big.txt")).correct(args[0]));
}

}

A diferencia del código anterior, en este se encuentra un lector de argumentos, así que pueden utilizar el código directamente desde línea de comandos. Simplemente compilen el código con javac Spelling.java y luego ejecuten java Spelling para ver los resultados.


Si les interesó todo esto del corrector ortográfico pueden chequear algunos de los correctores que se utilizan en Linux, como ser aspell, ispell o myspell, entre otros.
curiosidades: nmap en las películas
Es bien conocido que Hollywood toma al hacking como una ciencia oscura donde el actor es un winner con las chicas y puede hacer que las máquinas le obedezcan guiándolas con la mente... a veces pienso que si mienten tanto con respecto a la informática, cómo lo harán con respecto a otros temas?
Claro que queda más lindo ver pantallitas 3D con los planos completos de los edificios donde piensan entrar la fuerza, navegadores de archivos 3D, gusanos que tienen forma de gusano (graficamente hablando) dentro de internet... pfffff de solo pensarlo da nauseas.

Por suerte hay algunas películas que se toman las cosas un poco más en serio y consultan a gente que sabe del tema, con lo que logran un resultado medianamente creíble.
A lo largo de los años, la herramienta que más ha aparecido en pelis es nmap, esa herramienta que debe poseer y saber manejar cualquier persona que pretenda saber seguridad o hacking. Nmap se ha hecho bastante famosa en Hollywood y ha sido utilizada en diversas escenas. Es por esto que en la página de Nmap han agregado una sección donde cuentan en qué escenas de qué películas aparece nuestra amada herramienta.
Si recuerdan alguna película donde haya aparecido nmap y no esté listada, maileen a la gente de Nmap y ellos lo agregarán a su página.
Si recuerdan escenas totalmente descabelladas, de esas que los que conocemos de esto sentimos verguenza, compartanlo en los comentarios =)

La lista de películas es la siguiente:

- The Matrix Reloaded: una de mis películas favoritas y se podría considerar que es la que catapultó al estrellato a Nmap.
Cuando Trinity necesita hackear el sistema de energía de la ciudad, ella utiliza Nmap 2.54BETA25 para escanear el servidor y descubrir que permite conexiones SSH. Luego utiliza el exploit SSH1 CRC32 para explotar una vulnerabilidad en el servicio y acceder al sistema. Genial!

- The Bourne Ultimatum: en la película de nuestro amnésico héroe podemos observar que la CIA necesita hackear un servidor de e-mail de un diario para leer el e-mail de un reportero que ellos asesinaron. Para ello utilizan Nmap y su GUI oficial Zenmap para hackear el server. Con esta herramienta descubren que el servidor está ejecutando SSH3.9p1, Posfix y un servidor de DNS. Sorprendentemente también utilizan BASH.

- Die Hard 4: si bien a mi me pareció muy exagerada (en todo sentido), en una escena, el hacker Matthew Farrell rescatado por John McClane, demuestra sus habilidades nmap.

- 13: Game of Death: esta película, también conocida como "13 Beloved" o "13 game sayawng", sigue la historia de un hombre que debe completar 13 desafíos para ganar 100.000.000 u$s. Cada juego se va poniendo más y más aspero, demostrando el clásico "Qué harías por 100 millones de dólares?". Nmap aparece cuando una de amiga del protagonista se encuentra muy preocupada por su amigo, y lo utiliza para hackear la página web del juego.

- The Listening: película sobre un oficial de la NSA que monta una estación clandestina en los alpes de Italia. En una de las escenas utiliza Nmap.

- Battle Royale: controvertida película japonesa, conocida en su tierra como Batoru Rowaiaru, cuenta como unos jóvenes son enviados a una isla abandonada equipados con collares explosivos y forzados a matarse entre ellos, como parte de un juego de supervivencia. Uno de los estudiantes es un hacker y puede verse mirando el código fuente de nmap en una de las escenas.

- Khottabych: en una secuencia de esta peli puede observarse a una hacker adolescente utilizando nmap y telnet para voltear Microsoft.Com. Microsoft y el gobierno de USA se enfurecen por el ataque y envían a una chica hacker Annie para derrotarlos.

- HaXXXor: No Longer Floppy: con esta película Nmap pega el salto de películas de ciencia ficción a soft porn. Esta película incluye una larga escena de entrenamiento con Nmap por la modelo E-Lita. Seguro que ya están saliendo a alquilarla, hackers depravados! =P
Top peores malwares de todos los tiempos
Hace un par de días, TrendLabs publicó en su blog un artículo para conmemorar los 6 años del worm MSBLAST, en el cual remarcan según su experiencia, cuales fueron los peores bichos que plagaron la red, basandose en el riesgo que representaron al usuario en relación a la tecnología que existía en el momento que el malware vió la luz.
Como amo los rankings, no pude abstenerme de publicar este top 5, el cual es más que interesante.

1. DOWNAD: Multiple propagación - múltiple peligro. Descubierto en Noviembre de 2008 , esta amenaza masiva se aprovecha de la vulnerabilidad MS08-067. Este generó multiples variantes, cada una mejorando la anterior.
El ataque generó 50.000 dominios y logró conectarse a 500 de estos, logrando evadir eficientemente la baja de dominios.

2. KOOBFACE: inicialmente descubierto en agosto de 2008, KOOBFACE se aprovecha de la conectividad brindada por redes sociales como Facebook o MySpace. Este infecta el perfil de usuario así que el atacante puede irrumpir en circulo de confianza del usuario, incrementando las chances de propagación.

3. ZBOT: Robo organizado de información. También es conocido como una variante del malware Zeus. ZBOT es un troyano spyware transmitido a través de e-mails o exploits Web. Este malware entrega información del usuario (números de tarjetas de crédito) a servidores remotos.

4. SQL Slammer: Este ataque se hizo famoso por disminuir drásticamente el tráfico de internet el 25/01/2003. Lo notable es que este worm consistía de un solo paquete en memoria, sin componente en el sistema de archivos, que explotaba una vulnerabilidad en MS SQL Server que ya había sido parchado (MS02-039). Lo más loco es que los efectos de esta amenaza siguen siendo visibles en el presente.

5. VBS_LOVELETTER: Increíblemente este ataque aprovechaba excelentemente la ingeniería social (el string "I LOVE YOU" en el asunto) que despertaba curiosidad en los receptores, plagando las casillas de e-mail en mayo del 2000. Logró infectar el 10% de las computadoras del mundo!


Como una mensión especial, la gente de TrendLabs también cita otros malwares, que si bien no fueron tan severos como los ya listados, afectaron a usuarios en todo el globo:

- Virus Melissa: el primer mailer masivo (marzo de 1999); volteó completamente el sistema de e-mails de internet, plagandolos con mails infectados.

- MSBLAST: uno de los worms más memorables que se aprovechaba de vulnerabilidades del sistema. Se lanzó en esta época en el 2003.

- SDBOT/AGOBOT: pionero en la creación de bootnets utilizando IRC. Los bots de IRC actuales siguen usando el mismo código base. Este sigue vivo al día de hoy.

- Web Toolkits: termino colectivo para software comercial que asiste a los cybercriminales.

- ILOMO: troyanos que se instalan via exploits Web que permanecen activos en memoria aún cuando el binario se elimina del sistema, resultando en múltiples reinfecciones (apareció por primera vez en marzo del 2009).
Programando tareas con cron
Para el que no tenga la más pálida idea de qué es cron, les comento que este es el administrador de tareas ejecutadas automáticamente en sistemas *nix, en horarios definidos o cada cierto intervalo de tiempo. Digamos por ejemplo que quieren que todos los días al mediodía el sistema chequee en busca de actualizaciones, esto se podría hacer muy fácilmente utilizando una entrada en el cron.
Cron es muy flexible y permite programar tareas para que se ejecuten cada cierto intervalo de tiempo, en determinado día de la semana, en determinado día del mes, y para usarlo solo necesitan saber lo que les explico a continuación.
Cabe mencionar que el cron utilizado en las distribuciones de linux es una versión extendida del cron original. La más reconocida es Vixie Cron, y es sobre la cual realizaré la explicación.


Quién puede programar tareas?

Cualquier usuario del sistema puede utilizar cron para programar tareas, siempre y cuando éste no se encuentre listado en el archivo cron.deny, o bien, si existe el archivo cron.allow, el usuario debe estar listado en él.
Para que tengan más claro el sistema de permisos allow/deny, cabe aclarar lo siguiente:
- si no existen ni el archivo cron.allow ni cron.deny, cualquier usuario puede ejecutar tareas programadas.
- si existe el archivo cron.allow, el usuario debe estar listado en el para poder ejecutar tareas programadas. En este caso, no importa lo que haya en cron.deny, si existe cron.allow, se ignora el contenido de cron.deny.
- si no existe cron.allow, pero sí cron.deny, el usuario NO deberá estar listado en este último para poder programar tareas.


Bien, dónde coloco la tarea a realizar?

Para programar tareas, el usuario debe utilizar el comando crontab, el cual le permitirá editar el archivo crontab correspondiente a su usuario. Como se habrán dado cuenta, cada usuario tiene su propio archivo crontab donde se almacenan las tareas programadas, en debian estos archivos pueden encontrarse en /var/spool/cron/crontabs/, pero no es aconsejable que los editen a mano, dado que un cambio directo en el archivo puede que no se vea reflejado en la instancia de cron en memoria, por lo que sus trabajos quizás no se ejecuten.
Al ejecutar crontab -e, el sistema nos abre nuestro crontab con un editor predeterminado. Si quieren utilizar un editor en particular, deberán setear la variable de entorno EDITOR. Si por ejemplo quieren editar el crontab con nano, primero deberán ejecutar "export EDITOR=/bin/nano".
Por otro lado, para ver si crontab actual, pueden ejecutar crontab -l. Por supuesto que root puede ver cualquier crontab, y esto lo hace ejecutando crontab -u -l.
Otras opciones interesantes de este comando son -r para remover el crontab actual, y -v para ver cuándo lo editamos por última vez.
Para saber un poco más sobre el comando crontab, RTFM!, es decir "man crontab" y "man 5 crontab".


Formato de los crontab

Vamos, llegó la parte interesante, el formato del ya recontra nombrado crontab. Cada entrada en el crontab cuenta con 5 campos, correspondientes al día, fecha y hora seguidos del comando a ejecutar, tomando la siguiente forma:

* * * * * comando a ejecutar
| | | | |
| | | | +---- día de la semana (0 - 6) (domingo=0 or 7) o bien sun,mon,tue,wed,thu,fri,sat
| | | +------- mes (1 - 12) o jan,feb,mar,apr ...
| | +---------- día del mes (1 - 31)
| +------------- hora (0 - 23)
+---------------- minuto (0 - 59)

En cada columna podemos especificar un valor de los mostrados en la figura, o bien pueden introducir varios valores utilizando diferentes operadores. Nunca deben introducirse espacios entre el operador y los valores, dado que el espacio es interpretado como si nos refiriésemos a otra columna. Los operadores que podemos utilizar son:
- La coma (','), que nos permite especificar una lista de valores, por ejemplo "1,2,5,6"
- El guión ('-') nos permite especificar un rango de valores, por ejemplo "1-8", lo cual es equivalente a "1,2,3,4,5,6,7,8"
- El asterisco ('*') que indica que ese campo puede tomar todos los valores. Por ejemplo, un asterisco en el campo de la hora, indicará que el comando se ejecute a cada hora (siempre sujeto a lo que indiquen los otros campos).
- La barra ('/') que podemos utilizar para saltar un dado número de valores. Por ejemplo, "*/3" en el campo de la hora es equivalente a colocar "0,3,6,9,12,15,18,21". El fundamento del ejemplo es que el "*" nos indica que se ejecute cada hora, pero el "/3" especifica que utilice sólo las horas divisibles por 3.

El comando a ejecutar puede ser cualquier comando ejecutable, incluso un script creado por nosotros mismos, o algún programa compilado. Cualquier ejecutable es válido.


Ejemplos salva papas

Siempre uno necesita ejemplos para aclarar lo explicado, así que ahí van algunos:

Como cité antes, supongamos que queremos mantener nuestro sistema actualizado, y queremos que se actualice todos los días (si es que hay actualizaciones) a las 12.15. Para esto, podríamos agregar una entrada en nuestro crontab que tenga el siguiente formato:

15 12 * * * apt-get upgrade &> /home/user/update_log.txt

En el ejemplo redirigí la standar output y la standar error a un log, así en caso que algo suceda, podremos verificarlo en un bonito log.

Ahora supongamos que queremos correr un script de backup todos los viernes a las 03:00, la entrada sería como la siguiente:

0 3 * * 5 backup

Por último, les dejo un ejemplo sin mucha utilidad, pero que demuestra el poder de cron. Supongamos que queremos que el 28 de febrero de cada año el sistema nos imprima en un log cada 5 minutos que hoy es 28 de febrero... ejemplo re loco =D La sintaxis sería la siguiente:

*/5 * 28 2 * echo "es 28 de febrero!" > /home/user/febrero.log

Jueguen con las opciones para obtener diferentes resultados, y lograr lo que desean.


Variables de entorno

En nuestro crontab, además de los trabajos que queremos ejecutar, podremos editar algunas variables de entorno, para que se adapten a nuestras necesidades. Es así como podemos decirle a cron que ejecute los comandos utilizando el shell bash y/o especificarle el path de los binarios.
Al principio de nuestro crontab podríamos tener algo como lo siguiente:
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/usr/games


Crontab del sistema

Así como existe un crontab para cada usuario, también existe uno para el sistema, es decir, para ejecutar tareas del sistema. El archivo designado para tal labor es el /etc/crontab. En este crontab podrán agregar cualquier tarea que deseen realizar, y ejecutarlas a nombre del usuario que más les guste. A diferencia de los crontab de usuario, no deberán utilizar el comando crontab para editarlo.
Si hechan un vistazo este crontab, encontrarán que tiene un formato ligeramente diferente y en muchas distribuciones, ya contiene algunas entradas default.
En este crontab, además de las columnas especificadas anteriormente, también contiene una columna donde se indica el nombre de usuario, a nombre del cual se ejecutará el comando.
Este nuevo formato es el siguiente:

* * * * * usuario comando a ejecutar

Los asteriscos tienen el mismo significado que antes, la única diferencia es que se incluye el nombre del usuario.
Como dije antes, muchas distribuciones traen entradas default en el crontab, estas suelen ser (por ejemplo en debian):

17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

Estas entradas predefinidas permiten que un usuario ejecute tareas a cada hora, diariamente, semanalmente o mensualmente, simplemente colocando un script o un link en las carpetas /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly.


Interfaces gráficas

Para el que no es muy amigo de la consola, también puede encontrar interfaces gráficas para manejar cron. Las que encuentro más interesantes son kcron para kde y gnome-schedule para gnome.


Algunas otras referencias:

Si bien traté de cubrir las partes más importantes para que puedan utilizar cron en sus tareas diarias, siempre algo queda fuera, además, por si quieren leer algunos ejemplos más que les aclare la idea, les dejo los siguientes links:
http://www.adminschoice.com/docs/crontab.htm
http://www.centos.org/docs/4/html/rhel-sag-en-4/ch-autotasks.html
https://help.ubuntu.com/community/CronHowto
http://en.wikipedia.org/wiki/Cron
http://www.linuxjournal.com/article/3290
http://www.debian-administration.org/articles/56
http://www.softpanorama.org/Utilities/cron.shtml
http://www.debianhelp.co.uk/schedulejobs.htm
Ocultando URLs con JavaScript
No se si muchos lo habrán notado, pero uno suele confiar en las urls que aparecen en la barra de estado del navegador cuando colocamos el mouse sobre un link. Bueno, esto no debería ser así!

Hace ya bastante tiempo que observo que si hacemos mouse over sobre los resultados devueltos por google, vemos la dirección real de la página a la que hace referencia. Esto me puso a pensar... google mantiene muchas estadísticas de los usuarios, así que si colocan directamente la dirección de una página en sus resultados, ellos no tienen forma de darse cuenta si clickeamos un link o no... debe haber algo detrás!
Bien, hoy ya no pude más con la incertidumbre, así que le di un vistazo al código de la página y encontré la verdad oculta. Esto me dio pie para explicar algunas formas simples de ocultar el destino real de un link y engañar al usuario.

Hay algunas formas de ocultar la URLs para engañar al usuario... la más simple es escribir una dirección de url entre tags <a></a> (osea, lo que se ve en el browser), pero hacer que el puntero apunte a otra dirección. Por ejemplo si tenemos el siguiente link <A HREF="http://tehackeo.com">http://www.google.com</A> el usuario verá en el browser la dirección http://www.google.com, pero el enlace realmente apunta a http://tehackeo.com. Esto es un engaño bastante simple y usado incluso en los e-mails falsos, y puede despistar a los más básicos. Si colocamos el mouse sobre el link, en la barra de estado veremos la dirección real del link.

Algo que se podía hacer hace algún tiempo, era modificar desde Java Script lo que el browser muestra en el status bar, usando la propiedad window.status. Por suerte en los browsers modernos removieron esta facilidad. En firefox si miran en about:config veran que la propiedad dom.disable_window_status_change está en true, osea, que no podemos modificar el valor de la barra de estado.

Otra forma para ocultar la url real usando Java Script, es hacer no solo que el link falso aparezca en el cuerpo de la página, sino también en la barra de estado del browser y además en el código html! De esta forma, podemos lograr un mejor efecto, haciendo creer al usuario que accede a donde cree, mientras lo redirigimos a donde queremos =D

La forma en que google resuelve esto es bastante simple, utilizar la función de JS onMouseDown para reescribir la url justo en el momento en que el usuario hace click y lograr que el resultado sea un acceso a google y no a la página real... mágico?... no, bastante simple pero efectivo. De esta forma, no sólo la dirección aparecerá en el status bar, sino que también aparecerá en el código html!, y tendremos que revisar una función de Java Script bastante codificada para entender el resultado final.
Para que se den una idea, ustedes pueden utilizar un código como el siguiente:
<A HREF="http://www.google.com" onMouseDown="return codifica(this);">http://www.google.com<A>
<SCRIPT>
function codifica(link)
{
link.href="http://tehackeo.com";
link.onmousedown = "";
return true;
}
</SCRIPT>
Con ese sencillo código despistaremos hasta a los usuarios avanzados que no se tomaron el tiempo de analizar el código HTML... y es lo que suele pasar. Imaginense, uno no se la pasa mirando el código HTML de todas las páginas que visita para saber si las URLs que sigue son válidas o no. Pero el problema es que podemos terminar en una página con cualquier tipo de malware, cuando en realidad capaz queríamos ver la página de un amigo! =P

Más allá del uso maligno de este código, también nos sirve para demostrar que Google nos observa constantemente... estén alerta =P
Evitando que un programa explote, técnicas para detectar buffer overflows
Como lo prometí hace algunos días en mi artículo sobre buffer overflows, hoy les traigo las técnicas de defensa más importantes contra esta vulnerabilidad.
Existen varias técnicas que se pueden aplicar a distintos niveles de la vida de un programa, así que las dividí siguiendo esta idea. A continuación planteo qué es lo que podemos hacer, dependiendo en qué nivel nos encontremos:


qué puede hacer el programador?

El programador es el principal encargado de eliminar la posibilidad de buffer overflows, pero muchas veces es el que tiene menos idea del tema, por eso es importante que preste atención a lo siguiente:
- elegir un lenguaje que chequee los límites de un buffer antes de asignarle datos. Los lenguajes más riesgosos conocidos son C y C++, los cuales no realizan ningún chequeo y básicamente permiten que uno "haga lo que quiera". Los que si chequean correctamente los límites son los interpretados, o los compilados a bytecodes, como python, java, ruby, etc.
- si se utiliza un lenguaje como C/C++, utilizar funciones de librería que chequeen límites antes de leer datos de entrada. Hay funciones conocidas por no realizar chequeos y ser utilizadas comúnmente, las cuales deben evitarse, como por ejemplo gets, scanf, strcpy, etc. Igualmente, como muestran en Advances in adjacent memory overflows, ni siquiera utilizando versiones seguras de librerías estaremos a salvo =S
- utilizar librerías bien testeadas. A veces nuestro programa puede estar libre de bofs, pero si las librerías utilizadas tienen el citado problema, entonces estamos en peligro. El problema de los exploits encadenados es muy peligroso.
- por supuesto, como última e importante recomendación está la siempre sabia frase "trust no one", es decir, siempre que se ingresen datos al programa, chequearlos antes de asignarlos a una variable.


qué puede hacer un compilador?

Existen algunas extensiones a compiladores como gcc que permiten al compilador ayudar bastante en la protección contra los buffer overflows. Entre las extensiones más conocidas se pueden citar:

- StackGuard. Esta extensión para el compilador gcc existe desde 1997 (osea, hace rato) y lo que hace es que el compilador inserte una marca (llamada "canario") en la pila inmediatamente después de haber almacenado la dirección de retorno en la misma. De esta forma, si ocurre un buffer overflow que intenta sobre-escribir la dirección de retorno, éste deberá primero sobre-escribir el canario (pobre canario). Antes de retornar, la función revisará el valor del canario y si detecta que fué sobre-escrito, arrojará la excepción segmentation fault. El canario es un valor difícil de utilizar por un atacante y puede ser de tres tipos: terminator (NULL, CR, LF, -1), random y random xor. Es más seguro utilizar valores random para el canario, pero otros terminadores como NULL serían difícil de insertar en un buffer overflow que intente sobre-escribir la dirección de retorno.

- Stack-Smashing Protector (ProPolice). Otra extensión para gcc que funciona de manera similar a StackGuard, esto es, utilizando un canario para detectar sobre-escritura. SSP presenta una mejora al sistema de StackGuard, dado que protege todos los registros salvados en el prólogo de una función, no sólo la dirección de retorno.
SSP actualmente es estándar en OpenBSD (el SO más seguro del mundo), FreeBSD, Ubuntu, DragonFly BSD, IPCop.

En el ambiente actual, StackGuard y SSP son los más utilizados y mantenidos, pero también han surgido otras extensiones interesantes, que parecen no seguir siendo soportadas (no encontré info que supere el año 2000). Debido a que valen la pena, las menciono a continuación:

- Stack-Shield. También trabaja con gcc (es un preprocesador en assembler) y protege tanto de buffer overflow directos e indirectos. Su funcionamiento se basa en agregar instrucciones durante la compilación para copiar las direcciones de retorno en un segmento de datos aparte. Sería difícil para un atacante modificar la dirección de retorno almacenada en la pila y la copia en el segmento de datos al mismo tiempo. Cuando una función retorna, se comparan ambos valores y se lanza un alerta si no coinciden.
Stack Shield también provee un mecanismo secundario. Este se basa en implementar un chequeo de rango en la llamada a función y la dirección de retorno. Si el programa intenta realizar una llamada a una función que caiga fuera del rango predefinido, o si una función retorna a una locación fuera del rango, entonces se asume que ocurrió un ataque y se termina el proceso.

- Return Address Defender (RAD). Otro parche para gcc que funciona de forma similar a StackShield. Este almacena una copia de la dirección de retorno en un repositorio, pero luego usa las funciones de protección de memoria del sistema operativo para detectar ataques contra este repositorio. RAD hace que el repositorio entero sea read-only o bien marca las páginas vecinas como read-only.

Cabe citar que Microsoft también provee un parche similar en Visual Studio llamado "Microsoft Visual Studio /GS". Este funciona de forma muy similar a StackGuard, utilizando canarios para proteger direcciones de retorno y frame buffer.
Existe un paper interesante llamado "Four Different Tricks to bypass StackShield and StackGuard protection" donde se explica cómo es posible saltear las protecciones de StackShield, StackGuard e incluso la de Microsoft Visual Studio /GS.


qué se puede hacer una vez que se ejecuta el programa?

Una vez que el programa llegó categoría ejecutable, tendremos que atrapar los problemas que nos relegaron los programadores a nivel de sistema operativo. Para esto se han desarrollado algunas modificaciones que harán lo posible por proteger al sistema contra los buffer overflows. Las técnicas más conocidas son las siguientes:

- Marcar los segmentos de datos y pila como NO ejecutables. Esa es la salida más lógica y fácil de implementar, dado que el hardware hace años que ofrece facilidades marcar las páginas/segmentos como read-only, escribible, ejecutable y algunas otras variantes. Es decir, simplemente tenemos que setear un bit para marcar las páginas como no ejecutables. Si hacemos que la sección de datos y la pila no sean ejecutables, evitaremos que el atacante ejecute código insertado por él en el overflow. Sin embargo esta solución no es completa, dado que el atacante todavía puede realizar el conocido ataque return to libc, donde se modifica la dirección de retorno para apuntar a una librería de sistema cuya dirección es conocida, y utilizar variables sobre escritas como parámetros de la función.

- Address space layout randomization (ASLR). Esta técnica involucra organizar aleatoriamente la posición de áreas de datos claves, incluyendo la base de lo ejecutable y la posición de librerías, heap, y stack en el espacio de direcciones del proceso. Esta randomización permite evitar que un atacante pueda precedir las direcciones de los objetivos.
Esta solución permite evitar ataques del tipo return to libc, dado que necesita localizar el código a ejecutar, además, ataques que inyectan shellcode en la pila deberán hallar la dirección de la pila primero.

- Utilizar una modificación de librería llamada Libsafe, la cual intercepte todas las llamadas a funciones vulnerables conocidas y ejecute una versión "segura" de las llamadas. Las versiones seguras estiman un limite para el tamaño del buffer destino.
El inconveniente de Libsafe es que sólo añade seguridad a funciones conocidas y sólo en programas linkeados dinámicamente.

- Proof-carrying code. Esta técnica basa su funcionamiento en una prueba (poof) sobre cómo un programa debería funcionar. A medida que el programa se ejecuta se observa el comportamiento y se compara con la prueba, si se detecta una desviación, estaremos frente a un problema y el programa puede abortarse.
El problema de este mecanismo es que los programas deben venir con esta prueba, la cual debe ser desarrollada con precaución, y el mecanismo puede significar una sobrecarga apreciable para el sistema.

- Program Shepherding. Esta técnica previene la ejecución de código malicioso monitoreando todas las transferencias de control (jmp, call, return, etc) para asegurarse que cada una satisface una dada política de seguridad. Para lograr esto utiliza tres técnicas: código orígen restringido (se clasifica qué código puede ser ejecutable y qué no), transferencias de control restringidas (condiciona qué saltos son válidos), y agregando Sandboxing en las operaciones.
Como uno se puede imaginar, este sistema, si no está bien optimizado, podría incurrir en severos problemas de performance.


Tanto el seteo de los segmentos/páginas de datos como no ejecutables, como ASLR están incluídos en el parche para el kernel de linux PaX. PaX implementa protección de mínimos privilegios para las páginas de memoria. Hasta donde tengo entendido, PaX aún no fue incorporado en el kernel por defecto debido a que se considera en estado beta.
Por su parte, Windows también incorporó la protección de datos a partir de XP SP2 a través de Data Execution Prevention (DEP), aunque no viene activado por defecto por compatibilidad hacia atrás. Este puede activarse, pero he leído sobre algunos programas que dejan de funcionar correctamente. También a partir de Windows Vista se incorporó ASRL en los SO de Microsoft.


Cómo puede ayudarnos el hardware?

Como sucede con todo nuevo reto, el hardware se va adaptando para ayudar al sistema operativo a realizar sus funciones. Ayudas como los bits de protección entre modo monitor y modo usuario, bits de protección de páginas y muchas otras cosas se han ido incorporando a medida que surgía la necesidad. Por esto es importante saber qué puede brindarnos el hardware a la hora de defendernos de los buffer overflows, y qué implementaciones están haciendo uso de ello.
Entre los proyectos más destacados, podemos citar:

- SmashGuard: usa versiones modificadas de las micro codificadas instrucciones para CALL y RET para habilitar de forma transparente protección contra ataques por buffer overflow. Esta solución aprovecha que las CPUs modernas cuentan con grandes espacios de memoria para crear una pila secundaria para almacenar las direcciones de retorno (similar a lo que hace StackShield). Al igual que StackShield, cuando se realiza un CALL, se almacena la dirección de retorno tanto en la pila común como en la pila secundaria, luego, cuando se ejecuta el RET, se comparan los valores de la pila con la copia y si difieren ocurre una excepción.
Cabe destacar que ésta solución no es parte de ningún CPU, sólo se ha probado en simuladores.

- Split Stack and SRAS (secure return address stack). Este sistema (similarmente a SmashGuard) divide la pila en dos, una pila control donde se almacenan las direcciones de retorno y una pila de datos, donde, obviamente, se almacenan los datos. Gracias a esta división, sería imposible que un overfow sobre-escriba una dirección de retorno.
Split Stack presenta tanto una solución a nivel de compilador como a nivel de arquitectura, así que podría haber entrado en la sección de lo que puede hacer el compilador.
Por otra parte se ofrece la solución Secure Return Address Stack (SRAS), donde se almacenan en el SRAS todas las direcciones de retorno cuando se realiza un CALL que luego se usan en las subsiguientes instrucciones RET.

- StackGhost. Parche para el kernel de OpenBSD que corre en arquitecturas Sparc que ajusta las rutinas spill/fill de venana de registros para hacer que los buffer overflows sean mucho más difíciles de explotar. Este usa una característica del hardware para detectar modificaciones en las direcciones de retorno transparentemente, automáticamente sin requerir ninguna modificación en las aplicaciones.
Es necesario conocer un poco de la arquitectura Sparc para entender mejor cómo funciona esta técnica, así que en las referencias les dejo el nombre del paper donde lo explican.


qué se puede hacer a nivel de red?

A nivel de red podemos evitar que exploits conocidos lleguen a tocar nuestras máquinas utilizando sistemas de detección de intrusos (IDS) como snort, los cuales buscan patrones de exploits en los payloads de los paquetes. Esta es la primer barrera que podemos poner para evitar que los problemas ni siquiera lleguen a las máquinas.


y qué hay de los antivirus?

Muchos antivirus modernos incorporaron mecanismos de protección contra buffer overflows, los cuales suelen funcionar bastante bien. He navegado en busca de explicaciones sobre los mecanismos utilizados para realizar tal tarea, pero no tuve éxito. Siempre que se busca información sobre un producto comercial propietario, uno suele encontrar solo información comercial (alias, yo lo hago mejor que todos mis competidores).
Igualmente ninguno inventa nada nuevo, así que deben utilizar alguna de las técnicas de tiempo de ejecución que cito en este artículo. Si bien no confiaría ciegamente en ésta protección, no cuesta nada tenerla activada (bueno, tal vez algunos recursos =P), he hecho algunas pruebas con un McAfee 8.5i y la verdad que funciona bastante bien, detectó todos los overflows.

Conclusiones

A lo largo de los años se han propuesto muchas técnicas para prevenir/detectar/evitar buffer overflows, muchas de las cuales llegaron a implementarse y realizan un trabajo decente. Sin embargo, el problema de la compatibilidad, el "hacer que todo sea más fácil de usar" y la ignorancia de los administradores lleva a que los mecanismos de seguridad no se utilicen o vengan desactivados. Además la ignorancia de los programadores, en conjunto con las presiones de tiempos, llevan a que los programas sigan incorporando errores recontra conocidos y explicados, y es por ello que hoy día sigan existiendo tantos problemas de overflows explotables.
Es importante poner énfasis en los controles de programación, porque todo surge de allí. Es interesante ver cómo OpenBSD ganó su fama del sistema más seguro gracias a los chequeos de códigos y los mecanismos de prevención que presenta, muchos deberían copiar aunque sea parte del trabajo de OpenBSD.


Referencias

Prevention and Detection of Stack Buffer Overflow Attacks
Buffer Overflow Protection wiki
ASRL wiki
Buffer Overflow wiki
Type-Assisted Dynamic Buffer Overflow Detection
Secure Execution Via Program Shepherding
Architecture Support for Defending Against Buffer Overflow Attacks
StackGhost: Hardware Facilitated Stack Protection
Dynamic Buffer Overflow Detection
Network-Based Buffer Overflow Detection by Exploit Code Analysis
Curiosidades: man strcpy
Hace un tiempo, en una tierra lejana... ehh digo, hace un tiempo, mientras creaba un programa en C, se me ocurrió consultar a los útiles manuales de librería sobre la función strcpy y me encontré con algo gracioso.
Cómo hace poco expliqué el problema de los buffer overflows, y como todavía me falta postear la otra mitad del artículo, me pareció oportuno recordar esto =)
Si hacen "man strcpy", dependiendo la versión del manual que tengan, en la sección fallos, pueden encontrar el siguiente comentario:
Si la cadena destino de un strcpy() no es bastante grande (esto es, si el programador fue estúpido o perezoso, y no comprobó el tamaño antes de la copia) entonces puede ocurrir cualquier cosa. Provocar el desbordamiento de cadenas de caracteres de longitud fija es una técnica favorita de los piratas informáticos.
jejeje una forma bien directa de avisarnos lo que puede suceder si no comprobamos los límites de lo que copiamos usando esta función.
Lo más leido en Julio
Por si alguno no lee siempre el blog, o si comenzó a seguirlo hace poco tiempo, les dejo los post más leídos durante julio, para que no se pierdan lo que la gente encuentra más interesante (alias hago un refrito de posts).
Los datos los obtuve del google analytics, es increíble toda la información que se puede obtener a través de este servicio... la verdad que da un poco de miedo.

1. Uso de memoria: Firefox Vs Chrome Vs Safari Vs Opera. Lejos el post más leído durante julio, a pesar de que lo publiqué en junio. Parece que chrome viene haciendo un buen trabajo reclutando gente y muchos buscan comparaciones entre este y Firefox.

2. Hacking Bluetooth: ni tan fácil, ni tan imposible. A pesar de que lo publiqué a mitad de mes, se posicionó en segundo lugar entre los más leídos. Sea porque te preocupa tu seguridad al usar bluetooth, porque andas explorando nuevas formas de hacking, o porque te resulta interesante el tema, este post te va a gustar (espero).

3. Sistema de passwords incrackeables. Esta idea mia no innovadora (desgraciadamente =( ) parece que capto bastante atención, lo cual me alegró mucho. Si andás buscando nuevas formas de proteger tus sistemas, te conviene darle una mirada.

4. Utilidad para hackear passwords de Windows y Linux. Quién no debió recuperar su password alguna vez, o quién no intentó acceder al sistema de otro?... es bastante claro por qué este post aparece entre los primeros =D

5. review: NineBall + FFSearcher. Dupla de malware que captó mucho la atención, no sólo porque infectó miles de ordenadores, sino porque utilizan un mecanismo interesante y atractivo. Siempre es bueno leer nuevas ideas.

Mención de honor: Grub: configurando el gestor de arranque. Sin dudas el más popular de todos los post. A pesar de que lo escribí en mayo, cuando apenas arrancaba el blog, hoy en día sigue apareciendo entre los más leídos, ocupando el 6to lugar, muy cerca del 5to.
news: rootkit en laptops, NULL permite SSL spoofing, torrents en PNG
Alfredo Ortega y Anival Sacco descubrieron una vulnerabilidad interesante en el software "Computrance LoJack for Laptops". Resulta que esta aplicación a nivel de BIOS está diseñada para llamar a casa (autoridad central) en caso que la laptop sea robada o perdida, pero el problema es que lo que el soft considera 'casa' puede cambiarse. Por ello, sería posible crear un malware capaz de infectar el BIOS con código persistente que soporte reinicios y reflashings.
Y cuál puede ser el daño? esta es la mejor parte... la autoridad central asignada (llamada casa) puede darle la instrucción al BIOS para que borre todo como medida de seguridad!!!, también permite rastrear la laptop.
El 60% de las laptops nuevas están integrando este servicio, incluyendo a todos los fabricantes más importantes (Dell, Toshiba, Asus, Lenovo, HP, etc). Así que estén atentos a las actualizaciones que puedan surgir, dado que el sistema es relativamente fácil de explotar...
Pueden leer la noticia completa en http://blogs.zdnet.com/security/?p=3828

----------------------

Pasando a la siguiente noticia, ayer leo un sobre un hack al que debemos estar MUY atentos, porque podría resultar en la pérdida de nuestro dinero.
En slashdot publicaron sobre cómo es posible engañar a los browsers haciéndoles creer que visitamos un sitio conocido con certificado válido y todo, cuando en realidad estamos visitando un sitio falso. Para que se den una idea de la gravedad, un usuario podría visitar una página de un atacante que personifica la página de un banco, paypal, ebay, etc, y el browser le dirá al usuario que el certificado está OK, mostrando que el certificado corresponde a paypal.com o ebay.com, etc. Para el que no recuerde cómo funcionan los certificados, puede leer la introducción de mi artículo Certificados Digitales.
El problema surge en cómo los browsers implementan las comunicaciones SSL, y el caracter NULL en las URLS.
Supongamos que un atacante que es el dueño del dominio chicomalo.com desea obtener un certificado para el dominio PayPal.com\0.chicomalo.com. Para esto consulta alguna CA conocida y hace el requerimiento. Dado que el atacante es dueño de chicomalo.com, entonces la CA firmará el certificado sin objetar. Hasta acá todo bien, todo legal, pero el problema surge en los browsers, dado que al leer el certificado con un caracter NULL en el medio de la URL, interpretarán que el certificado corresponde a PayPal.com!!!.
La vulnerabilidad se debe a que los browsers dejan de leer cuando encuentran un caracter NULL en el nombre, dado que se interpretan como terminador de string.
Algo peor es que el atacante puede requerir un certificado con un wildcar como *\0.chicomalo.com y ahora puede impersonar cualquier página que desee, con certificado y todo que demuestran la validez!
Simplemente es excelente este hack =D

----------------------

Para terminar la tripleta clásica de noticias, les traigo una de hace un par de semanas. Resulta que en TorrentFreak nos hablan sobre un nuevo servicio que permitiría evadir los constantes problemas legales que suelen enfrentar los sitios que hospedan archivos .torrent. La solución es tan simple como perfecta, esconder los torrents en imágenes!!! El uso de imágenes para esconder secretos no es para nada nuevo, y se conoce como esteganografía. Incluso no es nueva la idea de esconder torrents dentro de imágenes, ya existe hace tiempo el programa Stegtorrent. Lo nuevo es que, a diferencia de Stegtorrent, este nuevo servicio llamado Hid.im, es web, con lo que no necesitamos instalar nada para usarlo.
Básicamente la forma de uso es darle a hid.im un torrent y este nos devuelve una imagen que lo contiene. Para la vuelta, es decir obtener el torrent a partir de la imagen, debemos contar con una extensión de firefox o un bookmarklet.
Usando hid.im podemos hospedar archivos torrent en cualquier servicio gratuito de hosting de imágenes como imageshack.com, en redes sociales, en avatars de foros, cualquier lugar donde se pueda poner una imagen. La única limitación del servicio es que el torrent no debe exceder los 250KB.
Dejando de lado lo legal de compartir cierto contenido a través de torrents, sin dudas, esto es un nuevo aire para evitar las censuras de sitios y la pérdida consecuente de los torrents.