Tuesday, May 22, 2012

Let's focus on two important lessons security history has taught us over the years:

Cryptography relies heavily on random numbers

Implementing cryptography in the right way is not easy

To point out and stress these concepts, I would like to recall a significant episode... Do you remember Debian/OpenSSL Fiasco in 2008? Briefly, due to some modifications to the code, as a side effect, the only "random" value that was used in the PRNG was the current process ID.

This resulted in thePRNG having only 32,767different possible seed values (i.e. the default maximum process ID in Linux systems), that means... a lot of people using the same keys to perform sensitive operations! Or... in other words, as a famous quote by Robert Coveyou says: "random number generation is too important to be left to chance".

So, wouldn't it be nice if we could rely on a high quality standard implementation, that is also performing, reliable under worst case assumptions and secure against software attacks? Yes, of course. Is it possible? Well, lucky day... yes, it is!

The input is taken from an entropy source in order to supply an entropy pool. This pool is then used to provide nondeterministic random numbers that repeatedly seed a Cryptographically Secure PRNG (CSPRNG). Finally, the CSPRNG generates cryptographically secure random numbers.

Intel's DRNG is implemented in hardware on the processor itself, so the entropy source is built-in and is, indeed, a reliable source of high-quality entropy.

The implementation consists of three logical components that correspond to the ones described above, except for the entropy pool that is replaced by a conditioner to improve the performances.

Here is how it is structured:

The entropy source uses thermal noise over the silicon in order to generate streams of random bits, which are then fed to an AES-CBC-MAC based conditioner.

The conditioner combines pairs of blocks of 256 bit from the entropy source and produces one block of 256 bit that will seed the AES-CTR based Deterministic Random Bit Generator (DRBG), that is the hardware CSPRNG.

The DRBG provides a wider number of random bytes available from the hardware module: it generates long streams of bytes from the seed, thus improving the final number of random bytes being produced.

Note that the employment of block ciphers in this contest is not a novelty and it is a common approach in PRNG construction, as modern block ciphers are designed to perform good pseudo-random permutations.Also, the hardware approach adopted by Intel gives additional advantages as the self-contained hardware module is isolated from software attacks on its internal state. How does a user interface to DRNG? A new Intel 64 instruction is introduced: RDRAND. Intel documentation provides all the necessary details to its usage, and also to determine whether the underlying platform supports the instruction (this can be done using the CPUID instruction).Basically, RDRAND can be invoked to obtain a 16-, 32-, or 64-bit random integer value. For example, "RDRAND eax" stores a 32-bit random number in eax.After calling it, the carry flag will either be 1 if a random value was available at the time the RDRAND instruction was executed, or 0 if it wasn't.It seems that Intel is spending a lot of effort in providing crypto dedicated instructions (remember the AES instructions set?) and I hope this trend will bring us many other ones. I think that it will take some years to see this implementation spreading around and become popular, but I also think this may be the solution to many practical problems in everyday cryptography: good work, Intel!

Sunday, May 13, 2012

Recently I noticed an interesting blog entry in contagiodump: it was about a new attack using CVE-2012-0779, that involves a MS Word file named "World Uyghur Congress Invitation.doc". It got me curious, so I started analysing it.

To investigate this file I used FileInsight, it is a simple hex editor that supports OLE format. I searched in the object inside the ObjectPool field and found some useful information.

In particular, you can find this object in the CompObj stream:

and a CLSID in the OCXDATA stream:

Also, in the last screenshot you can notice a JavaScript code listing an url that points to a Flash file:

I searched for this data and discovered that ScriptBridge is the name for AE24FDAE-03C6-11D1-8B76-0080C744F389, and found a nice article, explaining that this CLSID allows the navigation to an url without requiring any user interaction. This is really a powerful feature for malicious purposes!

Now let's focus on "essais.swf". This is a CWS file (a compressed SWF file), but we don't care about this detail as opening it with Trillix will unpack it by default.This file is encoded by DoSwf:

We need to unpack the DoSwf layer in order get to the exploit code, but Trillix fails at decompiling the ActionScript of the packed Flash file. So i searched for other similar Flash files related to this attack, and found "exp.swf" from the jsunpack website.This time Trillix is able to show us the decompiled ActionScript code of the packer:

Here we go, this code shows a xor encryption! Searching for a decryption script I found this one, but it doesn't work as it is.

So, I rearranged the code to make it work with this sample. I only had to use the "decrypt" function properly, and fix the following lines:

byte block_size = (byte) (buffer.get() - 1);

byte key = (byte) (buffer.get() - 1);

int offset = buffer.getInt() - 2;

int length = buffer.getInt() - 2;

Once decrypted and decompressed, the result will be a file containing three concatenated Flash files. The first and third Flash files are from the DoSWF and only contain some metadata and license information. The original malicious Flash file is the second one, and you can find it here (thanks to contagiodump for the link).

This is our final exploit! If we give a look at the code we will find: a shellcode (line 23); a heapspray (line 133); some other stuff including cookies usage, a Rtmp connection and some control on the Windows version.

I'm unable to determine where the vulnerability is: maybe the exploit works only on certain software conditions, or maybe the Rtmp connection is involved in some way, or there's some other missing detail... I don't know! I think that I haven't got enough information to fully understand what happens, but at least here it's an idea of how the attack is structured: more complicated than usual .doc based attacks!

One final detail about the .doc file: as usual a exe file is appended at the end of the OLE, this one is a PE encrypted with a byte-per-byte xor using 0x70 as key (bytes that are 0 or 0x70 are not encrypted).

As I wanted to investigate this vulnerability, I compiled the code in Visual Studio and built the executable.

Then I ran it on a dedicated virtual machine, and…

Yeah… I got the dreaded Blue Screen Of Death! So… it worked :P

This screen gives us useful information; we can read: "PAGE_FAULT_IN_NONPAGED_AREA" and then "STOP: 0x00000050 (0xFF7C98CC, 0x00000000, 0x805D33A5, 0x00000000)".

Now, if we read the documentation we get "Bug Check 0x50: PAGE_FAULT_IN_NONPAGED_AREA". But, what does that mean? Well, in the Windows Kernel, the memory is divided into two kinds: paged memory and nonpaged memory.Basically the difference is that the former can be swapped to the disk while the latter can't. So, the error means that the kernel referenced an invalid memory location within the area reserved to the nonpaged memory.

The parameters of the Bug Check stand respectively for: memory address being referenced ("0xFF7C98CC"); read operation/write operation (0 in this case indicates that read operation mode is selected); address that referenced memory (0x805D33A5, the line of code where the crash happened); reserved (that is not set).

I opened ntkrnlpa.exe with IDA, I loaded the debug symbols and searched for the address that caused the crash, getting this:

we see that the invalid pointer is the first parameter of the function, and it is accessed without being properly validated.Besides, we can see that the memory location being accessed is the same that is passed from the user mode POC code:

UINT c[]={

0x00000000,0x28001500,0xff7c98cc,0x23ffffff

Thus we know that the pointer from user mode is never validated or modified in any way.

From the cross-references we see that the previous function is called by these two functions:

RtlAddAtomToAtomTable(x,x,x)

RtlLookupAtomInAtomTable(x,x,x)

Both these functions don't validate the pointer either. In particular we can see it from the code of the second one:

PAGE:004FC692 push 18h

PAGE:004FC694 push offset dword_4031A0

PAGE:004FC699 call __SEH_prolog

PAGE:004FC69E push [ebp+arg_0]

PAGE:004FC6A1 call _RtlpLockAtomTable@4;

PAGE:004FC6A6 test al, al

PAGE:004FC6A8 jnz short loc_4FC6B4

PAGE:004FC6AA mov eax, 0C000000Dh

PAGE:004FC6AF jmp loc_4FC76C

PAGE:004FC6B4 xor edi, edi

PAGE:004FC6B6 mov [ebp+ms_exc.disabled], edi

PAGE:004FC6B9 lea eax, [ebp+var_20]

PAGE:004FC6BC push eax ; int

PAGE:004FC6BD mov esi, [ebp+PointerCrash]

PAGE:004FC6C0 push esi ; CrashPointer

PAGE:004FC6C1 call _RtlpGetIntegerAtom@8 ;

This function is the one used in the exploit.

Again, from the cross-references we got that this function is called by NtFindAtom, which instead does valid proper validation:

PAGE:00535B81 mov ecx, [ebp+CopyOfCrashPointer]

PAGE:00535B87 lea eax, [ecx+ebx]

PAGE:00535B8A cmp eax, ecx

PAGE:00535B8C jb short Exception

PAGE:00535B8E cmp eax, _MmUserProbeAddress

PAGE:00535B94 jbe short CodeOk

PAGE:00535B96 call _ExRaiseAccessViolation@0 ;

NtFindAtom is a dead end for us, so we switch the analysis on win32k.sys.

From the source code we see the code making a call to a function named NtUserCreateWindowEx. In particular, this code is a home made syscall to a Kernel API in win32k.sys:

mov eax,0x1157

mov edx,7FFE0300h

call dword ptr[edx]

Thus loading win32k.sys in IDA, and searching for this API, we find the function:

This function executes a little bit of code until it gets to the following lines:

.text:BF833E54 mov eax, [ebp+DataBlock]

.text:BF833E57 test eax, 0FFFF0000h

.text:BF833E5C jz short Skip

.text:BF833E5E push dword ptr [eax+8]

.text:BF833E61 call _UserFindAtom@4 ;

DataBlock corresponds to the buffer of data which is stored in the variable "c" in the source code.

The code takes a DWORD at the offset + 8 from such a buffer, and this DWORD is exactly 0xff7c98cc… that is... the vulnerable pointer!

We get into UserFindAtom, and we finally find the missing link:

.text:BF80DA19 mov edi, edi.text:BF80DA1B push ebp.text:BF80DA1C mov ebp, esp.text:BF80DA1E push ecx.text:BF80DA1F and [ebp+NtStatus], 0.text:BF80DA23 lea eax, [ebp+NtStatus].text:BF80DA26 push eax.text:BF80DA27 push [ebp+CrashPointer].text:BF80DA2A push _UserAtomTableHandle.text:BF80DA30 call ds:__imp__RtlLookupAtomInAtomTable@12this is where win32k.sys transfers control to the vulnerable function RtlLookupAtomInAtomTable in ntkrnlpa.exe passing the non-validated pointer.This pointer was set in the exploit code to be 0xff7c98cc, which is a memory address that falls within the kernelspace region, and the problem is that nowhere in this series of calls this pointer is validated to make sure it is accessible.usermode app----|------------------------------------ VxxxUserCreateWindowEx | VUserFindAtom win32k.sys

----|------------------------------------ V ntkrnlpa.exe

RtlLookupAtomInAtomTable | VRtlpGetIntegerAtomThis vulnerability does not seem to be exploitable for code execution, it looks like the security impact is a Denial Of Service.However, we have seen that there are two functions potentially vulnerable:

RtlAddAtomToAtomTable(x,x,x)

RtlLookupAtomInAtomTable(x,x,x)

there are several calls from win32k.sys to them (I found 8 to UserFindAtom and 30 to UserAddAtom). Remember, these two functions won't validate the pointer they take in input, so it is the caller's responsibility to validate it.I had a quick look at all the other functions that call these two, and at a first glance they seem to perform proper validation.Thus I am not going to spend too much time on them, but if anyone wants and finds anything, please let me know!P.S. As it is, the exploit won't work on 64 bit OSes (I tested Windows 7 Professional and Windows 8 Consumer Preview). This may be due to the pointers being 64bit sized, for one thing (or maybe win32k.sys syscall interface is not the same, I haven't checked).