2010-10-28 14 views
8

Navegación a través de las partes más dudosos de la web, me pasó a venir a través de esta inyección SQL en particular:Explicación de inyección en particular sql

http://server/path/page.php?id=1+union+select+0,1,concat_ws(user(),0x3a,database(),0x3a,version()),3,4,5,6--

Mi conocimiento de SQL - que pensé que era medio decente - parece muy limitado mientras leo esto.

Como desarrollé mucho para la web, tenía curiosidad por ver qué hace realmente este código y, más importante aún, cómo funciona.

Respuesta

8

Sustituye a una consulta parametrizada incorrectamente escrita así:

$sql = ' 
SELECT * 
FROM products 
WHERE id = ' . $_GET['id']; 

con esta consulta:

SELECT * 
FROM products 
WHERE id = 1 
UNION ALL 
select 0,1,concat_ws(user(),0x3A,database(),0x3A,version()),3,4,5,6 

, que le da información sobre el nombre de la base de datos, la versión y el nombre de usuario conectado.

+2

Solo una nota: 0x3A es un punto (:) en hexadecimal –

+0

+1: Tenga en cuenta también que en realidad no está reemplazando '?' Como marcador de posición; si lo fuera, ¡no sería una inyección! Lo está reemplazando como texto * antes * de interpretación como SQL; esa es toda la esencia de los ataques de inyección SQL. –

+0

@Donal: lo dejó más claro en la respuesta. – Quassnoi

0

Parece recuperar el usuario utilizado para conectarse a la base de datos, la dirección de la base de datos y el puerto, la versión de la misma. Y será puesto por el mensaje de error.

1

Este código agrega una consulta de unión adicional a la instrucción de selección que se está ejecutando en page.php. El inyector ha determinado que la consulta original tiene 6 campos, por lo tanto, la selección de los valores numéricos (los recuentos de columnas deben coincidir con una unión). el concat_ws solo hace un campo con los valores para el usuario de la base de datos, la base de datos y la versión, separados por dos puntos.

4

El resultado de la inyección se basa en algunas suposiciones sobre la sintaxis subyacente de la consulta.

Lo que se asume aquí es que hay una consulta en algún lugar del código que tomará el parámetro "id" y lo sustituirá directamente en la consulta, sin molestarse en desinfectarlo.

Está asumiendo una sintaxis de consulta ingenua de algo como:

select * from records where id = {id param} 

Lo que esto hace es resultado de una consulta sustituido (en el ejemplo anterior) de:

select * from records where id = 1 union select 0, 1 , concat_ws(user(),0x3a,database(),0x3a,version()), 3, 4, 5, 6 -- 

Ahora, lo que hace esto lo que es útil es que logra capturar no solo el registro que le interesaba al programa, sino que también lo UNION con un conjunto de datos falso que le dice al atacante (estos valores aparecen separados por dos puntos en la tercera columna):

  • el nombre de usuario con el que estamos conectado a la base de datos
  • el nombre de la base de datos
  • la versión del software db

Se puede obtener la misma información simplemente ejecutando:

select concat_ws(user(),0x3a,database(),0x3a,version()) 

Directamente en un indicador de sql, y obtendrá algo como:

joe:production_db:mysql v. whatever 

Además, dado que UNION realiza un tipo implícito, y la primera columna del conjunto de datos falso comienza con un 0, las posibilidades son bastante buenas de que su resultado falso esté en la parte superior de la lista. Esto es importante porque el programa probablemente solo utiliza el primer resultado, o hay un poco más de SQL en la expresión básica que le di más arriba que limita el conjunto de resultados a un registro.

La razón de que exista el ruido anterior (por ejemplo, el select 0,1, ... etc) es que para que esto funcione, la instrucción con la que está llamando a UNION debe tener el mismo número de columnas que el primer conjunto de resultados. Como consecuencia, el ataque de inyección anterior solo funciona si la tabla de registro correspondiente tiene 7 columnas. De lo contrario, obtendrás un error de sintaxis y este ataque realmente no te dará lo que deseas. Los guiones dobles (-) son solo para garantizar que se ignore todo lo que pueda suceder después de las palabras en la sustitución y obtengo los resultados que deseo. La basura 0x3a solo dice "separar mis valores por dos puntos".

Ahora, lo que hace que esta consulta sea útil como vector de ataque es que se puede volver a escribir fácilmente a mano si la tabla tiene más o menos de 7 columnas.

Por ejemplo, si la consulta anterior no funcionaba, y la tabla en cuestión tiene 5 columnas, después de un poco de experimentación me ocurrió la siguiente dirección de consultas utilizar como un vector de inyección:

http://server/path/page.php?id=1+union+select+0,1,concat_ws(user(),0x3a,database(),0x3a,version()),3,4-- 

El El número de columnas que el atacante está adivinando probablemente se basa en una apariencia educada de la página. Por ejemplo, si usted está buscando en una página listando todos los Doodads en una tienda, y parece que:

Name  |  Type  |  Manufacturer 
Doodad Foo Shiny    Shiny Co. 
Doodad Bar Flat     Simple Doodads, Inc. 

Es una muy buena suposición de que la mesa que está viendo tiene 4 columnas (recuerda que hay más probablemente una clave primaria escondida en algún lugar si estamos buscando por un parámetro 'id').

Disculpe el muro de texto, pero afortunadamente eso responde a su pregunta.

+0

+1 - bien explicado – Nivas