Copy Link
Add to Bookmark
Report

4x08: Estandar de Programacion Segura

eZine's profile picture
Published in 
0ri0n Team Venezuela
 · 1 month ago

-[ 4x08.txt ]---------------------------------------------------------------- 
-[ Estandar de Programacion Segura ]-----------------------------[ Bit-Man ]-
---------------------------------------------------[ victor@bit-man.com.ar ]-


Cuando se expone una interfaz (de programacion, usuario, etc.) subuso
puede ser subvertido (uso abusivo). Es este abuso el que debe ser evitado
(segun en que lado uno se encuentre parado). Ya que planeamos realizar un
standard de esta metodologia desde el lado de la programacion, y
seguramente Ud. es un programador, arquitecto de sistemas, team leader u
otra cosa por el estilo querra mantener la interfaz limpia, usable y sin
componentes que puedan ser abusadas.

A medida que las aplicaciones de Internet comienzan a ser mas y mas
complejas, y la generacion de codigo comienza a ser cada vez mas
automatizada a traves del uso de wizards, ambientes de programacion,
frameworks y otras herramientas por el estilo comenzamos a estar en franca
desventaja. La tecnicas para programacion segura es algo que ha sido
abordado desde muchas formas y por muchos lenguajes. Lo que se trata de
hacer es una unica metodologia independiente de lenguajes de programacion,
ambientes de programacion y herramientas de desarrollo.

La idea de convertirlo en un standard abierto nos da el inmediato beneficio
que puede ser usado por cualquiera, pero esto tambien incluye a los chicos
malos. Sin embargo, si se sigue una metodologia seguramente los errores mas
comunes ya no aparecen. La contrapartida es que cuanto mas programadores
lean y entiendan este manual, mayor es la posibilidad de desarrollar
aplicaiones en forma segura y ayudar a mejorar esta tecnologia.


[ Agradecimientos ]

Quisiera agradecer a David A. Wheeler por escribir "Secure Programming for
Linux and Unix HOWTO"
[1] que tanto me inspiro para hacer este trabajo.
Tambien una agrdecimiento a quienes escribieron "SECPROG@SecurityFocus.com
working document"
[9], algo asi como el "Primer Diccionario" sobre
"Programacion Segura".

Debo tambien dar un agradecimiento muy especial a Pete Herzog, por toda la
ayuda brindada en muchos de los aspectos de este trabajo.

Todos aquellos que contribuyeron a este manual en alguna forma son
mencionados al principio de este documento. Cada quien recibe un
reconocimiento por el tipo de contribucion, y no por lo que ha contribuido.

El uso de este ocultamiento es para prevenir la polarizacion al momento de
la interpretacion. Solo en la traduccion del documento se saben las
personas que realizaron la contribucion, ya que el traductor se convierte
en el contacto del documento traducido que incluye, no solo el mantener
actualizado el documento, sino tambien las FAQs, agregados y comentarios
hechos en el original, en Ingles, y traducido al lenguaje deseado.


[ Terminos ]

* DoS (Denial of Service): Ataque cuyo porposito es no permitir el uso del
sistema. No afecta los datos almacenados en el
sistema.

* out-of-the-box: instalacion standard, utilizando los parametros por
defecto.

* super-user: es un usuario especial (conocido como root o administrador)
que no tiene restricciones de acceso dentro del sistema.


[ Audiencia ]

Este manual fue escrito para profesionales de la programacion que quieren
establecer lineamientos y/o procedimientos para la programacion segura en
cualquier proyecto de Tecnologia de la Informacion (IT), independiente del
lenguaje de programacion, ambiente de ejecucion y herramientas de
desarrollo.

Este manual no examina la forma correcta de usar una herramienta de
desarrollo en particular o como programar en un lenguaje dado.

Los desarrolladores encontraran muy util este manualen realizar mejores
programas, mas resistentes a ambientes hostiles tales como Internet.


[ Alcance ]

El objetivo es realizar un standard de metodologia de programacion segura
que pueda ser usado en cualquier proceso, manual o automatico, y permita
alcanzar los requerimientos de seguridad para maximizar el uso y evitar
su abuso. El resultado indirecto es la creacion de una disciplina que
pueda actuar como un punto central en todas las pruebas de seguridad
independientemente del lenguaje de programacion, ambiente de ejecucion y
herramientas de desarrollo.


[ Excepciones ]

Los casos no cubiertos, aun, en este trabajo son :

* Programas cuyo proposito es el manejo de la seguridad.
* Programas que deben correr como super-user.


[ Preparacion para trabajar en un ambiente hostil ]

Esto no es tarea facil, y fue hecho en diferentes maneras, cada una
cubriendo su punto de vista, comenzando en diferentes formas, etc. Aqui
establecere las mias propias.

Si le damos una mirada a Secure Programming for Linux and Unix HOWTO [1]
(seccion 2.2, Security principles) la programacion segura puede ser
interpretada como el cumplimiento de los siguientes objetivos:
confidencialidad, integridad y disponibilidad. Esto es correcto y puede
ser moldeado para cualquier ambiente en particular, pero es una muy buena
respuesta generica. El problema comienza en como alcanzar esto objetivos.
Lo que se tratara de enfatizar no es el arreglo de los mismos, sino en una
metodologia open source que provea la base para el desarrollo de metodos
y/o procedimientos.

El trabajo de un sistema es implementar requerimientos funcionales que,
debidamente acordados, puedan ser probados. En una aproximacion mas
detallada, la codificacion se hace para cumplir con este objetivo pero en
una escala atomica (a nivel de subrutina o procedimiento de programacion).

Lo que no es parte de los requerimientos funcionales es la disponibilidad
del sistema, la que establece las condiciones de uso tales como en que
dias sera usado (laborables, feriados, etc.), ventana diario de uso (9:00
a 17:00 hs, etc.), maximo tiempo permitido sin acceso al sistema (2 horas
mensuales, etc.) y toda una serie de requerimientos que definen el
denominado Acuerdo de Nivel de Servicio (SLA o Service Level Agreement).

Es en este punto donde, ejecutando en ambientes hostiles como Internet,
poder brindar los niveles requeridos del SLA (integridad), imposibilitar
el robo de informacion (seguridad) o proveer la informacion a la persona
correcta (confidencialidad ) es de particular interes.

Una vez que conocemos sobre este y su impacto negativo, hay una gran
preocupacion en coomo adoptar una aproximacion sistematica para resolverlo.

Para comenzar, veamos los factores que dan comienzo a esta problematica :

* Que no hacer: es muy dificil construir sobre lo que no debe hacerse.
Protegerse de algo que no se sabe su forma exacta es una
tarea muy dura (un muy buen articulo sobre este tema puede
verse en el newsletter Crypto-gram de Noviembre de 1999
[2]). Es similar a la defensa contra los microbios, uno no
puede protegerse a menos que se sepa de su existencia y de
como derrocarlos.

* Complejidad: esto da origen a uno de los mas viejos y dificiles
problemas de la humanidad. Se llama comunicacion, y segun
se agrega complejidad a un sistema este puede manejarse
mejor si se divide en tareas mas pequeñas, se asignan a
distintos equipos que deben comunicarse entre si para
alcanzar el objetivo: cuanto mas equipos hay mayor cantidad
de comunicaciones deben establecerse y, como es sabido,
convierte a la construccion del sistema en un problema de
crecimiento exponencial (lo mejor es dar una mirada al
titulo software essential difficulties de "No silver
bullet"
[3]). Esto favorece la existencia de errores
ocultos que son cubiertos por el sindrome de "hay muchos
lugares donde mirar"
.


[ Metodologia ]

Como este trabajo es parte de "The Open-Source Security Testing Methodology
Manual"
(OSSTMM), la misma metodologia sera usada, estableciendo los
Parametros y Tareas orientadas a la Programacion Segura, pero con una
aproximacion un tanto diferente. En OSSTMM se descubre que hay un error, y
ahora queremos saber donde se haya ubicado, como arreglarlo y evitar su
aparicion en futuras codificaciones.

Esta seccion trata de los dos primeros objetivos (descubrimiento y
reparacion) mientras que el trabajo de como evitar estos problemas es un
tema a ser tratado en un trabajo a ser desarrollado (no incluido en este).


[ Datos entrantes ]

Debe notarse que las interfaces se basan en la implementacion de alguna
tecnologia y que la explotacion de los problemas de seguridad deben ser
arreglados para obtener una completa solucion al problema. No es
suficiente con arreglar la implementacion de la interfaz o el programa
bajo prueba.

Algo a tener en cuenta es que los dato de entrada no son solo los
adquiridos a traves del usuario o de otros aplicaciones, sino tambien los
obtenidos desde el sistema (fecha, variables de ambiente, etc.) y otro
software que forman la base para el sistema. Resumiendo, cada porcion de
datos que alimenta a nuestro programa o sistema debe ser analizado.


[ Validacion de patrones de datos de entrada ]

Deben probarse los datos de entrada contra patrones de aceptacion y
rechazo. Esto puede dividirse entre diferentes pantallas, scritps, URLs,
etc. para manejarlo segun los recursos (tiempo, costos) y la gente
disponible. Se recomienda probar todas las interfaces disponibles (GUI,
API, etc.) y no solamente los que son expuestos al usuario.

En este punto quien realiza las pruebas debe hacer foco en como elaborar
los grupos de datos que no solamente no coincidan con los patrones
establecidos, sino que trate de explotar algun elemento proveniente de la
arquitectura en la que el sistema se ha basado (sistema operativo,
lenguaje de programacion, base de datos, etc.)

Resultados esperados:

* Una lista patrones de datos aceptados y rechazados

Tareas a realizar: Acetacion/rechazo de datos

* Verificar los datos aceptados que deben ser aceptados.
* Verificar los datos rechazados que deben ser aceptados (falso negativo).
* Verificar los datos aceptados que deben ser rechazados (falso positivo).
* Verificar los datos rechazados que deben ser rechazados.

Trabajo sobre el codigo:

* Identificar los segmentos de codigo que manejan cada dato entrante y su
validacion.
* Arreglar el codigo.

En lo referente al arreglo de codigo, y solo para esta prueba, la clave es
no solo arreglar codigo para rechazar los datos nocivos, sino extrapolarlos
en patrones genericos. En este punto el metodo usado para filtrar y
rechazarlos debe ser discutido. El metodo elegido depende de las
limitaciones del ambiente escogido, como se explica en "Ingreso de Datos"
en el Apendice C, pero aun hay algo sobre el filtrado que debe mencionarse:
el metodo de aceptacion y rechazo.

Hay dos metodos basicos :

* Patron de aceptacion: los datos ingresados se prueban contra patrones de
aceptacion, haciendolos mas selectivos segun se descubren nuevas
vulnerabilidades. Si ninguno de los patrones es satisfecho los datos son
rechazados.

* Patron de rechazo: los datos ingresados se prueban contra patrones de
rechazo, agregando patrones a medida que se descubren nuevas
vulnerabilidades. Si ninguno de los patrones es satisfecho los datos son
aceptados. Si se presta atencion cad metodo tiene sus pros y contras. El
segundo es mas facil para agregar nuevos patrones, pero requiere pruebas
adicionales para cada patron de rechazo. El primero es mas limpio y
generico. Por esto el metodo del Patron de aceptacion es el preferido,
basicamente porque se trabaja en reducir los patrones de aceptacion,
siendo asi un esquema mas proactivo mas facil de mantener y menos
propensa a errores.

Un ejemplo tipico de los bugs encontrados con esta prueba pueden
encontrarse en el "Apendice A" baj el titulo "Compromiso Remote".


[ Validacion de los limites de los datos de entrada ]

Una vez que los datos de entrada se prueban contra los patrones
correspondientes, puede ser que los que se obtenga no sea tan bueno. Por
ejemplo si un identificador de una cuenta bancaria es numerica, no todas
las combinaciones ni todas las longitudes de cuenta son son validas. Notar
que estos limites no estan relacionados con el significado en el mundo
real, sino con las implicancias de seguridad en cuanto a la longitud de
las variables. Dicho de otra forma, es cuando la implementacion de la
tecnologia (lenguajes, sistemas operativos, etc.) se lleva a limites de
stress que hacen desviarlos de su comportamiento normal (un forma comun
de probarlos es llamar a funciones con parametros que esten en el orden de
los kilobytes y que se supone no deben ser mas de unos cuantos bytes).

Resultados esperados:

* Comportamiento del sistema a entradas validadas pero no esperadas .

Tareas a realizar: Monitoreo de sistema

* Uso CPU (porcentaje, tiempo, picos de uso, etc.).
* Uso deMemoria (real, virtual, cache, etc.).
* Uso I/O (espacio en disco, acceso en rafagas, etc.).
* Uso de red (rechazo de paquetes, generacion, etc.).

Trabajo sobre el codigo:

* Identificar los segmentos de codigo que manejan cada dato entrante y su
validacion.
* Arreglar el codigo.

En este punto, el analisis y codificacion es una especie de arte, porque
hay mas importancia en el comportamiento del sistema que en los valores
devueltos. Esto requiere un amplio conocimietno de la tecnologia que se
utiliza, principalmente de las manejos internos del lenguaje tales como
manejo de memoria, generacion de procesos y threads, bloqueos, IPC, etc.

Un ejemplo de los bugs descubiertos con este tipo de pruebas puede ser
visto en el "Apendice A" bajo el titulo "Bug de Format String". su efecto
puede ser minimizado si las pruebas correspondientes sobre el tamaño y
formato son realizadas.


[ Procesos ]

Una vez que nos protegemos del mundo exterior, debemos hacerlo de nuestro
propia forma de codificacion y practicas internas.

Un analisis de como proteger el proceso es basicamente la proteccion de
todos los recursos usados por el sistema: memoria, disco, red, etc. para
evitar su abuso por el mismo o por terceros.


[ Consumo de recursos ]

Cada programa hace uso de recursos (tiempo de CPu para calculos, memoria
para almacenamiento interno y externo, archivos para almacenamiento, etc.)
para sus propositos. Bajo ciertas condiciones es posible hacer que el
programa comience un ciclo de consumo que termine en una caida del sistema
(system thrashing) o una finalizacion abrupta (program dumping). Estos son
los llamados negaciones de servisio (DoS - Denial of Service).

Es practica normal el realizar las pruebas solo con los datos provenientes
de patrones aceptados, pero es una buena practica hacerlo tambien con los
provenientes de patrones rechazados y variaciones de estos (conocido como
prueba sucia o dirty test).

Resultados esperados:

* Consumo de recursos y uso para cada patron de entrada y estado (referido
a la maquina de estados implementada).

Tareas a realizar: Monitoreo del sistema: por cada clase de recurso (CPU,
memoria, etc.)

* Conveniente adquisicion de recursos.
* Conveniente uso de recursos.
* Conveniente liberacion de recursos.
* Analisis/monitoreo de abrazos mortales (deadlocks).

Trabajo sobre el codigo:

* Identificar los segmentos de codigo que manejan cada dato entrante y su
validacion.
* Arreglar el codigo.

Para evitar estas condiciones de DoS es buena practica limitar la cantidad
de recursos usados, y rechazar peticiones cuando se alcanza un imbral de
consumo de recursos es alcanzado.

Un ejemplo de bugs descubiertos con este tipo de pruebas puede ser visto
en el "Apendice A" bajo el titulo "Retencion de Recursos".


[ Predicion del uso de recursos ]

A veces el ser muy predictivo en el uso de recursos (lo que significa
tener un patron de uso) no es bueno, basicamente porque ayuda a predecir
el siguiente movimiento a ser hecho por el sistema. Esto puede ser usado
por un atacante para personificar al sistema (ofreciendo la misma
respuesta que el sistema original, conociendo el siguiente nombre de
archivo a ser usado y redireccionarlo para sobreescribir un archivo
sensible, predecir identificadores de sesion, etc.)

Resultados esperados:

* Patron del uso de recursos.

Tareas a realizar: Monitoreo del sistema: por cada clase de recurso (CPU,
memoria, etc.)

* Analisis de uso de recursos: Buscar patrones en el uso de recursos.

Trabajo sobre el codigo:

* Identificar los segmentos de codigo que manejan cada dato entrante y su
validacion.
* Arreglar el codigo.


[ Prevencion de ataques ]

Cuando se procesan los datos obtenidos tendemos a creer que los datos
disponibles son seguros, pero ... pasaron los datos por los controles de
seguridad si el programa no es ejecutado bajo el ambiente especifico para
el que fue programado? Que ocurre si un atacante encontro la forma de
ejecutar el modulo de procesamiento pasando por alto estos controles?.

Algunos programas hacen pruebas adicionales tales como de funcionamiento
en el ambiente indicado y modificacion del codigo.

Resultados esperados:

Respuesta detallada del sistema bajo condiciones anomales de
funcionamiento.

Tareas a realizar: Ejecucion del sistema:

* Usar puntos de entrada al sistema distintos de los especificados.
* Inyeccion y modificacion del codigo.
* Modificando las condiciones de funcinamiento.

Trabajo sobre el codigo:

* Identificar los segmentos de codigo que manejan cada dato entrante y su
validacion.
* Arreglar el codigo.

La primera forma de reparacion que se nos viene a la mente es la de
incluir un codigo similar al de validacion de datos de entrada, pero esta
tarea esta reservada a los modulos de verificacion de datos, por lo que
esta tarea no debe ser duplicada. La tarea a ser llevada a cabo es
distinta: deteccion de condiciones de ejecucion anormales y no la de
deteccion de datos impropios.


[ Salida ]

Todos los datos de entrada estan filtrados, se tomaron precauciones sobre
el uso de recursos pero ... no es suficiente. Que tal el decirle a sus
competidores la clave del exito ?? A veces no es tan drastico, pero el
darle algunas pistas es solo una cuestion d tiempo para obtener la
informacion completa.

Algo debe tenerse en cuenta, y es que algunos errores pueden ser vistos
como errores de proceso porque producen informacion sutil, producto de una
salida no esperada (espurea). Lo que se trata de mostrar es el pasaje de
informacion en los cabales normales de salida, tales como tags de HTML
ocultos, errores que pueden dar informacion sobre la estructura interna,
y problemas por el estilo.


[ Niveles de autorizacion de los datos ]

Este concepto es muy claro en el uso militar. En forma resumida, se tienen
categorias (ultra secreto, secreto, publico, etc.) que marcan cada objeto
(informacion, gente, etc.) y una persona puede acceder cualquier recurso
marcado con el mismo o menor nivel que el suyo propio (por ejemplo, una
persona con nivel "secreto" puede acceder recursos marcados como "secreto"
y "publico" pero no los marcados "ultra secretos"). Ademas de esto, un
recurso tiene el mismo nivel que cualquiera de los objetos que contiene
(por ejemplo, un documento que contiene datos marcados como "publico" y
"secreto" es clasificado como "secreto"; si se agrega una parte "ultra
secreta"
se convierte en un documento "ultra secreto"). Lo mismo se aplica
a los canales de comunicacion, no se puede transmitir un documento "ultra
secreto"
a traves de un canal "secreto" (el canal tiene menos mecanismos
de proteccion que los que el documento puede aceptar).

Este mismo concepto deberia ser aplicado aqui.

Expected results:

Clearance levels for each output object (data, persons, channels, etc.)

Tareas a realizar:

* Identificaion de los segmentos de codigo que realizan la salida de datos.
* Claisificacion del sujeto al que esta destinada la salida.
* Clasificacion de los datos de salida,
* Clasificacion de los datos a enviar por la salida.

Trabajo sobre el codigo:

* Marcado de los datos con niveles de autorizacion.
* Arreglar el codigo.

A veces se necesita brindar una buena cantidad de informacion, y no
siempres una buena practica, y la misma contiene los errores que nos da el
sistema operativo tales como nombre de archivos, que pueden dar alguna
pista a personas cuya intencion es no brindarla.

Un claro ejemplo de esto son los web servers. Un server MS IIS (Internet
Information Server) instalado out-of-the-box muestra un mensaje de error
indicando que la pagina no existe y mostrando la supuesta ruta de acceso
(file path) al archivo (en caso que este no exista) o la salida de un
script en caso de error (que puede contener estructuras internas de datos
o informacion de debugging cuya divulgacion no es deseable). Su
contrapartida (Apache) muestra un mensaje indicando que ha ocurrido un
error, el administrador sera notificado y la informacion mas jugosa es
almacenada en el archivo error_log.


[ Apendice A - Errores mas frecuentes ]

En esta seccion las fallas seran mostradas, a veces en detalle y otras
solo una idea de las mismas, mayormente en el caso donde hay estudios o
papers que las discuten.

No se pretende que esta sea una lista exhaustiva de fallas, sino las mas
frecuentes y representativas, para poder brindar una guia en cuanto a
informacion, herramientas y resultados que pueden encontrarse.


[ Stack Smashing ]

En esta version en español se ha decidido mantener el nombre en ingles
debido a que su traduccion no es muy utilizada y hay mas de una acepcion
del mismo. Tambien se la conoce como "buffer overflow".

Sera descripta muy brevemente, porque hay muy buenos articulos que las
describen (ver [5] y [6]). Cuando se definen dos variables en un lenguaje
de alto nivel y estan adyacentes en el codigo fuentes, hay una muy alta
probabilidad que usen areas de memoria adyacentes. Por esto si se escribe
una de estas y se sobrepasan sus limites, entonces se esta escribiendo en
el area de memoria perteneceiente a la otra. Si la primera tiene 30 bytes,
cuando se accede al byte 31 es en realida el primer byte de la segunda
variable.

No parece ser de mucho uso, pero hagamos una pequeña investigacion. Cuando
se usa un lenguaje de alto nivel mayormente usa subrutinas (tambien
llamadas funciones, procedimientos, etc.) que usan sus propias variables
locales. Es practica comun que los compiladores usan una porcion de
memoria, llamada stack, donde es almacenada la direccion de la proxima
instruccion a ser ejecutada, llamada direccion de retorno, cuando la
subrutina termina, y tambien se almacenan alli las variables locales. Lo
que podemos hacer es utilizar esta localidad porque si accedemos las
variables locales podemos ir mas alla de sus limites y acceder la
direccion de retorno. No se puede hacer magia para adivinar esta
direccion, pero si podemos inyectar una nueva pieza de codigo y apuntar
la direccon de retorno a este podemos hacer que al terminar ejecute
nuestro codigo en lugar del original.

Esto puede evitarse usando algunos trucos tales como insertar algunas
pruebas de integridad para la direccion de retorno. Esto tambien puede ser
evitado, pero hay menos probabilidades de ocurrencia de ataques. Un muy
buen articulo sobre esto puede ser leido en [7].


[ Format String Bug ]

Hay funciones y funciones ... algunas mas flexibles que otras, pero ... la
flexibilidad tiene sus costos y limitaciones, y una de ellas es la
seguridad. hay un conjunto de funciones en C (la familia de los printf)
que uno de los parametros es un string conteniendo el formato, y orden, en
que los parametros seran pasados a la funcion. Por ejemplo, la siguiente
llamada a la funcion:

printf( "Hola, %s. Nos ha visitado %u veces", nombre, contador );

nos dice que los parametros son tres (el string y las variables nombre y
contador), y la informacion relativa a la cantidad y tipo de parametros
puede leerse del primer parametro (tambien llamado "format string"): un
string (%s) y un entero sin signo (%u).

Ahora que este "format string" se encuentra como constante en la
aplicacion, que hay acerca de darle elcontrol de este string al mundo
exterior ?? Tomemos la siguiente porcion de codigo :

scanf( "%s", *format_string );
printf( format_string, name, counter );

donde format_string es provista por un usuario no verificado y/o no
confiable (a traves de la funcion scanf). Esto le podria permitir ver
alguna informacion interna, muy util para obtener datos y explotarlos
posteriormente (tales como un "stack smashing" o "buffer overflow") a
traves de la manipulacion del string, tales como el cambio de %s o %u por
una forma mas conveniente de ver la informacion de memoria (por ejemplo,
usando un contador hexadecimal y declararlo en el format_string que es un
puntero a un string o un char). Para una completa descripcion, y ejemplos
"in the wild", ver la referencia [10].


[ Compromiso remoto ]

Este ataque combina dos errores muy usuales: ausencia de filtrado (o
filtrado defectuoso) y ejecucion de un programa con privilegios excesivos.

A continuacion se muestra un breve resumen extraido del aviso de seguridad
indicado en [11]:

"El motor de base de datos MS Jet (que permite acceder a bases Access)
permite la inclusion el embeber expresiones de VBA en sus comandos, lo que
permite ejecutar comandos de Windows NT. Esto, combinado con un error en
IIS ejecutando comandos de ODBC como el usuario system_local permite a un
atacante remoto poseer un control total del sistema. Otros web servers
pueden ser afectados. Muchos motores de MS Jet son afectados, pero pueden
no conducir a la elevacion de privilegios"


Basicamente se puede embeber comandos VBA (Visual Basic for Applications)
dentro de una sentencia de SQL y dejar que ODBC los ejecute (filtrado
inadecuado), tales como comandos del sistema a traves de un interprete de
comandos (shell). Esto puede minimizarse si es ejecutado con un usuario
que tiene privilegios minimos para ejecutar esta tarea en una forma
eficiente. Este no era el caso.

No se haran mas explicaicones. El aviso de seguridad mencionado es una
obra maestra que merece ser leida en detalle.


[ Retencion de recursos ]

Cuando se inicia una conexion de TCP la maquina de estados establece que
deben seguirse tres pasos:

* Requerir la conexion al extremo remoto.
* El extremo remoto responde con una aceptacion (acknowledge), o la conexion
se rechaza.
* El extremo local responde con un acknowledge.

Debido a la simplicidad de su mecanismo no posee un control para evitar la contencion de recursos. Supongamos que cuando su computadora requiere una conexion a la computadora remota se cuelga, entonces el acknowledge sera enviado pero la computadora local no lo recibira, por lo que la computadora remota espera hasta que cierto time-out se cumpla y considera la conexion como cerrada. debido a que TCP/IP fue diseñado para trabajar sobre vinculos no confiables y de alta latencia, este esperara durante mucho tiempo hasta que considere la conexion cerrada (o fallida). Esto usa recursos en la computadora remota (mayormente CPU y memoria) que pueden ser reducidos a su minima expresion si muchas conexiones permanecen en este estado.

Un reporte muy completo puede encontrarse en el CERT, en la referencia
[12].


[ Apendice B - Herramientas ]

Que vuele a su mente cuando se dice herramientas. Si la respuesta es
"programas para reforzar la programacion segura" es mas o menos correcto,
solamente si, no significa solo listas para usar. Se debe estar preparado
para algun tipo de trabajo interno o la adaptacion de algun que otro
programa a sus necesidades.


[ Logging extensivo ]

Despues de todos estos problemas a ser resueltos algo debe estar claro, y
es que a pesar de todo el esfuerzo los programas no son perfectos, y las
imperfecciones puede y, seguramente, van a aparecer. Para descubrir estos
problemas deben usarse las herramientas apropiadas tales como debuggers y
analizadores de dump, pero a veces no son los suficientemente utiles,
particularmente cuando no se sabe por donde comenzar la busqueda.

Recuerdan el cuento de "Hansel y Gretel" ? Iban tirando migas de pan
durante su camino, y asi podian volver mas tarde. Nostros usaremos el
mismo truco, dejaremos una marca de cada pedazo de codigo que es ejecutado
junto con los datos mas importantes durante un ataque (o una simple falla),
tal que se puedan rehacer los pasos seguidos.

FIX ME: What should and shouldn't (DoS attacks, special chars, passwords,
...)


[ Listos para usar ]

Esto es una simple lista de las herramientas conocidas para asegurar la
programacion segura, siendo los predilectos los del tipo Open Source.

Nombre: RATS (Rough Auditing Tool for Security)
Resumen: Es una herramienta de seguridad para C y C++ que hace una
busqueda sobre el codigo fuente, buscando llamadas a funciones
potencialmente peligrosas.
Licencia: Version 2 de la Licencia Publica GNU (GPL - GNU Public License).
Link: http://www.securesw.com/rats/

Nombre: Flawfinder
Resumen: examina el codigo fuente buscando vulnerabilidades en el codigo C
o C++.
Licencia: Licencia Publica GNU (GPL - GNU Public License).
Link: http://www.dwheeler.com/flawfinder/

Nombre: ITS4
Resumen: Es una herramienta simple que busca en el codigo fuente C o C++,
en forma estadistica, por potenciales vulnerabilidades de
seguridad.
Licencia: ITS4 NO-COMMERCIAL para el codigo fuente.
Link: http://www.cigital.com/its4

Nombre: LCLint
Resumen: Prueba estadistica de programas en C.
Licencia: Licencia Publica GNU (GPL - GNU Public License).
Link: http://lclint.cs.virginia.edu/

Nombre: StackGuard
Resumen: StackGuard es un compilador que genera programas mas resistentes
a los ataques del tipo "stack smashing" o "buffer overflow".
Licencia: StackGuard es Free Software: es una mejora a GCC y se distribuye
bajo licencia GPL enforma def uentes y binarios.
Link: http://www.immunix.org/stackguard.html

Nombre: FormatGuard
Resumen: FormatGuard protege programas C y C++ contra el "format bug",
mayormente usado en la familia de funciones printf.
Licencia: FormatGuard es Free Software: es una mejora a GCC y se
distribuye bajo licencia GPL enforma de fuentes y binarios.
Link: http://www.immunix.org/formatguard.html

Nombre: RSX
Resumen: RSX es un extensor del espacio de direcciones en tiempo de
ejecucion (Runtime addressSpace eXtender) que provee reubicacion
de codigo en tiempo de ejecucion para binarios Linux, que
implementa un stack no ejecutable y areas de heap pequeñas y
grandes. ataca el problema de "buffer overflow" previeniendo que
se ejecute codigo en las areas reubicadas (definidas de solo
lectura).
Licencia: Licencia propietaria que incluye los fuentes
Link: http://freshmeat.net/projects/rsx

Nombre: PageExec
Resumen: Implementacion de paginas no ejecutables para procesadores IA-32.
Licencia: Desconocida.
Link: http://pageexec.virtualave.net/

Nombre: Libsafe
Resumen: Permite evitar los "buffer overflow" y "format string",
empaquetado en forma de biblioteca (library) que intercepta las
llamadas conocidas como vulnerables.
Licencia: Libsafe version 2.0 (codigo fuente) es licenciado pajo la
licencia GNU Lesser.
Link: http://www.avayalabs.com/project/libsafe/index.html


[ Apendice C - Fallas ]

Una vez que hemos navegado a la vieja usanza, cerca de la costa,
necesitamos trazar un mapa mas detallado. Es mi preferencia personal ir de
lo generico hacia lo particular, asi que comencemos.

[ Datos entrantes ]

Comencemos con lo basico sobre programas o manipulacion de la informacion.
El esuqema tipico es obtener datos, procesarla (tranformarla) y ofrecer
los resultados: entrada-proceso-salida.

.-----------.
| |
INPUT --->| PROCESS |---> OUTPUT
| |
'-----------'

No es gran cosa, pero para evitar funcionamientos incorrectos y efectos
colaterales (algunos relacionados con las dependencias del sistema) deben
ser filtrados para obtener los datos apropiados.

Supongamos que lidiamos con un sistema bancario donde debe ingresarse un
numero de cuenta y que debe obtenerse el balance de la cuenta, entonces la
entrada (numero de cuenta) debe tener un formato determinado (digamos tres
numeros, cinco letras y ocho numeros), los que deben ser validados
(probados contra una plantilla) y revisados (rechazarlo si el formato no
es el apropiado o si la cuenat no existe).

En este ejemplo las opciones del formato de la cuenta son realmente
simples, solo no puede darse el balance de una cuenta si esta no existe,
pero hay problemas mas sutiles (que se mostraran mas adelante) que no son
del tipo funcional. Puede tomarse esta regla: todo lo que no sea usado
debe ser evitado.

Hay muchas formas de hacerlo, y cada una depende de los objetivos de cada
sistema:

* Finalizacion anormal: esta es la mas radical; en caso de deteccion de
una dato no valido el sistema interpreta que esta
bajo ataque (alguien buscando formatos de datos
impropios) y finaliza.
* Rechazo: a mitad de camino, cuando un dato no valido es detectado se
pregunta nuevamente por el mismo. esto tiene una ventaja para
una atacante, y es que puede preguntarse una cantidad ilimitada
de veces hasta que un dato valido es detectado.
* Utilizable: las partes impropias son quitadas y solo lo que coincide con
el formato apropiado es usado. Tipicamente se usa para datos de longitud
variable tales como direcciones de e-mail, URLs y direcciones postales.

Un lenguaje de programacion que tiene capacidades para la programacion
segura es Perl. Puede ser ejecutado utilizando el "tainted mode" donde,
esencialmente, cada dato obtenido desde el mundo exterior es marcado como
"sucio" y no puede ser usado hasta que sea limpiado. Normalmente la
maquina lavadora para estos "datos sucios" esta hecha de filtros, y si
estos datos son usados sin lavar Perl interrumpe su ejecucion (para una
explicacion mas profunda ver la referencia [4]).


[ Procesamiento (La caja de Pandora) ]

A veces se tiene mucho cuidado sobre los datos obtenidos pero, odio
decirlo, no es suficiente. Porque no somos perfectos y cometemos errores
debemos proteger al programa, y el sistema, de nosotros. Recordemos que en
cualquier programa hay muchos factores a tener en cuenta (es tan cierto
que en el analisis de confiabilidad de software el comportamiento de los
programas se estudian en forma estadistica) y no todos ellos pueden ser
tomados en cuenta a la vez, por lo que la posibilidad de introducir errores
es realmente alta (esta probabilidad decrece a medida que el programa es
probado y arreglado con el correr del tiempo).

No es fuera de lo comun que en todas las empresas e software bien
establecidas el uso de ambientes de prueba, ejecucion, etc. queb simulan
las condiciones de campo (ejecucuion en su destino final) y ejecutandolo
en una ambiente protegido, donde este falle, arroje errores, o lo que se
le ocurra. Lo mismo ocurre en su destino final, es ejecutado con mucha
precacucion hasta que se ejecuta como un proceso productivo, siendo su
monitoreo un proceso critico en las primeras semanas.

La mayoria de los lenguajes modernos de programacion como C++, Java, Perl
y Phyton contienen mecanismos de proteccion. Basicamente se ejecutan
partes del codigo en un ambiente protegido, y se atrapa cualquie error
(o excepcion) que pueda ser generado por el programa.

Por ejemplo, se puede rodear al codigo con un bloque que lo aisle de su
ambiente en caso de falla, y devuelva el control a una porcion de codigo
que maneje este error:

try() {
Code_under_suspicion();
} catch (Exception e) {
System.println "Code_under_suspicion(),
Exception generated : "
+ e;
}

Ahora supongamos que estamos desarrollando una serie de programas de uso
critico, como para medicina, aeronautica, etc. donde deben continuar
corriendo aun en condiciones de falla. Imaginemos que durante su vuelo, el
programa que sigue la ruta hacia el aeropuerto envia el siguiente mensaje
a la consola :

"Excepcion en 0x3F745DE9. El sistema esta siendo bajado."

Estos programas estan hechos con estas situaciones en mente, y deben
proseguir su ejecucion aun bajo condiciones especiales (digamos que se
aisla el codigo que causo el problema, realiza algun tipo de prueba sobre
el hardware y software, etc.)

Para leer una muy buena revision sobre excepciones aplicado a Java, ver la
referencia [8].

A veces no es una buena opcion hacerlo de esta forma, pero el colocar
algunas vallas de contencion alrededor del programa suele ser un poco mas
facil: no se requiere programacion extra, ni recompilacion para su
activacion. Para este casoe pueden usarse una serie de herramientas
standard tales como dump analyzers (analisis post-mortem) o debuggers
que envuelven al programa, y cuando se produce un error este es atrapado
y manejado por el debugger. Estos pueden imprimir la situacion del stack,
contenidos de variables, u ofrecer al programador/operador un interprete
de comandos (shell) que permita la inspeccion del programa, su reinicio,
dumping, etc.


[ Salida de datos ]

Y hablando de efectos laterales, tiene en mente que su salida es la fuente
de entrada de otro proceso? O aun peor ... que hay acerca de la basura
que se genera?.

Comencemos por el principio. El mismo problema que tenemos con nuestros
datos de entrada se transfiere al proceso que manejara nuestros datos de
salida y los procesara. Este proceso no manejara datos en crudo porque
nuestro programa/sistema actuara como filtro, pero asimismo puede generar
problemas (no a porposito, por supuesto) que pueden dañar un buen trabajo.

Tomemos un ejemplo donde se procesan una serie de datos y, como parte del
proceso de salida, se genera un archivo. Todo parece estar correcto, todo
esta en las especificaciones y estamos siguiendo las reglas del juego.

Seguro?. Si, por ejemplo, generamos un archivo con un nombre fijo, digamos
output.data, sencillamente :

filehandle = open( "output.data", w );
write( filehandle, data );
close( filehandle );

Seguramente se habran agregado algunas precauciones sobre la existencia
del archivo, preguntar al operador si el archivo puede ser borrado en caso
que ya exista, hacer un backup, y todo ese tipo de cosas, pero ... que
ocurre si la infraestructura en la que nos basamos fue comprometida y no
estamos escribiendo el archivo que realmente pensamos? Hay un "acceso
limpio"
al archivo?

Ademas, como seguramente sabra, una fuente importante de informacion son
el analisis y recoleccion de los contenedores de basura (despues de todo
por esto existen los trituradores de papel). El ejemplo mas claro de esto
es la respuesta a la pregunta "donde envia usted sus mensajes de
advertencia y error ?"
. Seguramente habra notado que en algunos web
servers cuando ocurre un error, tales como una pagina no encontrada o
una falla en un CGI, el error se envia al browser, y mensajes como el
siguiente aparecen:

The requested CGI program in '/home/httpd/cgi-bin/script' failed to
execute. The next lines contain the error:

Couldn't connect to database 'Customers' in server 'internal_db'.
Send a message to hostmaster@this_domain.com <mailto:hostmaster@this_domain.com>

Que fuente de informacion excelente!!! Esto DEBERIA redirigirse al log de
errores o hacia algun otro lado donde pueda ser leido por el
administrador/operador. Despues de todo esto no tiene sentido para la
mayoria de los usuarios y esa una muy buena fuente de informacion para los
crackers. No lo cree asi? La parte de triste de la historia es que la
mayoria de los web servers estan configurados en forma insegura
out-of-the-box.


[ Apendice D - Links ]

[1] Titulo: Secure Programming for Linux and Unix HOWTO
Autor: David A. Wheeler
Ubicacion: http://www.dwheeler.com/secure-programs

[2] Titulo: Why Computers are Insecure
Autor: Bruce Shneier
Ubicacion: http://www.counterpane.com/crypto-gram-9911.html#WhyComputersareInsecure

[3] Titulo: No silver bullet
Autor: Frederick P. Brooks, Jr.
Ubicacion: http://www.undergrad.math.uwaterloo.ca/ñcs212/resource/Articles/SilverBullet.html

[4] Titulo: Perl security
Ubicacion: http://www.perl.com/pub/doc/manual/html/pod/perlsec.html

[5] Titulo: Smashing The Stack For Fun And Profit
Tutor: Aleph One
Ubicacion: http://www.phrack.com/search.phtml?view&article=p49-14

[6] Titulo: Avoiding security holes when developing an application
Autor: Frederic Raynal, Christophe Blaess, Christophe Grenier
Ubicacion: http://www.linuxfocus.org/English/March2001/article183.meta.shtml

[7] Titulo: Bypassing StackGuard and StackShield
Autor: Bulba and Kil3r
Ubicacion: http://www.phrack.com/search.phtml?view&article=p56-5

[8] Titulo: What's an Exception and Why Do I Care?
Autor: Sun Microsystems
Ubicacion: http://java.sun.com/docs/books/tutorial/essential/exceptions/definition.html

[9] Titulo: SECPROG@SecurityFocus.com working document
Autor: Secure Programming list contributors
Ubicacion: http://www.securityfocus.com/forums/secprog/secure-programming.html

[10] Titulo: Analysis of format string bugs
Autor: Andreas Thuemmel
Ubicacion: http://www.securityfocus.com:80/data/library/format-bug-analysis.pdf

[11] Titulo: NT ODBC Remote Compromise
Autor: Matthew Astley & Rain Forest Puppy
Ubicacion: http://www.securityfocus.com/archive/1/13882

[12] Titulo: CERT Advisory CA-1996-21 TCP SYN Flooding and IP Spoofing Attacks
Autor: CERT
Ubicacion: http://www.cert.org/advisories/CA-1996-21.html


-- Victor A. Rodriguez (Bit-Man)
victor@bit-man.com.ar
http://www.ideahanster.org


<EOF>

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT