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.
Solo una nota: 0x3A es un punto (:) en hexadecimal –
+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. –
@Donal: lo dejó más claro en la respuesta. – Quassnoi