domingo, 10 de julio de 2011

Seguridad en sockets TCP

Seguridad en sockets TCP: "
En alguna ocasión, bien porque necesitamos desarrollar una solución cliente / servidor, o bien porque queremos implementar otro servicio conocido, tenemos que programar un servidor TCP. Hay una serie de buenas prácticas que nos pueden ayudar a conseguir una mayor estabilidad frente a ataques o saturación del servicio.


Si participasteis en el primer wargame de SbD que organizamos hace unos meses, recordareis la primera prueba de networking que se trataba de un servidor que emulaba ser la configuración de un router. Estas buenas prácticas de las que hablamos fueron implementadas y, puede que gracias a ello, el servidor estuvo activo constantemente durante todo el concurso.


Está programado en ruby, y vamos a tomarlo como ejemplo. Hay que tener en cuenta que, al ser ruby un lenguaje de alto nivel, es posible que no necesitemos solucionar problemas que pueden darse en lenguajes de otro tipo, o de bajo nivel. Dicho ésto, ¡empezamos!


La estructura del programa es algo parecido a esto:


login

if correcto

bucle

menu

leer_opción

realizar_acción

fin

fin


Como de casualidad el servidor está a la escucha y cuando recibe una nueva conexión crea un hilo nuevo para servir a ese cliente y volver a ponerse a la escucha.


server = TCPServer.new('', srvport)
loop do
socket = server.accept
if socket
newclient(socket)
end
end


En este caso la función newclient() toma el socket y crea el hilo.


Uno de los problemas que podemos encontrar en este punto es que si se reciben muchas conexiones de forma simultánea, se crearán más hilos de los que el lenguaje o el sistema puede soportar, por lo que el programa morirá.


Ésto depende mucho del lenguaje de programación y de la versión. Por ejemplo, en versiones antiguas de ruby sucedía, pero en las versiones más modernas parecen haberlo controlado de alguna forma.


Las soluciones que podemos tomar son variadas. Personalmente la que más me convence es poner un pequeño tiempo de espera entre que se acepta la conexión y se crea el hilo. Nuestro código quedaría de la siguiente forma:


server = TCPServer.new('', srvport)
loop do
socket = server.accept
sleep(0.05)
if socket
newclient(socket)
end
end


Aunque controlemos el número de conexiones al incio, puede que alguien con malas intenciones realice conexiones y luego las deje sin actividad. Ésto podría causar que se llegara al límite de conexiones que soporta el sistema, haciendo que quede saturado.


Para solventar este problema podemos usar timeouts por inactividad, de forma que si un usuario no muestra actividad durante X tiempo, se cierre el socket y el hilo muera. Para ello, hice una función alternativa para leer del socket.


def read_socket(s, thread, tout = 15, size = 500)
begin
Timeout::timeout(tout) do
info = s.recv(size)
return info
end
rescue Timeout::Error
s.close
thread.kill
return false
end
end


La función recibe el socket y el hilo como parámetros, también podemos pasar el tiempo de timeout y el tamaño de lectura del socket. Si se supera el timeout se cierra el socket y se mata el hilo.


En nuesto caso particular hay otra cosa más con la que hay que contar. ¿Y si se crean conexiones de bots que entran en el bucle y realizan acciones para que no se les expulse por timeout?


Teniendo en cuenta esa posibilidad, la solución pasa por limitar el número de interacciones en el menú. En este caso estaba limitada a 50.



Tomando estas precauciones podemos conseguir un servicio bastante estable y resistente a ataques o saturación. ¿Conoces o sigues más medidas? ¡Compártelas en los comentarios!
"

Vigilando tu casa con Rovio

Vigilando tu casa con Rovio: "
Tiempo llevaba dándole vueltas a la posibilidad de comprar otra Roomba, lo más barata posible, vieja, de segunda mano, o como fuera,.. únicamente para trastear, puesto que la otra tiene la importante misión de dejar la casa limpia diariamente.



La idea era ponerle una webcam y poderla guiar por casa en remoto y que me muestre cómo está todo. Comentando esto con mi amigo Alex me comentó que había ya un robot llamado Rovio con webcam integrada, que a lo mejor me interesaba más para añadir a la colección de bichos que conforman el Skynet de mi casa, en vez de repetir con otra Roomba.



Buscando diversas opciones en Amazon, Ebay, etc,… el precio no bajaba de los 160 euros, hasta que en segundamano dí con un chico de Madrid que tenía uno sin usar, por bastante menos dinero. Así que quedé con él y nos pegamos un domingo por la tarde probándolo en su casa. La unidad tenía bastante buena pinta así que dije: para mí!



La configuración del cacharro se hace bastante rápido vía wireless, permitiendo cifrados WEP, WPA y WPA2.



Los únicos puertos abiertos son:



[root@Carmen ~]# nmap -sT 192.168.1.13

Starting Nmap 4.20 ( http://insecure.org ) at 2011-06-17 08:20 CEST
Interesting ports on 192.168.1.13:
Not shown: 1695 closed ports
PORT STATE SERVICE
80/tcp open http
554/tcp open rtsp
MAC Address: 00:12:34:56:78:90 (CyberTAN Technology)
Para manejarlo se utiliza una interfaz web que proporciona mediante el servidor web embebido en el propio robot.









Trasteando con Tamper Data por ejemplo, se puede ver que el mecanismo de comunicación para dar órdenes al robot es muy sencillo.



Han implementado Basic Authentication en HTTP para poder acceder al panel, y son todo el rato llamadas a un CGI modificando dos parámetros: action y drive (opcionalmente está el parámetro 'speed' que por las pruebas que he hecho no da para mucho más).



Así pues hice un programilla 'supercomplicado' en perl que permite hacer que el bot se mueva para donde queramos según le pases por comando



[root@Carmen ~]# more rov.pl
#!/usr/bin/perl
use LWP::UserAgent;

$IP_Rovio="192.168.1.13";
$Auth="Elhashquetoque";

my $url="http://".$IP_Rovio."/rev.cgi";
my $browser = LWP::UserAgent->new;
my $response = $browser->post(
$url,
"Pragma" => "no-cache",
"Cache-control" => "no-cache",
"Authorization" => "Basic $Auth",
"Content" => [Cmd=>'nav', action=>'18', drive=>$ARGV[0]]
);
Para hacer que se mueva, el parámetro action tiene que ser = 18.



En el parámetro drive decimos la dirección hacia donde tiene que ir. Fuzzeando dicho parámetro vemos lo siguiente:



1 adelante

2 atrás

3 izquierda

4 derecha

5 rota a la derecha (muy poquito. 1 grado?)

6 rota a la izquierda (muy poquito. 1 grado?)

7, 8, 9 y 10 hace moverse el robot a izquierda y derecha empujando con dos de las ruedas en vez de con una sola. Es parecido a 1, 2, 3 y 4

17 Rota a la derecha unos 15 grados (Necesario después de un action=33 para cancelar un Go_Home)

18 Rota a la izquierda unos 15 grados



La webcam que trae incorporada dispone de tres posiciones: abajo, media o levantada. Para seleccionar la posición, con el parámetro action=18, pasamos los valores 11, 13 y 12 al parámetro drive para hacer que esté arriba, a media altura o abajo del todo, respectivamente.



Si queremos encender o apagar un 'led' que trae para poder ver algo mejor lo que la cámara envía, haremos la llamada con action=19 y un parámetro LIGHT con valores 0 ó 1.



Si simplemente queremos monitorizar el estado del robot, pasamos el valor 1 al parámetro action y nos devuelve algo como lo siguiente:



[root@Carmen ~]# perl rov.pl  
Cmd = nav
responses = 0|x=-385|y=413|theta=-0.347|room=0|ss=43
|beacon=22|beacon_x=5183|next_room=-1|next_room_ss=0
|state=0|ui_status=0|resistance=0|sm=15|pp=0|flags=0007
|brightness=6|resolution=0|video_compression=0|frame_rate=5
|privilege=0|user_check=1|speaker_volume=21|mic_volume=20
|wifi_ss=199|show_time=0|ddns_state=0|email_state=0
|battery=116|charging=0|head_position=203|ac_freq=1
Entre otras cosas, la batería que le queda, si se está cargando o no, datos de la potencia de señal wireless, el volumen del altavoz y del micrófono (se supone que puedes hablar con la gente a través del robot estando conectado al interfaz web desde donde sea), etc,…



Rovio permite además hacer un snapshot de lo que la cámara está viendo en ese preciso momento y enviarlo a una dirección de correo electrónico predefinida. Para eso el valor del parámetro action debe ser 26.



Para hacer que el robot vaya a su dock a cargarse, hay que enviar en action el valor 13.



El streaming de lo que va mostrando la webcam incorporada en el robot, se puede ver mediante http://IP_Del_rovio/GetData.cgi?width=640px&height=480px afinando la resolución deseada.



Ya hay aplicaciones para controlar Rovio desde iPhone y desde Android, aunque con todos estos datos que hemos comentado, deberíamos ser más que capaces de hacer cualquier otro tipo de interfaz de comunicación con el robot: como un programa en modo texto mediante teclas por ejemplo; o que cuando estemos de vacaciones haga un recorrido diario predefinido, que vaya haciendo snapshots y nos los vaya enviando por email,… O incluso se puede tener otro programa que coja todas esas imagenes y genere un video, que sea lo que recibamos finalmente en nuestro correo. De esa manera podríamos ir recorriendo el recinto y ver el estado en fotos de las habitaciones deseadas, que como podéis imaginar, es algo que el cacharro no es capaz de hacer por si solo.



La gracia de este tipo de robot es poder utilizarlo cuando no estás en casa y moverte con él. Sin embargo, al ser el interfaz de configuración y monitorización a través de HTTP y la autenticación básica, quizá no sea una buena idea el mapear un puerto del router directamente al servidor web del Rovio y dejar en manos de la bondad del mundo que un ataque de fuerza bruta/diccionario permita sacar la contraseña y el robot se mueva por casa a voluntad de otros.



En mi caso, que desde mi Mac puedo realizar una conexión VPN hasta mi casa, no hay problema, porque no tengo que exponer ningún servicio nuevo hacia fuera. Sin embargo, desde el iphone me gustaría acceder de forma directa.



Para ello he establecido alguna medida de seguridad extra para asegurar que desde fuera soy yo y solo yo quien accede.



Dispongo de un PC entre las redes confiables de casa y el router que me conecta a Internet. En él, tengo un Apache al que he realizado las siguientes modificaciones en el fichero httpd.conf:



<virtualhost ip_externa:puerto>
ServerName lorenzomartinez.es
ProxyRequests On
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
SSLCertificateFile /unaruta/serverpem.pem
SSLCertificateKeyFile /otraruta/serverkey.key
SSLCACertificatePath /otrasrutamas/_ssl_.crt
SSLCACertificateFile /laultimadelasrutas/ca.crt
SSLVerifyClient require
SSLVerifyDepth 10
SSLOptions +OptRenegotiate
ProxyPass / http://192.168.1.13/
ProxyPassReverse / http://192.168.1.13/
CustomLog logs/rovio_log combined
</virtualhost>


Lo que hemos hecho es crear un Virtualhost que requiere un certificado SSL X.509 de cliente, firmado por una CA interna que, si todo es correcto, y gracias a mod_proxy, Apache hará las peticiones al servidor del robot Rovio. La comunicación hasta mi casa va cifrada y autenticada con el certificado SSL y entre mi máquina y Rovio, va por HTTP con cifrado WPA2 establecido por la propia red wireless.

Ya comentamos hace tiempo en SbD qué herramienta se puede utilizar para introducir el certificado digital en el iPhone. Otra opción sería dejar el certificado accesible en un servidor web privado y añadirlo al keystore del iPhone.



Conclusiones:

  • La idea de tener un robot en casa que puedas manejar desde donde estés, suena muy friki y permite pensar en cuánto juego te va a dar.

  • El precio del robot es bastante elevado, a no ser que encuentres uno de segunda mano (aunque en perfecto estado) a muy buen precio como el que compré yo, ni se me pasaría por la cabeza comprarlo

  • Como webcam wireless que es, podría integrarlo y dejarlo activo como una webcam más controlada por Motion, y si detecta un movimiento, que avise. El problema es que cuando diéramos una vuelta con el robot, manualmente, daría un montón de falsos positivos

  • Se supone que las baterías las cargas durante 4 horas y media, el robot dura una hora y media moviéndose. En mi caso, el robot no termina nunca de cargar las baterías, permaneciendo un montón de luces encendidas del mismo (de noche parece una nave espacial como podéis ver en la foto de arriba). Por supuesto la batería dura menos de lo deseado y de lo especificado.

  • Leyendo (a posteriori… damned!) las experiencias de otros compradores de Rovio en Amazon, dan ganas de no comprarse un bicho de estos: Efectivamente la batería dura 15 minutos, el soporte de WowWee es lamentable, tardan semanas en contestar y finalmente te dicen que no es su problema, la calidad de la webcam es bastante mala cuando aun a ojos humanos hay suficiente luz.

  • Existe un accesorio que permite añadirle más luz al robot (incluso le da un aire a Johnny Número 5), y así poder monitorizar el recinto de noche. Sin embargo, el artículo está descontinuado y no hay manera de comprarlo, al igual que cualquier otro Rovio, lo cual tampoco aporta mucha fe en este tipo de producto. En Hackaday publicaron un DIY para añadirle más leds que permitan ver algo cuando las condiciones de luz empiezan a flaquear.

  • La calidad del producto no es ni de lejos la de la Roomba. Rovio cuando está en modo: 'vete al dock', se nota que cuando choca con un obstáculo, tarda en detectar que eso ha pasado y que tiene que intentar moverse hacia otro lugar. Roomba en cambio, detecta cuándo va a chocar, ralentiza su movimiento para impactar despacito y gira sobre sí misma para buscar otra forma de llegar a la base. Además para poder ir al dock de forma directa, Rovio necesita tener diferentes captadores que le guíen en diversas habitaciones, en cambio Roomba va buscando con calma donde está la base cuando pueda.

  • Como ventaja ante Roomba es que Rovio trae un interfaz wireless ya incorporado, y no hay que hacer malabarismos para lograr algo vía bluetooth como en el caso del 'robot redondo'

  • En definitiva, Rovio es un producto con más ambición invertida en el márketing que en la calidad del producto en sí (parece demasiado de juguete), la parte del audio sólo funciona con Internet Explorer, no tiene un modo standby,…

  • Una pena que en mi búsqueda de un novio para mi Roomba, me haya equivocado con un robot mediocre que sólo puede funcionar de día, poco rato, y con todas las luces puestas.

  • Afortunadamente, el chico que me vendió el Robot me ofreció la oportunidad de devolvérselo si el equipo no cumplía con mis espectativas. Después de hablar con él, y a la vista de los problemas del robot, y de manifestarle que efectivamente, no me va a valer para mucho en estas condiciones, no sólo me ha dicho que me devuelve el dinero, sino que si el producto no da buen resultado, y dado que para él también fue un regalo y que ve que a mí me encantan estas cosas y que 'lo vivo', me quede además con el robot. Es increíble y loable que queden personas así de honradas en este mundo! La verdad es que pasamos una tarde de domingo bastante divertida inicializando el cacharro (casi me tengo que quedar a ver la Fórmula 1 en su casa!). Me contó que tenía un grupo de música llamado 'Ojos de Gamba' e incluso me regaló un disco! Muchísimas gracias Israel!

"

sábado, 9 de julio de 2011

Los 25 errores más peligrosos del software según CWE/SANS 2011

Los 25 errores más peligrosos del software según CWE/SANS 2011: "



Selection_001.png


Como el título indica, esta es la lista que este año han creado CWE/SANS sobre los errores más peligrosos que cometemos los programadores en este año 2011.



































































































































































PosPuntIDDescripción
[1]93.8CWE-89No filtrar propiamente las sentencias SQL (Inyección SQL)
[2]83.3CWE-78No filtrar las llamadas al sistema de forma adecuada (Inyección en comandos del SO)
[3]79.0CWE-120No chequear el tamaño de la memoria reservada a la hora de copiar datos (desbordamiento de memoria)
[4]77.7CWE-79No detectar la inyección de scripting (XSS)
[5]76.9CWE-306No autentificar en llamada a funciones críticas
[6]76.8CWE-862No autorización
[7]75.0CWE-798Usar credenciales estáticos en el código
[8]75.0CWE-311No cifrado de datos sensibles
[9]74.0CWE-434No restringir la subida de ficheros a ciertos formatos
[10]73.8CWE-807Confiar en una fuente de datos no confiable a la hora de tomar una decisión de seguridad
[11]73.1CWE-250Ejecución con privilegios innecesarios
[12]70.1CWE-352Cross-Site Request Forgery (CSRF)
[13]69.3CWE-22No limitar el acceso al sistema de ficheros a directorios restringidos
[14]68.5CWE-494Descarga de código sin chequear la integridad del mismo
[15]67.8CWE-863Autorización incorrecta
[16]66.0CWE-829Permitir la integración de funcionalidades de fuentes no confiables
[17]65.5CWE-732Asignación de permisos incorrecta a recursos críticos
[18]64.6CWE-676Uso de funciones potencialmente peligrosas
[19]64.1CWE-327User un algoritmo de cifrado que ha sido comprometido o roto
[20]62.4CWE-131Cálculo incorrecto del tamaño de memoria
[21]61.5CWE-307No restricción a un número de intentos fallidos de acceso
[22]61.1CWE-601Redirección URL a sitios no confiables (‘Open Redirect’)
[23]61.0CWE-134Formato de cadena no controlado
[24]60.3CWE-190Desbordamiento de enterios
[25]59.9CWE-759Aplicar una función hash sin usar la sal

Aquí tienes toda la información en PDF


Fuente

Entradas relacionadas:


"