Método para extraer datos de Blind SQLi
Recientemente me encontré un documento titulado Faster Blind MySQL Injection Using Bit Shifting por Jelmer de Hen el cual describe una técnica que permite obtener datos de una base de datos MySQL en tan solo 8 peticiones por caractér, utilizando Bit Shifting. Es una ligera mejora con respecto al método tradicional de Bisección. Me puse a pensar en cómo se podría extraer información en una cantidad menor de peticiones, después de unas horas de estar jugando, esto fue lo que encontré.
AND (SELECT @a:=MID(BIN(FIND_IN_SET(MID(table_name,1,1), 'a,b,c,d,e,f
,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9,_,!,@,#,
$,%,^,&,*,(,),-,+,=,\,,.,",\',~,`,\\,|,{,},[,],:,;, ,')),1,1) FROM in
formation_schema.tables LIMIT 1)=@a AND IF(@a!='',@a,SLEEP(5));
Una explicación rápida de cómo funciona esta sentencia y lo que hace:
Primero inicia con la clasica inyección blind, seleccionando solamente 1 caractér de la tabla cada vez
SELECT MID(table_name,1,1) FROM information_schema.tables LIMIT 1
Después utiliza FIND_IN_SET(), para buscar la posición del caractér en la lista. Por ejemplo, digamos que la tabla es "CHARACTER_SET", MID("CHARACTER_SET",1,1) = 'C', entonces el valor que regresa FIND_IN_SET('C', 'a,b,c') seria 3 (no importan las mayusculas). Procedemos a utilizar BIN() para convertirlo a binario, BIN(3) = 11. Ahora hemos reducido las posibilidades a solo 1 o 0. Únicamente tenemos que revisar si el caractér es 1, si no lo es, asumimos que es 0. Por lo tanto BIN(3) = 11 nos tomaria 3 requests: Es el primer dígito 1? Si. Es el segundo dígito 1? Si. Es el tercer dígito 1? No, no hay tercer dígito, así que te envía a la función SLEEP().

Ahora sabemos que CAST(b'11' AS DEC) es 3 y que es el equivalente a la letra 'c' de la lista, todo en 3 peticiones! Digamos que tu lista contiene 45 elementos, BIN(45) = 101101, aún así la cantidad total de peticiones sería 7 para los caracter que esten cerca del final de la lista. Estoy seguro que se puede optimizar y mejorar de gran manera, probablemente agregando o utilizando funciones mas eficientes. Una idea seria dividir la lista en dos peticiones, de esta forma aseguras que la longitud del binario no sea demasiado grande.

Desventajas:
La sentencia puede ser mas larga que lo normal.
Requiere la función SLEEP() para saber cuando se ha terminado el binario.
Otra posible solución que no requiere SLEEP(), pero requeriría dos páginas diferentes (test.php?id=0, test.php?id=1) podría ser de la siguiente manera:
IF((@a:=MID(BIN(FIND_IN_SET(MID(table_name,1,1),'a,b,c,d,e,f
,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9
,_,!,@,#,$,%,^,&,*,(,),-,+,=,\,,.,",\',~,`,\\,|,{,},[,],:,;,
,')),1,1)=1||0),@a,0/0) FROM information_schema.tables LIMI
T 1;
ACTUALIZACIÓN (4-ABR-11):
Debería mencionar dos puntos importantes: Esta técnica no requiere la función
FIND_IN_SET(). Hay varias funciones similares que pueden sustiruirla como LOCATE(), POSITION(), INSTR(), FIELD() por nombrar algunas. Y la segunda, no es necesario utilizar comillas. Por ejemplo, FIND_IN_SET(0x33, CONCAT_WS(0x2C,0x31,0x32,0x33));


Método para extraer datos de Blind SQLi
TWITTER
FACEBOOK
RSS
CONTÁCTANOS