sábado, 26 de septiembre de 2015

Error "BUG" en Microsoft-Edge (TRK:0285936)

Microsoft TRK:0285936
Microsoft Case: 31110

Recientemente he notificado a Microsoft un "error" que he localizado en su nuevo navegador Microsoft-Edge. Se trata de un fallo en el parser del campo dedicado a la dirección o URL, el cual encontramos en la parte superior de la ventana del navegador.


Aunque Microsoft no lo considera una vulnerabilidad desde el punto de vista de la seguridad del sistema, si que están de acuerdo conmigo en que puede ser utilizado para realizar un ataque de Denegación de Servicio (DoS).


En fallo hace que Microsoft-Edge entre en una especie de bucle infinito que se dedica a abrir de manera continuada gran cantidad de nuevas pestañas vacías en el navegador. Esto, no solamente provoca una Denegación de Servicio sobre el equipo atacado, dado que impide que el usuario pueda navegar por internet, sino que además puede llegar a provocar una sobrecarga de la memoria (Heap exhaustion), ya que por cada nueva pestaña que se abre, se consume una cantidad de memoria que no es liberada.


Cronología de comunicaciones entre mi persona y el equipo de seguridad de Microsoft:
  • El primer contacto con el equipo de seguridad de Microsoft lo realicé el día (03/09/2015) remitiéndoles un correo electrónico para notificar dicho hallazgo para que sus expertos lo analizaran en profundidad.
  • El equipo me responde el mismo día (03/09/2015 diciéndome que no se puede explotar remotamente y que por lo tanto no lo tendrán en consideración, ya que, entienden que es necesario tener acceso físico al equipo para poder explotar este fallo.
  • Ese mismo día (03/09/2015) les envío otro e-mail con una pequeña prueba de concepto para que vean que si puede ser explotado remotamente y además desde varios frentes distintos.
  • El mismo día (03/09/2015) me notifican que lo van a trasladar al equipo de análisis para su investigación.
  • El día (05/09/2015) me agradecen nuevamente la información facilitada y me indican que van a abrir un nuevo caso (nº 31110) y que el administrador de casos (Michael) se pondrá en contacto conmigo en cuanto tenga más información al respecto. Me piden que por favor, en un principio respete las "Directrices de divulgación de vulnerabilidades coordinada" y que no revele públicamente este hallazgo para permitir que los usuarios tengan la posibilidad de actualizar sus sistemas y estar protegidos ante eventuales ataques.
  • Así lo hago, y no revelo nada para evitar que "el lado oscuro" pueda hacer un mal uso de este fallo en Microsoft-Edge.
  • Finalmente, el día (18/09/2015) me contestan con el siguiente e-mail:
"After our investigation we have determined this to be user-recoverable temporary DoS. This does not meet the bar for security servicing and we will be closing out as wont fix."


Básicamente que se trata de una "Denegación de Servicio" y que no lo consideran un problema para la seguridad y que por tanto no se aplicará una solución al respecto.


NOTA: A día de hoy 26 de Noviembre de 2015, Microsoft ya ha aplicado un parche que repara este Bug. "De nada Microsoft, un saludo".


¡ADVERTENCIA! A continuación podéis probar el fallo encontrado en vuestro navegador (Microsoft-Edge) bajo vuestra responsabilidad, yo no me hago responsable de los daños que se puedan ocasionar en vuestros equipos. Para poder probar este "Bug" en vuestros navegador podéis pulsar sobre este LINK desde Microsoft-Edge y veréis el efecto de infinitas pestañas abriéndose y consumiendo la memoria de vuestro sistema.

Así que, ya sabéis, si estáis utilizando Microsoft-Edge que sepáis que existen una serie de "bugs" que pueden provocar una Denegación de Servicio en vuestro acceso a internet e incluso consumir la totalidad de la memoria de vuestros sistemas, eso sí, de momento no parece que vaya a haber una solución al respecto.


Ya veremos si en futuras actualizaciones corrigen estos problemas o por el contrario será el clásico "bug" que se arrastra durante años, espero que no.


NOTA: A día de hoy 26 de Noviembre de 2015, Microsoft ya ha aplicado un parche que repara este Bug. "De nada Microsoft, un saludo".

miércoles, 16 de septiembre de 2015

MIDLRT - Generate metadata files (.winmd)

If you are programming a custom Windows Runtime component by hand, one of things you must to do is generate the IDL (Interface Definition Language) file. Once you have that file, you can get the metadata file (.winmd) by using the "MIDLRT" tool.


MIDLRT is a command line tool used to create metadata (.winmd) files that represent the API of your own custom Windows Runtime component.


You can use this nice tool as easy as writing this command:


C:>midlrt filename.idl


One option you can specify is the "metadata_dir" option, like in this example:


C:>midlrt MyRuntimeComponent.idl /metadata_dir "C:\windows\system32\WinMetaData"


When the tool MIDLRT has finished his job, you will have the following files in your current directory:


  • dlldata.c
  • MyRuntimeComponent.h
  • MyRuntimeComponent.winmd
  • MyRuntimeComponent_i.c
  • MyRuntimeComponent_p.c


Another nice tool you can use with all this stuff is "WINMDIDL". This is also a command-line tool you can use to generate automatically IDL files from your metadata files (.winmd) like this:


C:>winmdidl MyRuntimeComponent.winmd

martes, 15 de septiembre de 2015

C++/CX & Xaml Data Binding

There is a few methods that you can use to make a C++/CX class with data-bindable capability. The most simple way is by adding an attribute to the class declaration:


[Windows::UI::Xaml::Data:Bindable]

public ref class SampleDataClass sealed
{
...
};


But, What about non-public classes? With the non-public classes you can declare the class by implementing either the ICustomPropertyProvider interface or IMap:


ref class SampleDataNonPublicClass sealed : Windows::UI::Xaml::Data::ICustomPropertyProvider
{
...
public:
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetCustomProperty(Platform::String^ name);
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetIndexedProperty(Platform::String^ name, Windows::UI::Xaml::Interop::Type type)
property Windows::UI::Xaml::Interop::TypeName Type
{
virtual Windows::UI::Xaml::Interop::TypeName get() { return this->GetType(); }


}

virtual Platform::String^ GetStringRepresentation()
{return this->ToString();
} };

jueves, 3 de septiembre de 2015

Windows Runtime DateTime to SYSTEMTIME conversion

This post is about how to make date/time conversion between Windows::Foundation::DateTime and SYSTEMTIME structure types. Let's go to see by example:


// First we obtain the current DateTime from Calendar class

Windows::Globalization::Calendar^ cal = ref new Windows::Globalization::Calendar();
Windows::Foundation::DateTime date= cal->GetDateTime();


// Here, we are converting DateTime to a 64bit value (UniversalTime format)
ULARGE_INTEGER time;
time.QuadPart = date.UniversalTime;


// Now convert the ULARGE_INTEGER to a FILETIME structure
FILETIME fileTime;
fileTime.dwHighDateTime = time.HighPart;
fileTime.dwLowDateTime = time.LowPart;


// And finally we get a SYSTEMTIME value by calling the FileTimeToSystemTime Windows Api.
SYSTEMTIME systemTime;
FileTimeToSystemTime(&fileTime, &systemTime);

With C++ and once again, we are doing many things to something simple but sometimes necessary.

C++ Platform::String^ object to const wchar_t* conversion

In Windows Store applications, for example when you want to make a shared library, it is necessary to make use of common types like Platform::String. All the public types must be types from Windows Runtime to make it possible a cross language usage of your libraries (C++, JavaScript, C#, VB).

But when you want to use the C++ standard types like wchar_t or std::wstring, you're going to need a temporary conversion from Windows Runtime types to C++ Standard types.

You can access the string value of a Platform::String^ object by using the Data() method like this:

Platform::String^ ps3DModel(L"Gear");
std::wstring _3DModel = ps3DModel->Data();


Now, you can use the _3DModel std::wstring like another C++ standard string by using his own methods. Also, you could have converted to a "const wchar_t type":


const wchar_t * _3DModel = ps3DModel->Data();

The problem is when you want to make any changes into the ps3DModel Platform::String object since this is inmutable. What you mus to do is make a copy of the string into a std::wstring object and them modify it according to your needs. Later, when you must save the changes into the Platform::String object, you must create as a new "ref new Platform::String^". But better, let's see this with a small example:


// We create the Platform::String object
Platform::String^ ps3DModel(L"Gear");

// Now, we copy the string into a new wstring object
std::wstring _3DModel = ps3DModel->Data();

// Here we make some changes
_3DModel = L"_GEAR_";

// An finally, we put the changes into the original 'ps3DModel' object
ps3DModel = ref new Platform::String(_3DModel.c_str());

WinRT with C++ Standard vs C++/CX

OFFTOPIC:
Nota: Hoy he decidido escribir esta publicación del blog en inglés.
Note: Today I decided to write this blog post in English.


In a new application than I am developing for a company, I had to decide if to make use of C++/CX (C++ with Component Extension) or make all the main stuff in C++ standard and ABI/COM.

All of you than have had to work with COM (Component Object Model) and fighting with the interfaces, reference count, etc. known the tricky and heavy that it can become.

As an example of the easy approach using C++/CX, I am creating a new Uri object, like this:

auto uriEasyWay = ref new Windows::Foundation::Uri(http://www.manuelvillasur.com);
assert(wcscmp(uriEasyWay->AbsoluteUri->Data(), L"http://www.manuelvillasur.com/") == 0);


Now, I going to show you the more difficult approach using C++ Standard and  ABI/COM interfaces:

HSTRING_HEADER header = {};
HSTRING string = nullptr;

HRESULT hr = WindowsCreateStringReference(L"Windows.Foundation.Uri", 22, &header, &string);

if (SUCCEEDED(hr)) {
    ABI::Windows::Foundation::IUriRuntimeClassFactory * factory = nullptr;
    hr = RoGetActivationFactory(string, __uuidof(factory), reinterpret_cast<void **>(&factory));

    if (SUCCEEDED(hr)) {
        HSTRING stringUri = nullptr;
        hr = WindowsCreateStringReference(L"http://www.manuelvillasur.com", 24, &header, &stringUri);

        if (SUCCEEDED(hr)) {
            ABI::Windows::Foundation::IUriRuntimeClass * uri = nullptr;
            hr = factory->CreateUri(stringUri, &uri);

            if (SUCCEEDED(hr)) {
                HSTRING absUriString = nullptr;
                hr = uri->get_AbsoluteUri(&absUriString);
                if (SUCCEEDED(hr)) {
                    const WCHAR * uriString = WindowsGetStringRawBuffer(absUriString, nullptr);
                    assert(wcscmp(uriString, L"http://www.manuelvillasur.com/") == 0);
                    WindowsDeleteString(absUriString);
                }
                uri->Release();
            }
        }
        factory->Release();
    }
}

martes, 1 de septiembre de 2015

C++ Moderno

Si eres programador de C++, no te quedes atrás y ponte las pilas con C++ Moderno, porque ya viene pisando fuerte desde hace unos añitos y cada vez se está haciendo notar más.


Con las nuevas especificaciones del lenguaje de programación C++ (C++11, C++14, 17 ...) vienen, como es lógico, nuevas características interesantes y poderosas que no podemos dejar de utilizar por desconocimiento. Así, aunque podemos seguir programando en C++ "antiguo", hacer caso omiso de las nuevas características del lenguaje impedirá, entre otras cosas, que seas más productivo.


Como ejemplo, puedes echar un vistazo a esta función que localicé hace tiempo por Github (https://gist.github.com/goldshtn/7433212) en la cual puedes ver algunas de estas nuevas características del lenguaje:


#include <iostream>

#include <future>


using namespace std;


template <typename Fn, typename... Args>

auto do_async_with_log(ostream& os, Fn&& fn, Args&&... args) ->

         future

{

    os << "[TID=" << this_thread::get_id()

       << "] Starting to invoke function..." << endl;

    auto bound = bind(fn, forward(args...));

    return async([b=move(bound),&os]() mutable {

            auto result = b();

            os << "[TID=" << this_thread::get_id()

               << "] ...invocation done, returning " << result << endl;

             return result;

     });

}


Cualquier programador de C++ de "la vieja escuela", posiblemente al observar este código se pregunte ¿Esto es C++? Pues sí, pero esto es C++ Moderno.


Algunas de las nuevas características que debieras ir mirando son:


  • Plantillas Variádicas,
  • Bucles For basados en rango,
  • Inicializadores de listas,
  • Expresiones Lambdas,
  • Concurrencia,
  • Especificadores como Override, Final, noexcept, decltype, ...
  • Punteros inteligentes,
  • Referencias Rvalue y semántica move,
  • etc.

viernes, 28 de agosto de 2015

¿Dónde se instalan las aplicaciones en Windows 10?

Si necesitas saber donde se instalan las aplicaciones en Windows 10, tan solo debes dirigirte al siguiente directorio/carpeta y ahí las encontrarás:


C:\Program Files\windowsapps ó


C:\Archivos de Programa\windowsapps


Recuerda que al igual que en Windows 8 (como ya comenté aquí), esta carpeta está protegida y necesitarás los permisos adecuados para poder acceder a ella.



RAII (Resource Adquisition is Initialization)

Todo programador de C/C++ sabe que un handicap extra a la hora de diseñar software e implementarlo correctamente, es la gestión de recursos/memoria. En este lenguajete de programación es bien conocido el trabajo de punteros y reservas/liberación de memoria y los riesgos que ello conlleva si no se realiza correctamente. Encontrarse con problemas de "fugas de memoria", "saturación de recursos", "buffer overflows", UaF, además de propiciar el mal funcionamiento del software o su comportamiento no controlado, pueden dar pie a graves problemas de seguridad.

Con esta idea en mente, un buen día Bjarse Stroustrup, inventor del lenguaje de programación C++, ideó una técnica de programación conocida como RAII (Resource Adquisition Is Initialization). Traducido al español, significaría algo así como que la adquisición de recursos es inicialización. La idea general consiste en dejar que sea el propio destructor del objeto el que se encargue de liberar los recursos que se habrán reservado previamente en la inicialización del mismo.

Vamos a plantear un caso práctico donde tiene mucho sentido implementar un patrón de estas características tipo RAII. Supongamos que tenemos un clase cuyo objetivo es guardar determinados eventos en un archivo de registro (LOG) clásico. RAII nos estaría diciendo que debemos inicializar y posiblemente abrir el archivo de registro en la inicialización del objeto o en su constructor y, que dicho archivo debería cerrarse y por ende, liberar sus recursos en el destructor de dicho objeto.

Esto cobra un gran sentido, si planteamos un escenario donde el archivo de registro se ha abierto con total normalidad, pero al escribir algún determinado evento en el mismo, se produce alguna excepción., o incluso excepciones que no tengan una relación directa con la clase encargada de gestionar el registro de eventos. Algo que debemos saber, es que ante tales excepciones, el código que con seguridad se va a ejecutar es el correspondiente al destructor de los objetos, lo cual garantizaría la liberación de los recursos. Sin embargo, si no utilizamos esta técnica, podríamos estar fugando la memoria correspondiente a los recursos consumidos por el objeto, dado que tras producirse la excepción, estos no serían liberados.

A continuación podemos ver una clase donde se hace uso de la técnica de programación RAII.


class CEventLog
{
public:
 // Constructor
 CEventLog(const char* nombrearchivo)
 : _pvFile(std::fopen(nombrearchivo, "w+")) {
  if (!_pvfile) {
   throw std::runtime_error("Error al abrir el archivo de registro (LOG).");
  }
 }
 // Destructor
 ~CEventLog() {
  if (std::fclose(_pvfile)) {
   throw std::runtime_error("Error al cerrar el archivo de registro (LOG).");
  }
 }
private:
 std::FILE* _pvFile;
 // ...
};


Pues bien, esta clase la podríamos utilizar con total tranquilidad, en cuanto a la liberación de los recursos consumidos por FILE se refiere, ya que estos, serán liberados "sí o sí", en el destructor de la clase, aunque se produjeran excepciones.


Como conclusión final, recordad que la liberación de los recursos consumidos por nuestros programas, es tan importante o más que su reserva.

sábado, 22 de agosto de 2015

Base64 encoding & decoding with OpenSSL

Just a Little reminder about using base64 with OpenSSL in Windows Operating Systems.

Encoding:

C:\> OpenSSL enc -base64 < file_name_plain_text.txt

Decoding:

C:\> OpenSSL enc -base64 -d < file_name_base64_encoded.txt

domingo, 2 de agosto de 2015

Android Stagefright Exploit / POC (III)

En la anterior entrada del blog comentaba que podíamos seguir principalmente dos vectores de búsqueda a la hora de localizar código vulnerable en el caso que nos ocupa (Android Stagefright).

Pues bien, en esta nueva entrada me voy a centrar en el vector de búsqueda por código fuente. Dado que tenemos acceso al código fuente, la manera más sencilla de localizar alguna vulnerabilidad, sin lugar a dudas será esta.

Son muchos los tipos de vulnerabilidades que puede tener un software y, una de ellas bien conocida y documentada son los "Integer Overflows" y los "Integer Underflows".

Parece bastante lógico pensar, que dada la complejidad del código de un sistema operativo (Android en este caso), no será difícil que algún programador cometa determinados tipos de errores y los desbordamientos de números, enteros en este caso, no son una excepción.

Como sabemos a día de hoy, desde la versión Android 2.2 hasta Android 5.1.1.r4 se han encontrado diversos fallos relacionados con los Integer overflows/underflows.

Para poder verlo de una manera más clara, nada mejor que echar un vistazo al código fuente de Android y en concreto al framework multimedia Stagefright que ha suscitado tanta polémica en los últimos días (y no es para menos,  según  dicen, más de 900 millones de dispositivos podrían ser vulnerables).

A continuación tenemos un pedazo de código fuente de Stagefrigtht en donde vamos a ver claramente uno de estos "Integer underflows", se trata de la función parseESDescriptor, cuya firma o prototipo tiene la siguiente forma:

status_t ESDS::parseESDescriptor(size_t offset, size_t size)

Rápidamente podemos observar que requiere de un par de parámetros de tipo size_t, que como sabremos se trata de un tipo entero sin signo (unsigned int), utilizado principalmente para devolver el tamaño en bytes de algún tipo de objeto, etc.

Esto significa que tanto "offset" como "size" debieran contener algún valor de tipo entero mayor o igual que cero, pero nunca menor, es decir, nunca debiera ser negativo.

Pues bien, aquí es donde han cometido el fallo, los chicos de Google cuando programaron esta función, cuyo cuerpo podemos ver a continuación, eso sí un poco abreviado para no mostraros código innecesario para la prueba de concepto:

1.  status_t ESDS::parseESDescriptor(size_t offset, size_t size) {
2.  
3.  if (size < 3) {
4.         return ERROR_MALFORMED;
5.  }
6.  
7.  offset += 2; // skip ES_ID
8.  size -= 2;
9.  
10. unsigned streamDependenceFlag = mData[offset] & 0x80;
11. unsigned URL_Flag = mData[offset] & 0x40;
12. unsigned OCRstreamFlag = mData[offset] & 0x20;
13. 
14. ++offset;
15. --size;
16. 
17. if (streamDependenceFlag) {
18.        offset += 2;
19.        size -= 2;
20. }
21. 
22. if (URL_Flag) {
23.        if (offset >= size) {
24.              return ERROR_MALFORMED;
25.        }
26.        unsigned URLlength = mData[offset];
27.        offset += URLlength + 1;
28.        size -= URLlength + 1;
29. }
30. ...
31. ... código eliminado intencionadamente
32. ...
33. }


Analicemos un poco este código para darnos cuenta donde está realmente el fallo encontrado. Si os fijáis en la primera sentencia de comparación, en caso de que size sea menor que 3 la función retornará con un error controlado y esto no supondrá a priori ningún problema (siempre que este sea tratado correctamente). Es decir, solo se seguirá ejecutando el código de la función cuando size sea mayor o igual que 3.

Supongamos que size vale 3, en la siguiente instrucción menos como se le resta 2 a size, con lo que pasaría a valer 1. Y en la siguiente instrucción que hace referencia a size, se le vuelve a restar 1, por lo tanto ahora size valdría 0.

Hasta aquí todo correcto, pero ahora viene la parte delicada, que provocará el desbordamiento de tipo entero (Integer overflow/underflow).


Se trata de la siguiente sentencia de comparación:


1.  if (streamDependenceFlag) {
2.         offset += 2;
3.         size -= 2;

4.  }


Recordad que en estos momentos size valdría 0, por lo tanto si se cumple la condición, es decir, si streamDependenceFlag es True, entonces se le restará nuevamente 2 al valor de size, dando como resultado "-2" y como hemos dicho anteriormente, el tipo de datos size_t es un tipo de datos entero sin signo, por lo tanto estaremos intentando almacenar un valor negativo en una variable que solo admite valores positivos, provocándose entonces el desbordamiento.


Ahora bien, ¿qué es lo que haría que se cumpla tal condición? pues si nos fijamos en la línea 10 del código:


1.  unsigned streamDependenceFlag = mData[offset] & 0x80;


Se hace una operación binaria entre mData[offset] y el valor 0x80, por lo tanto si en los datos almacenados en el array mData, y en el índice indicado por 'offset' almacenamos un valor tal que de como resultado TRUE, entonces la condición que provoca el desbordamiento se cumplirá.

La función completa tiene más código, pero es a partir de lo expuesto cuando se produce el verdadero desbordamiento y en las siguientes llamadas a funciones que se hacen en el resto de código, se pasa size como parámetro pero en esta ocasión con un valor del tipo 0xfffffffe

En el caso expuesto, hemos visto una función muy concreta del framework multimedia de Android (Stagefriht), que se encargaría de parsear o analizar archivos MPEG-4 en el caso de que el codec utilizado sea por ejemplo un 'mp4v'. Se trata de una extensión del formato de video MPEG-4 conocida como "Elementary Stream Descriptor" o ESDS para los amigos.


En todo caso, aquí tenéis un pequeño ejemplo con el que jugar para comprobar lo explicado:


unsigned datos[] = {0x01, 0x02, 0x98, 0x04, 0x45};


int Integer_Underflow(size_t offset, size_t size)
{
       if (size < 3)
            return -1;

       size -= 2;
       unsigned flag = datos[offset] & 0x80;
       --size;

       if (flag)
       {
             size -= 2;
       }

       return 0;
}



int main(int argc, char *argv[])
{
       return Integer_Underflow(2, 3);
}

miércoles, 29 de julio de 2015

Android Stagefright Exploit / POC (II)

Pero ¿Qué vectores podemos/debemos seguir para localizar este tipo de vulnerabilidades?


A priori, yo me decantaría principalmente por dos vectores muy distintos y, para los cuales se tendrán que emplear técnicas muy diferentes.


VECTOR de búsqueda 1


Ante todo hay que tener en cuenta que Android es un proyecto Open Source, lo que significa que tenemos acceso a su código fuente. Así, un claro vector de búsqueda sería por esta vía, es decir, analizando el código fuente en busca de aquellos 'Bugs', descuidos y metodologías, técnicas y funciones inseguras utilizadas por los ingenieros del software.

Por tanto, un poco para empezar a buscar es el repositorio del código fuente de Android, el cual podemos encontrar en la siguiente URL:


Como podemos ver en dicho repositorio, la cantidad de código fuente con la que tendremos que lidiar es claramente INMENSA, entonces ¿por qué camino debemos ir? En el caso que nos ocupa sobre StageFright, una vía clara de búsqueda, es la ruta que nos lleva directamente al framework de audio y video nativo del StageFright, el cual está ubicado aquí (para android-5.1.1 r8):


En caso de querer tener acceso al framework de otra reléase, podemos entrar desde esta otra URL:


Por ejemplo, para ir directos al código fuente en C++ de parte de Stagefright podríamos comenzar por aquí:



VECTOR de búsqueda 2

En este caso, como digo, las cosas serán muy diferentes. Ahora no se trata de analizar el código fuente en búsqueda de funciones 'sensibles' o estructuras mal definidas, etc. Aquí de lo que se trata es de utilizar un dispositivo "vivo", es decir, actuar sobre un dispositivo Android en tiempo real.

Nuevamente, en el caso que nos ocupa de StageFright y, en concreto en las vulnerabilidades que hacen referencia a la recepción de MMS, la técnica que se utilizará será la "Fuzzy Data Mining", básicamente el envío de datos mal-formados al dispositivo, con el fin de provocar algún tipo de error.

Está claro que el envío/recepción de mensajes de tipo MMS debe regirse por algún tipo de estándar con su correspondiente especificación, la cual se encarga de definir entre otras cosas las características, formatos de los datos, de las cabeceras, etc. que deben tener dichos mensajes.

Y entre otras cosas, algo que diferencia a un MMS de un SMS común, es que el MMS precisamente soporta el envío/recepción de archivos multimedia (audio y video). Archivos que pueden ser de diversos formatos y, los cuales nuevamente se deben regir por una especificación de formato, en la mayoría de los casos claramente definida.

Por ejemplo, para que os hagáis una idea StageFright, a priori es capaz de identificar las siguientes extensiones de archivos:

".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2", ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac", ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota", ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf", ".avi", ".mpeg", ".mpg", ".awb", ".mpga"

Esto, que de entrada podría no significar gran cosa, ya nos está dando una idea aproximada de la cantidad de CODECs con los que tiene que lidiar Android y su complejo framework multimedia.

Por lo tanto y dicho esto, ¿qué pasaría si en lugar de enviar un MMS como el dispositivo Android espera recibir, le enviamos un MMS mal-formado o erróneo? Pues la respuesta es sencilla, si el software no está correctamente diseñado para la detección de este tipo de situaciones tipo excepciones no controladas y demás, se producirá algún error.

Esos errores serán precisamente los que convertirán en vulnerable al dispositivo, pudiendo permitir la ejecución de código remoto no deseado o mal intencionado.


martes, 28 de julio de 2015

Android Stagefright Exploit / POC (I)

Antes incluso de hablar sobre la existencia o no, de los exploits/POC correspondientes, que sin duda a estas alturas ya los hay, sería interesante saber que es exactamente "Stragefright".

Pues bien, Stragefright es básicamente el motor de reproducción de medios digitales que incorpora Android de forma nativa. Este componente software, incorpora ya una serie de codecs de-facto para la reproducción de la gran mayoría de los formatos multimedia más populares y generalizados.

En el siguiente digrama (cortesía de Google), se puede ver como interactuan las aplicaciones de reproducción o gestión de medios, con el framework multimedia nativo de Android (Stragefright).

Se distinguen las siguientes partes o capas en dicha arquitectura, a saber:

- El framework de aplicación, es donde se encontraría el codigo en si de la aplicación de usuario, la cual, haciendo uso de las APIs correspondientes (android.media) pueden interactuar con el hardware multimedia.

- Binder IPC Proxies, se trata de la capa encargada de facilitar la comunicación entre procesos. Estos proxies, se encuentran alojados en el directorio 'frameworks/av/media/libmedia' y comienzan con la letra 'I'

- Native Multimedia Framework, ya a un nivel nativo, Android proporciona un framework multimedia que hace uso del motor Stragefright para la grabación y reproducción de audio y video. Stragefright ya viene con varios codecs por software, pero además se podrían implementar nuevos codecs hardware a través del estandar de OpenMax.

- OpenMAX Integration Layer (IL), como he mencionado anteriormente, se trata de una estandarización para el uso de codecs multimedia basados en hardware. Digamos que son una especie de componentes o plugins en forma de librería compartida.

Bueno, ahora que ya tenemos una ligera idea sobre que es Stagefright, es momento de hablar sobre el/los bugs que están apareciendo recientemente en los dispositivos Android y, que pueden permitir a determinadas personas sin escrúpulos, acceder a dichos dispositivos para tomar el control de los mismos, haciendo uso de la cámara de fotos/video, el micrófono, tarjeta SD, y demás información que pulula por nuestros cacharros.

Según parece, ya hay una serie de identificadores asignados a tales vulnerabilidades:

CVE-2015-1538, CVE-2015-1539, CVE-2015-3824, CVE-2015-3826, CVE-2015-3827, CVE-2015-3828, CVE-2015-3829

Y volviendo al hilo del título, ¿cuánto pensáis que van a tardar en aparecer los correspondientes exploits?

Si como dicen con enviar un MMS manipulado adecuadamente, ya es posible conseguir la ejecución de código remoto y, como es lógico con los privilegios de ejecución de los procesos de StageFriht, parece bastante lógico pensar que los problemas estén en los codecs oportunos. ¿Será una decodificación de cabeceras? ¿Desbordamientos? o por ejemplo ¿Guardará Stagefriht algún tipo de archivo temporal con parte de los datos extraídos, para proceder posteriormente a su interpretación?

Yo por el momento, ya dispongo de un dispositivo Android listo para ser investigado.

jueves, 11 de junio de 2015

¿Qué tiene dentro? El Condensador Electrolítico

Aquí uno de esos post que sirven para saciar la curiosidad de los "mente-inquieta", que gustan de conocer las interioridades de todo aquello que les rodea.

En esta ocasión algo pequeñito y sencillo a la vez, pero de vital importancia en la tecnología que nos acompaña cada a día en nuestro entorno, el condensador electrolítico.









Diagrama de Transición para números en Notación Científica (1.5e-10)

Si en el anterior post mostraba la expresión regular necesaria para representar patrones correspondientes a números expresados en notación científica, en esta ocasión quiero mostrar como sería el diagrama de transición necesario, para que un autómata sea capaz de analizarlo.

En la imagen siguiente podéis ver tanto el diagrama de transición como la expresión regular correspondiente:


Podríamos expresarlo con alguna variante, pero para entender el concepto general del diagrama de transición creo que es más que suficiente.

Expresión Regular para números en Notación Científica (1.5e-10)

No cabe duda que las expresiones regulares tienen un potencial de mucho valor a la hora de analizar textos, ya sea para marcado, búsqueda de patrones, o incluso la programación de un compilador, un analizador de frases, de expresiones matemáticas, etc.
 
En esta ocasión he tenido que echar mano de ellas para el análisis de textos matemáticos en los cuales aparecen números en Notación Científica (con exponentes del tipo 1.5E-10). Pues bien, una expresión regular que me está funcionando bastante bien es la siguiente:
 
[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?
 

Esta expresión regular se puede descomponer en los siguientes bloques, para poder interpretarla con mayor facilidad: 
  • El primer bloque [-+]? está indicando que el número podría estar precedido opcionalmente de un signo - o un signo +
  • El segundo bloque [0-9]* indica que podría aparecer un número de 0 o más dígitos del 0 al 9 
  • El tercer bloque indica que también de manera opcional podría aparecer un punto decimal
  • El cuarto bloque sugiere la aparición de un número de 1 o más dígitos del 0 al 9 
  • El quinto bloque es precisamente el que indicaría la parte exponencial del número y podría ser totalmente opcional.
Este último bloque se descompone en los siguiente sub-bloques:
  • Un primer bloque que indica la aparición de la letra 'e' o 'E' de exponente.
  • Un segundo bloque que indica la aparición opcional del signo '-' o el signo '+'
  • Un tercer bloque que indica la aparición de un número de 1 o más dígitos del 0 al 9.