Español | English
rss facebook linkedin Twitter

Ocultando información en un PDF

Vamos a hacer un pequeño descanso de acciones en PDFs (que por aquí ya me miran mal) para hacer una mención a los filtros que se pueden aplicar a los objetos stream de los documentos. Un objeto stream está definido por un diccionario seguido del contenido propiamente dicho, entre las palabras 'stream' y 'endstream'. En ese diccionario es donde se pueden definir algunas de las propiedades del stream, como por ejemplo, su tamaño, los filtros que hay que aplicar para decodificarlo/descomprimirlo o el nombre del archivo externo en caso de que el contenido del stream se encuentre en un archivo aparte.


Como supondréis, una forma de ocultar información dentro del PDF es aplicar a ésta uno o varios filtros para que al menos esos datos no sean visualmente identificables, dificultando así el acceso al contenido real. Ésta es una de las técnicas que nos podemos encontrar cuando echamos un vistazo a un PDF que explote una de las últimas vulnerabilidades, por ejemplo.

Existen dos tipos de filtros: los filtros ASCII, que decodifican un texto ASCII obteniendo datos en binario, y los filtros de descompresión, que, como su nombre indica, decodifican datos previamente comprimidos con cierto algoritmo. El filtro que se aplica más comúnmente es el FlateDecode, que se encarga de obtener los datos comprimidos con el método zlib/deflate, y éste suele emplearse sólo, es decir, sin ninguna codificación antes o después. Si os encontráis con un stream de este tipo lo primero que debéis hacer para obtener el contenido real es aislar el stream en un archivo aparte, entendiendo por stream los datos que van justo después de la palabra 'stream', sin tener en cuenta los caracteres de salto de línea y retorno de carro, hasta el carácter inmediatamente anterior a la palabra 'endstream', también sin tener en cuenta los mencionados caracteres. Una vez hecho esto necesitaremos la librería zlib y el lenguaje de programación de nuestra elección para programarnos en un momento la descompresión del stream, y obtener rápidamente el contenido. En Python, bastaría con unas pocas líneas para conseguirlo:


Los filtros no se usan normalmente para ocultar información, sino que son habituales a la hora de crear un PDF, con el objetivo de ahorrar espacio o evitar caracteres binarios en el archivo, por ejemplo. Hay muchos filtros aparte del comentado, que podréis encontrar detallados en la sección 3.3 de la especificación 1.7 del formato PDF.

A modo de práctica, por si os aburrís, os paso este PDF, a ver si demostráis lo fácil que es...;)


Jose Miguel Esparza
S21sec e-crime

7 comentarios:

Dani Kachakil dijo...

¿La imagen del PDF solo revela que Curro está en Amsterdam o hay algo más? ;-)

Saludos!

S21sec e-crime dijo...

Shhhhhh, que eso no se dice...:)

Sí, realmente era sólo una sencilla prueba para practicar lo comentado, los retos los dejo para mi compañero Mikel;) De todas formas, menuda rapidez, no?? jeje

Un saludo,
Josemi

DeMoNiC dijo...

Buenas. Estoy trabajando con unos pdf los cuales parece que tienen este tipo de filtro y no soy capaz de sacarles la información. Si alguien tiene un poco de tiempo para echarme una mano se lo agradecería. He intentado sacar la información usando la herramienta "pdftk", y he probado usando las funciones de zlib, pero no soy capaz. Os dejo un pdf de ejemplo: http://www.megaupload.com/?d=14A7I686

Saludos.

S21sec e-crime dijo...

Buenas DeMoNiC,

dónde tienes el problema exactamente? ten en cuenta el tamaño de los streams, indicado por el parámetro /Length (en este caso son referencias a otros objetos), ya que quizá tengas que descartar un par de caracteres para evitar errores de descompresión...

Un saludo,
Josemi

DeMoNiC dijo...

Veamos, he estado viendo el pekeño tutorial que has puesto, y he escrito un pequeño codigo en C usando zlib para poder obtener la información que necesito. La he probado con un pdf sencillo que sólo contenía un "hello world" y con él bien, pero al coger el texto contenido entre "stream" y "endstream" del pdf que necesito recuperar información, me dice: invalid or incomplete deflate data.

En cuanto al parámetro Lenght, no mencionabas nada en la entrada, ¿qué debería hacer con él?

¿Qué tengo que hacer a parte de coger el texto contenido entre las palabras "stream" y "endstream"?

Saludos y perdón por mi desconocimiento en la materia.

S21sec e-crime dijo...

Es cierto que no comentaba nada sobre el parámetro /Length, que no es estrictamente necesario, aunque a veces puede dar una idea de si el stream que tienes es el correcto.

Este parámetro indica el tamaño del stream, por lo que si no coincide con el número de bytes que has cogido significa que deberás hacer una pequeña limpieza de caracteres.

Sobre este aspecto sí que hago un pequeño comentario, y es que normalmente los caracteres de retorno de carro y salto de línea del comienzo y fin de stream deberían quitarse. Es cuestión de jugar con esto hasta obtener el tamaño correcto.

Creo que esto te puede ayudar. En caso contrario me puedes mandar un mail a jesparzaATs21sec.com con el contenido del stream y ya lo miramos con más detenimiento.

Un saludo,
Josemi

DeMoNiC dijo...

Mmm pues temgp Length 6 0 R y el primer stream que tengo es bastante largo, así que mejor te escribo al correo a ver si me puedes ayudar.

Saludos y gracias.


(+34 902 222 521)


24 horas / 7 días a la semana



© Copyright S21sec 2013 - Todos los derechos reservados


login