|
| viZard |
Es un placer
y un honor estar aqui |
| viZard |
Fui invitado
por Seth Arnold hace algunos meses |
| viZard |
Análisis
léxico en la exploración del código de fuente |
| viZard |
Nota: éste
es un borrador del qué será presentado en Uninet Infosec
2002 el sábado, 20 de abril, 2002. Una traducción de |
| viZard |
babelfish
al español y francés aparece abajo. Las diapositivas están
disponibles en mi sitioweb en: |
| viZard |
http://www.monkey.org/~jose/presentations/czech-rubicon02.d
/ |
| viZard |
INTRODUCCIÓN |
| viZard |
[ diapositiva
1 ] |
| viZard |
Esta charla
está diseña para introducir la aplicación de análisis
léxico al análisis del código de fuente. |
| viZard |
Específicamente,
el diseño y la implentación |
| viZard |
de la herramienta
estática de análisis para el lenguaje de programación
C, nombrada "czech", serán presentados. |
| viZard |
defectos |
| viZard |
inherentes
en análisis estático, el uso del análisis léxico
en revisiones de código fuente, y las lecciones específicas
aprendidas del |
| viZard |
incidente
en el implentation del checo serán discutidos. |
| viZard |
[ diapositiva
2 ] |
| viZard |
Rápidamente,
daré una descripción de parte de la investigación
actual con la que soy familiar en este area. Varias personas están |
| viZard |
procurando
plasmar muchos, muchos años de métodos de evaluación
de código fuente y herramientas para automatizar |
| viZard |
el análisis
de seguridad de su código. |
| viZard |
Ésta
es un área de alto interés tanto para investigadores corporativos
como académicos. Yo |
| viZard |
introduciré
cuales son las herramientas léxicas de generación de código
y como funcionan, especificamente el uso de la herramienta |
| viZard |
"flexión", |
| viZard |
un analizador
de sintaxis libremente disponible del "parser" lex. Luego mostraré
las estrategias típicas para estas herramientas, y |
| viZard |
después
ahondaré en los desafíos específicos hechos frente
en la ejecución de la herramienta czech, para la herramienta y el
autor así como |
| viZard |
para los usuarios
de la herramienta. |
| viZard |
Para aquellos
que llegan ahora, los slides estan en |
| viZard |
http://www.monkey.org/~jose/presentations/czech-rubicon02.d/ |
| viZard |
[ diapositiva
3 ] |
| viZard |
Rápidamente,
una descripción de "czech". Discutiré la filosofía
de diseño de czech, y como |
| viZard |
hice el diseño
y la implementación. El rendimiento de "czech" es algo de lo que
soy absolutamente orgulloso. |
| viZard |
Daré
algún ejemplo de como funciona y mostraré la salida en bruto
de la herramienta, también discutiré algunos de los fallos
de |
| viZard |
funcionamiento
excepcionales actualmente. |
| viZard |
Finalmente,
discutiré algunas de las directrices futuras para czech y el conjunto |
| viZard |
del proyecto
pedantic. |
| viZard |
[ diapositiva
4 ] |
| viZard |
A pesar de
todo el interés que despierta actualmente, el análisis de
código fuente no es nada nuevo. Los investigadores de |
| viZard |
ingeniería
del software han estado haciendo esto durante años. |
| viZard |
En el campo
de la seguridad, esto se ha convertido en un área caliente para |
| viZard |
los investigadores
en años recientes, y muchos grupos grandes se han involucrado. Éstos
incluyen David Wagner, David Evans, y |
| viZard |
Microsoft. |
| viZard |
Los dos acercamientos
principales son el análisis estático, mirando código
de fuente típicamente. |
| viZard |
El análisis
dinámico, en contraste, toma el |
| viZard |
conjunto o
partes del programa y lo ejecuta con diversas entradas, vigilando el comportamiento
del programa. |
| viZard |
El |
| viZard |
análisis
estático se centra en cosas como el análisis lógico
del diseño, el análisis de flujo como maneja datos, y el
análisis de los "qualifiers" |
| viZard |
del tipo en
argumentos. |
| viZard |
Todos éstos
tienen sus distintos puntos fuertes, incluyendo la posibilidad de ampliación,
la facilidad de empleo, o la completitud de |
| viZard |
la cobertura. |
| viZard |
Debe ser notado
que ningún método da cobertura total, y cada uno carece de
algunos aspectos. |
| viZard |
También,
hay el problema de parada de Turing |
| viZard |
, donde sólo
se puede examinar una pequeña fracción de todos los estados
posibles del código en cualquier marco de |
| viZard |
tiempo dado. |
| viZard |
Como tal,
hay que centrarse en algunos aspectos y hacer relaciones de compromiso
entre la completitud y la eficacia. |
| viZard |
[ diapositiva
5 ] |
| viZard |
El proyecto
pedantic debe ciertamente mucho a algunas de las herramientas estáticas
más accesibles del análisis. Pscan era una de las |
| viZard |
primeras herramientas
del análisis de formato de cadena, y se podía utilizar para
encontrar algunos problemas comunes de los formatos cadena |
| viZard |
(véase
también la charla de KF, más adelante). |
| viZard |
ITS4, y RATS
posteriormente, eran también algunas de las |
| viZard |
herramientas
comúnmente citadas para los errores de programación habituales. |
| viZard |
Ambos también
se basan en análisis léxico, |
| viZard |
también. |
| viZard |
Flawfinder,
basado en python, trabaja de forma parecida a RATS, pero toma algunas decisiones
más elegantes. Finalmente, dos grandes |
| viZard |
herramientas
a observar son Lclint y splint, ambas fruto de la investigación
de David Evans y compañeros de trabajo en Virginia (los E.E.U.U.). |
| viZard |
Czech está
muy inspirado en estas herramientas. |
| viZard |
De hecho,
comencé a escribirlo después de que un artículo que
escribí para el |
| viZard |
Linux Journal
sobre RATS, ITS4 y Flawfinder y sentirme algo molesto con ellas. |
| viZard |
También,
durante el diseño del czech, hablé con |
| viZard |
David Wheeler,
el autor de Flawfinder. Intenté aprovechar mucho de este ' arte
anterior '. |
| viZard |
Como nota
de humor diré |
| viZard |
que el conjunto
de pruebas para czech rompe RATS y Flawfinder. |
| viZard |
[ diapositiva
6 ] |
| viZard |
Lex es una
herramienta para analizar flujos de entradas. |
| viZard |
Un analizador
léxico mira los modelos según fluyen y realiza las acciones |
| viZard |
basadas en
ellas. La herramienta lex toma el analizador de sintaxis y genera el código
C basado en él, que entonces es compilado. |
| viZard |
Estos modelos
se basan en expresiones regulares, lo que da mucho potencia y facilidad
de construcción. Las acciones se basan en gran parte en |
| viZard |
C, con algunas
macros y funciones de las bibliotecas lex y yacc. |
| viZard |
[ diapositiva
7 ] |
| viZard |
Aquí
vemos un ejemplo de algo de código lex en el explorador principal
en czech. |
| viZard |
Algunas de
las acciones corresponden con algunas |
| viZard |
cosas obvias,
como tabulaciones, newlines, y caracteres, o palabras. La función
" unput() " es una función de lex que coloca lo que |
| viZard |
se le dice
hacia atrás en la secuencia. REJECT es una macro que "unputs" (quita)
aquello que coincide. |
| viZard |
Una vez que |
| viZard |
se ha comenzado
la acción, se puede continuar teniendo acceso a la secuencia vía
la función del input(). |
| viZard |
Este pedazo
del código es bastante feo, a propósito. Realmente necesito
limpiarlo hasta lo hago más legible y hacer algún chequeo |
| viZard |
de la gramática.
Niels Provos, amigo mío, lo leyó y dijo, " hace que me duela
el cerebro. " |
| viZard |
[ diapositiva
8 ] |
| viZard |
Como mencioné
arriba, usted ejecuta este analizador de sintaxis a través de lex
para generar código de C. Entonces usted |
| viZard |
puede compilarlo: |
| viZard |
$ lex - t file.l > file.c |
| viZard |
$ cc - c file.c |
| viZard |
$ cc - fichero file.o de o - ll - ly |
| viZard |
|
| viZard |
Eso ejecuta
el |
| viZard |
analizador
de sintaxis " file.l " a través de lex para generar un cierto código
de C, que usted entonces compila. En el paso final de enlace |
| viZard |
se enlaza
con las bibliotecas de lex y de yacc para las funciones específicas
de ellas. |
| viZard |
Muy simple.
La página man de flex |
| viZard |
es una gran
gúia de lex, por cierto. |
| viZard |
[ paginación
9 ] |
| viZard |
para aquellos
que acaban de llegar, las diapositivas estan en |
| viZard |
http://www.monkey.org/~jose/presentations/czech-rubicon02.d/
] |
| viZard |
( Diapositiva
9) |
| viZard |
La estrategia
del proyecto fue bastante simple, |
| viZard |
entonces,
en los borradores, y se enfocaria en los esfuerzos enun lex parser. |
| viZard |
Un yacc parser
es para despues (mas abajo) |
| viZard |
Para escoger
entre un parser completo C un tag de teclado, realmente fue una decision
entre un diseño complejo y uno simple |
| viZard |
yo escogi
el mas simple, pero eventualmente nos cambiaremos a algo mas cercano un
parser C |
| viZard |
Czech comprende
el uso impropio de funciones peligrosas, como printf(), la familia
de formatos strings y sus problemas y el uso de strcat() in loops, |
| viZard |
lo cual nunca
deberia hacerse. |
| viZard |
(Diapositiva
10) |
| viZard |
La filosofia
del deseño de zcech fue muy importante para mi. |
| viZard |
Los puntos
principales son: |
| viZard |
. No preguntar
demasiado al desarrollador, es tiempo de consumo, promotor de errores,
y un gran dolor de cabeza. |
| viZard |
Un ejemplo
es Lclint, |
| viZard |
una herramienta
poderosa que requiere anotaciones del codigo para uso real. |
| viZard |
Cqual es otro
ejemplo |
| viZard |
que requiere
que los desarrolladores reevaluen su codigo de una manera logica |
| viZard |
En vez de
eso, yo buscaba algo que manejara el CC del Makefile. |
| viZard |
. Hacer el
reporte de salida, de facil lectura. |
| viZard |
no dandoles
demasiado en que preocuparse. |
| viZard |
.- Hacerlo
extendible |
| viZard |
Si se extiende
un API, se debe ser capaz de entrenar la herramienta facilmente. (yo falle
en esto miserablemente) |
| viZard |
. Que trabaje
muy rapido |
| viZard |
Aun que se
perdera mucho tiempo leyendo el reporte de salida, se podra retornar en
un tiempo razonable. |
| viZard |
.- Que pueda
enterder el flujo de programa. |
| viZard |
czech divide
el programa en ingresos y egresos de flujos de datos. |
| viZard |
( Diapositiva
11) |
| viZard |
El reto encarado
por cualesquiera de estas herramientas es muy elementar. |
| viZard |
Primero, se
tienen falsas positivas, y luego falsas negativas. |
| viZard |
Cada una,
conlleva a un decaimiento de la confianza en su herramienta. |
| viZard |
y desmotiva
a los desarrolladores. |
| viZard |
Debe ser posible
el entender nueva funciones, coo glib o BIND, haciendolo realmente funcional
para grandes proyectos como GNOME. |
| viZard |
Finalmente,
se debe recordad que C es un lenguaja muy flexible, y que nadie codifica
similarmente. Su herramienta debe ser capaz de manejar esta realidad. |
| viZard |
(Disapositiva
12) |
| viZard |
Czech puede
verse como un intento inicial para implementar estas ideas. |
| viZard |
Usa un preprocesamiento
en primeras instancias para expandir macros y tomar las funciones prototipos, |
| viZard |
asi como las
variables declaratorias. |
| viZard |
Una cualificacion
basia es hecha, y construye dos listas de tipos de datos, |
| viZard |
Los datos
que son entrados por el usuario, seran tratados mucho mas estrictamente
que los datos estaticamente definidos. |
| viZard |
Esto es en
el caso de que los formatos string, por ejemplo. |
| viZard |
Considere
el caso impropio de manejar el siguiente string: |
| viZard |
<jose_n>
static char *stuff = "this is a string"; |
| viZard |
<jose_n>
/* things happen */ |
| viZard |
<jose_n>
syslog (LOG_INFO, stuff); |
| viZard |
Syslog se
tiene que preocupar acerca del formato de strings, pero si se ha definido
un string por a voluntad, se sabe que tipo de datos se obtienen, |
| viZard |
asi que no
se debe arrojar un alerta por eso (probablemente una alerta amarilla) |
| viZard |
Ahora, si
se usa una funcion como esa y las "cosas" tienen contenido suplido por
usuario, entonces se debe revisar el formato del contenido y sus entradas. |
| viZard |
Czech intenta
hacer esto por ud con esta separacion de tipos de datos |
| viZard |
(Diapositiva
13) |
| viZard |
Czech es el
primer componente disponible para analisis de programas |
| viZard |
el cual esta
diseñado una herramienta de analisis de codigo fuente. |
| viZard |
Esta hecho
con alrededor de 1000 lineas de codigo, y se ejecuta bastante rapido (ver
desempeño mas abajo) |
| viZard |
Y es muy facil
de usar. |
| viZard |
Actualmente
no es plenamente funcional. |
| viZard |
Mientras que
puede crear las listas, estas aun no son usables. |
| viZard |
Es mas un
asunto de tiempo y motivacion en este momento, pero debera ser muy facil
(usando OpenBSD QUEUE(3) como interfaz). |
| viZard |
finalmente,
hay muchos detectores de errores en el ahrora mismo. |
| viZard |
Sin embargo,
es posible usarse junto con su compilador de C en muchos archivos Makefile. |
| viZard |
Ademas, ya
lo he usado para encontrar varios fallos y los he reportado a las personas
encargadas. |
| viZard |
(Diapositiva
14) |
| viZard |
Las principales
opciones claves de Czech son listadas aqui: |
| viZard |
. conoce algo
de usuabilidad segura, un strcpy() con un string de codigo constante
es mas seguro que un string de longitud varialble, pero aun no es segura. |
| viZard |
Y puede ignorar
de manera segura, el uso de va_args() en la familia printf(). |
| viZard |
. Conoce acerca
del uso no seguro. |
| viZard |
es mas grande
es el uso de strcat() en un loop, |
| viZard |
lo que puede
hacerse peligroso rapidamente. |
| viZard |
.- funciona
analizando cada una de las lidas, y luego evaluandolas en un cada una de
sus funciones y luego toma las decisiones basados en ellas. |
| viZard |
para debatir
un momento del texto preparado, permitanme expandir sobre esto. |
| viZard |
Czech analiza
una linea asi como uds lo harian mentalmente, usando la division de componente
en C, asi que una linea como |
| viZard |
printf("this
is a string %s", string); |
| viZard |
seria manejada
por Czech asi: |
| viZard |
printf
"this is a string %s" string |
| viZard |
asi que sabe
que busca el uso de printf, y que tiene dos argumentos |
| viZard |
en el primer
argumento esta marcado el uso de un string (via el %s), asi que llama a
esto "seguro". |
| viZard |
Similarmente
a cuando se tiene un string de codigo constante strcpy: |
| viZard |
strcpy(foo,
"this is foo"); |
| viZard |
Czech ve: |
| viZard |
strcpy
foo "this is foo" |
| viZard |
y las marcas
le dicen "eso es un string de codigo constante". |
| viZard |
las detecciones
del loop se hacen por las palabras basicas 'for', 'while', 'until'. |
| viZard |
Cuando un
llamado strcat() es detectado dentro, el lanza un error para uds. |
| viZard |
Esto es lo
que quiero decir con analisis de lineas, y luego como evaluar ese analisis. |
| viZard |
Tambien ignora
las palabras clave fuera de funciones, e intenta ignorarlas dentro de los
strings. |
| viZard |
Asi que si
se tiene un string como "i gets printf" el intentara ignorala. |
| viZard |
(Diapositiva
15) |
| viZard |
El desempeño
de Czech es bastante asombroso, dado el estado del codigo. |
| viZard |
En modo simple
de paso (como czech -C *.c) Este puede leer un millon de lineas por minuto. |
| viZard |
Cuando se
hace un analisis completo usando preprocesamiento, se nota una perdida
de desempeño del 10%- |
| viZard |
Quiero hacer
notar que estos numeros son en base a mi portatil, un P3/600 OpenBSD
system. |
| viZard |
El sistema
de archivos, memoria y CPU, claro esta variaran estos numeros. |
| viZard |
Ademas, he
obtenido estos numeros corriendolos en varios codigos fuentes, como todos
los de la rama src de OpenBSD, Apache, OpenLDAP, y BIND 9 |
| viZard |
(si, encontre
algunos errores notables) |
| MJesus |
[diapositiva
16] |
| MJesus |
Aquí
está un ejemplo del czech en acción. En
este ejemplo, el czech fue utilizado en el makefile como reemplazo para
el CC: |
| MJesus |
$ make CC=czech |
| MJesus |
czech
-O2 -c www6to4.c |
| MJesus |
initializing
czech 0130-04082002 in /home/jose/software/www6to4-1.5 |
| MJesus |
scanning www6to4.c
... |
| MJesus |
line 120: possible buffer overflow in strcpy |
| MJesus |
line 487: possible buffer overflow in strcpy |
| MJesus |
line 505: possible buffer overflow in strcpy |
| MJesus |
total number
of lines: 683 |
| MJesus |
total number
of matches: 3 |
| MJesus |
[ diapositiva
17] |
| MJesus |
Este es un
breve análisis de una de las llamadas strcpy() que el Czech advirtió
al respecto: |
| MJesus |
|
| MJesus |
481
while (fgets (buf, sizeof (buf), configfp)) { |
| MJesus |
482
char cmd[BUFSIZ], arg[BUFSIZ], tmp[BUFSIZ]; |
| MJesus |
483
char *p, *q; |
| MJesus |
484 |
| MJesus |
485
line_num++; |
| MJesus |
486 |
| MJesus |
487
strcpy (tmp, buf); |
| MJesus |
En su de la
línea 487 llamado en strcpy() del buf al tmp. El riesgo aquí
depende de los tamaños relativos de los buffers, del tmp y del buf.
Una de las cosas checas tiene que aprender es cómo calcular esos
valores... |
| MJesus |
[ diapositiva
18] |
| MJesus |
[ diapositiva
19 ] |
| MJesus |
quisiera acabar
czech, pero creo que tendré que trasladarme a la gramática
yacc, para hacerlo. Esto ciertamente hará el código
lex más fácil entender. También tendré
que construir un programa de análisis rudamentario de C, y por supuesto
examino los tamaños de los argumentos de las funciones para comparación.
Lclint hace esto por ejemplo, con un prototipo básico de: |
| MJesus |
strcpy(dest,
src); |
| MJesus |
/* insist (size(src) = |
| MJesus |
La herramienta
de la segunda generación está en la fase del diseño.
Serña llamada 'prauge ', un juego en el capital de la república
checa, así como el "prog" como alias. Estoy tirando para una
herramienta dinámica del análisis, posiblemente usando funciones
ptrace(2) para monitorizar ls argumentos y cómo son llamados, o
quizás el motor del análisis de Gdb (sugerido por un par
de amigos). Puedo ser capaz de hacer simplemente análisis
estátic |
| MJesus |
[ diapositiva
20 ] |
| MJesus |
Gracias, y
deseo agradecer el sarnold, el viZard, MJesus, y Oroz, así como
toda la otra gente implicada en UniNet. Es un honor a presentar aquí
con tales presentadores estimados compañeros. ¡Gracias! |
| MJesus |
thas'all ! |
| MJesus |
clap clap
clap clap clap clap clap clap clap clap |
| MJesus |
clap clap
clap clap clap clap clap clap clap clap |
| MJesus |
clap clap
clap clap clap clap clap clap clap clap |
| MJesus |
clap clap
clap clap clap clap clap clap clap clap |
| MJesus |
clap clap
clap clap clap clap clap clap clap clap |
| jose_n |
gracias mjesus |
| jose_n |
y vizard |
| viZard |
:) |