Thursday, February 12, 2015

(^Exploiting)\s*(CVE-2015-0318)\s*(in)\s*(Flash$)

Posted by Mark Brand, Irregular Expressionist

So; issue 199/PSIRT-3161/CVE-2015-0318. Quick summary - it’s a bug in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PCRE regex engine as used in Flash. (Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 published version of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 avmplus code is significantly out of date; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are a number of ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r vulnerabilities present that have already been fixed by Adobe; so auditing it can be a little frustrating!).

Spoiler: it’s exploitable. Grab cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issues page and read along.

So, for a little bit of background - PCRE is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 regular expression library used in Flash to back cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir implementation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RegExp object. PCRE is a complex library, that supports several different operating modes, including a JIT. However, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mode that is used by Flash is one in which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 regex string is parsed and compiled to an internal bytecode (‘PCRE bytecode’) that is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n interpreted in order to match cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 regex; so for vulnerabilities in Flash we are mainly interested in vulnerabilities eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 regex parsing, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bytecode compilation or during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interpretation. This particular vulnerability results from an issue in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bytecode compilation; and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 root cause of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue can be found in this code, starting at line 743:

   /* For \c, a following letter is upper-cased; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 0x40 bit is flipped.
   This coding is ASCII-specific, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 whole concept of \cx is
   ASCII-specific. (However, an EBCDIC equivalent has now been added.) */

   case 'c':     <---- There’s no check to see if we’re in UTF8 mode
   c = *(++ptr); <---- This could be part of a multibyte unicode character
   if (c == 0)
     {
     *errorcodeptr = ERR2;
     break;
     }

#ifndef EBCDIC  /* ASCII coding */
   if (c >= 'a' && c <= 'z') c -= 32;
   c ^= 0x40;
#else           /* EBCDIC coding */
   if (c >= 'a' && c <= 'z') c += 64;
   c ^= 0xC0;
#endif
   break;


Below is what happens when we compile a regex that combines cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 \c escape sequence (which is intended to match a single ASCII character) with a multibyte UTF-8 character. A simple trigger for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug is ‘\\c\xd0\x80+’, below.

\cЀ+

This will compile to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following bytecode:

0000 5d0009      93 BRA              [9]
0003 1bc290      27 CHAR             ['\xc2\x90']
0006 201b        32 PLUS             ['\x1b']
0008 80         128 INVALID
0009 540009      84 KET              [9]
000c 00           0 END   

So clearly something has gone wrong… The question is now how to leverage this invalid bytecode to get code execution. Unfortunately, if we simply execute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 expression, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 behaviour on encountering an invalid opcode is simply to terminate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 match as a failure; not a very exciting possibility.

There are however a number of ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r functions in pcre_compile.cpp that give us some additional options; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one that I chose to use was find_brackets, as this iterates through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current bytecode, has a permissive default case, and is used to locate (and patch in an offset to) a numbered group; so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 possibility to perhaps cause some interesting memory corruption or get execution of PCRE bytecode somewhere ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 legitimate bytecode.

This turns out to be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case; by adding a back-reference to our regular expression,

\cЀ+(?1)

we can hit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following line of code with ‘c’ set to our invalid opcode, 0x80:

/* Add in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fixed length from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 table */
code += _pcre_OP_lengths[c];

Now, _pcre_OP_lengths is a global array, and 0x80 indexes a little way past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array, conveniently this is (on Windows and Linux, at least) located in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash binary directly before an array of strings used for internationalisation. In every version of Flash I looked at, this will get us a length of 110 (which is significantly larger than any valid bytecode op length), so if we can groom cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap, we can hop cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code pointer out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocated bytecode buffer and into data we control. We cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n just need to arrange to have find_bracket locate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bytecode pattern it’s hunting for in that buffer, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n it will helpfully link our malicious bytecode into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 regex program, ready to be executed.

We run into a slight hiccup when we want to actually execute this regex; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bytecode interpreter will exit when encountering an invalid opcode. However, we can get around this fairly easily by wrapping our broken bytecode in an optional group;

(\cЀ+)?(?2)

With an appropriate groom with buffers containing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bytecode for group 2, we get a successful compilation to:

LEGITIMATE HEAP BUFFER
0000 5d001b      93 BRA              [27]
0003 66         102 BRAZERO          
0004 5e000b0001  94 CBRA             [11, 1]
0009 1bc290      27 CHAR             ['\xc2\x90']
000c 201b        32 PLUS             ['\x1b']
000e 80         128 INVALID          
000f 54000b      84 KET              [11]
0012 5c0006      92 ONCE             [6]
0015 510083      81 RECURSE          [131]    <---- this 131 is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bytecode index to recurse to (131 == 0x83, at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start of our groomed heap buffer)
0018 540006      84 KET              [6]
001b 54001b      84 KET              [27]
001e 00           0 END              
GROOMED HEAP BUFFER
0083 5e00880002  94 CBRA             [136, 2]
0088 540088      84 KET              [136]

When we execute this regex, things look good for us, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 execution path we’ll take is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:

0000 5d001b      93 BRA              [27]
0003 66         102 BRAZERO          
0004 5e000b0001  94 CBRA             [11, 1]
0009 1bc290      27 CHAR             ['\xc2\x90']   <---- Fail, backtrack
0015 510083      81 RECURSE          [131]          
0083 5e00880002  94 CBRA             [136, 2]       <---- Now executing inside our groomed heap buffer
0088 540088      84 KET              [136]
0018 540006      84 KET              [6]
001b 54001b      84 KET              [27]
001e 00           0 END

So, at this point we can happily insert arbitrary regex bytecode in between our CBRA and KET in our groomed heap buffer.

The PCRE bytecode interpreter is surprisingly robust; and it took quite a while before I found a useful primitive for corrupting memory from this point. The majority of memory accesses from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interpreter are validated; if not perfectly (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are a lot of opportunities for out-of-bounds reads, or similar, but at this point we really need a write primitive) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n sufficiently to prevent an out-of-bounds write that we can leverage furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r.

There is, however, an interesting piece of code; in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 handling for CBRA, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a bad assumption made about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 group number (second parameter of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 opcode). Code snippet below (from pcre_exec.cpp, beautified and some debug code removed).

case OP_CBRA:
case OP_SCBRA:
   number = GET2(ecode, 1 + LINK_SIZE); <---- we control number
   offset = number << 1;                <---- we control offset

   if (offset < md->offset_max)         <---- bounds check that offset within offset_vector
   {
       save_offset3       = md->offset_vector[md->offset_end - number]; <---- we control number, so if number is 0, we index at md->offset_end, which is one past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array

       save_capture_last  = md->capture_last;

       if (ES3_Compatible_Behavior)   // clear all matches for groups > than this one
       {                              //  (we only really need to reset all enclosed groups, but
                                      //  covering all groups > this is harmless because
                                      //  we interpret from left to right)

           savedElems = (offset_top > offset ? offset_top - offset : 2);

           if (savedElems > frame->XoffsetStackSaveMax)
           {
               if (frame->XoffsetStackSave != frame->XoffsetStackSaveStg)
               {
                   (pcre_free)(frame->XoffsetStackSave);
               }

               frame->XoffsetStackSave = (int *)(pcre_malloc)(savedElems * sizeof(int));

               if (frame->XoffsetStackSave == NULL)
               {
                   RRETURN(PCRE_ERROR_NOMEMORY);
               }

               frame->XoffsetStackSaveMax = savedElems;
           }

           VMPI_memcpy(offsetStackSave, md->offset_vector + offset, (savedElems * sizeof(int)));

           for (int resetOffset = offset + 2; resetOffset < offset_top; resetOffset++)
           {
               md->offset_vector[resetOffset] = -1;
           }
       }
       else
       {
           offsetStackSave[1] = md->offset_vector[offset];
           offsetStackSave[2] = md->offset_vector[offset + 1];
           savedElems         = 0;
       }

       md->offset_vector[md->offset_end - number] = eptr - md->start_subject;  <---- even better, we write cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 match cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re; this is becoming interesting.


So, we can write some data we control one dword past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of offset_vector. As it happens, normally offset_vector is a stack buffer allocated in RegExpObject.cpp.

ArrayObject* RegExpObject::_exec(Stringp subject,
                               StIndexableUTF8String& utf8Subject,
                               int startIndex,
                               int& matchIndex,
                               int& matchLen)
{
   AvmAssert(subject != NULL);

   int ovector[OVECTOR_SIZE];
   int results;
   int subjectLength = utf8Subject.length();


This is of little interest though; it’s unlikely that our single dword write off cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of that buffer is going to achieve anything useful - I didn’t check, but modern compiler mitigations, such as variable reordering and stack cookies should prevent this path from being exploitable, and we have an easier option available to us. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case where we have more capturing groups in our regex than will fit in this buffer, PCRE will allocate a suitable buffer on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap when it executes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 expression.

/* If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 expression has got more back references than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 offsets supplied can
hold, we get a temporary chunk of working store to use during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 matching.
Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, we can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vector supplied, rounding down its size to a multiple
of 3. */

ocount = offsetcount - (offsetcount % 3);

if (re->top_backref > 0 && re->top_backref >= ocount / 3)
{
   ocount = re->top_backref * 3 + 3;
   
   md->offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int));
   if (md->offset_vector == NULL)
   {
       return PCRE_ERROR_NOMEMORY;
   }
   
   using_temporary_offsets = TRUE;
   DPRINTF(("Got memory to hold back references\n"));
}
else
{
   md->offset_vector = offsets;
}

md->offset_end = ocount;
md->offset_max = (2 * ocount) / 3;
md->offset_overflow = FALSE;
md->capture_last = -1;

Excellent, things are coming togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r. We can now write a dword that we mostly control (it can’t really be very big) after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of a heap allocation, as long as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocation is at least larger than 99 * 4 = 396. As we need to write directly after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocation, looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash heap allocator tells us that 504 bytes is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first bucket size that we can match exactly; and we’ll need a md->top_backref == 41 to achieve this. This can simply be achieved by adding a some capturing groups and a back reference.

(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)\41(\cЀ+)?(?43)

Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r issue we’ll hit shortly is that Flash doesn’t validate whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 regex compiled successfully; if our first heap groom failed, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n find_bracket will not find a match for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 group, and compilation will fail. This is annoying when we’re trying to debug our exploit, so we can add a constant match string to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 regex that we can use to test whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 regex compiled successfully.

(c01db33f|(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)\41(\cЀ+)?(?70))

As mentioned above; we’re going to need to have a heap groom to get our bytecode positioned directly after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer used to compile our regex into; to make things simple, we’ll pad our regex so that this buffer is a nice round number for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash heap allocator again; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next available bucket is 576 bytes, and each single character match adds 2 bytes.

(c01db33f|(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)\41AAAAAAAAAAAAAAAAAAAAAAAAAAA(\cЀ*)?(?70))

We need one more modification to make this useful; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value that we are overwriting with is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current match, so we need a way to easily control that. We can just change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first group to match an arbitrary number of a different character, and we’re good to go:

(c01db33f|(B*)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)(A)\41AAAAAAAAAAAAAAAAAAAAAAAAAAA(\cЀ*)?(?70))

NB: in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit code, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 B is replaced by one of a selection of characters - this is because Flash caches (successfully and unsuccessfully) compiled regexes, and if our groom fails we want to actually force a recompilation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 regex.

So, this gets us cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial regex that we’re going to compile as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first stage of our exploit. We’ve figured out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 payload bytecode that we need to trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OOB write, which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:

0000 5e00010046  94 CBRA             [1, 70]
0005 5e00000000  94 CBRA             [0, 0]
000a 6d         109 ACCEPT

The accept is needed since to successfully reach cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 write, we need for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 group with number 0 to be a match; accept will force this with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least messing around required.

Now, it’s entirely cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 write primitive we have would normally be quite annoying; in many situations this would barely be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start of an exploit - while we control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocation that we’re writing past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of it has to be pretty large, which rules out a lot of objects with vtables; and since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value we’re overwriting with is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of our current match, overwriting a pointer would be a mess anyway. Happily, in Flash, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a one-size-fits-all solution to all heap exploitation woes - Vector.. We can allocate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se objects in any size we like (more-or-less), and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first dword is a length field. Once we’ve corrupted that length, we are going to have no problem producing an arbitrary read/write primitive, and getting stable exploitation.

1 - Compile regex

First we allocate a large number of buffers of size 504 (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as our compiled regex) and fill cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m with our exploit bytecode.
_______________________________________________________________________________________
|exploit-bytecode------------|exploit-bytecode------------|exploit-bytecode------------|
````````````````````````````````````````````````````````````````````````````````````````
We cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n free every second buffer, leaving a lot of nicely sized gaps that are too tempting for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash heap allocator to overlook.
_______________________________________________________________________________________
|exploit-bytecode------------|FREE                        |exploit-bytecode------------|
````````````````````````````````````````````````````````````````````````````````````````

So that when we try to compile our regular expression, we’re almost certainly going to end up just where we want to be, with a copy of our exploit bytecode directly after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocated buffer.
_______________________________________________________________________________________
|exploit-bytecode------------|ERCP|metadata|regex-bytecode|exploit-bytecode------------|
````````````````````````````````````````````````````````````````````````````````````````


2 - Execute regex to corrupt vector length

We’re actually going to be a bit more fancy here; since ideally we’d like to have a Vector. with length 0xffffffff so that we can read and write all of memory, we’ll actually make gaps followed by two Vector.’s. These allocations now need to be size 576, as that’s cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of our offset_vector.
_______________________________________________________________________________________
|length|vector---------------|length|vector---------------|length|vector---------------|
````````````````````````````````````````````````````````````````````````````````````````
Like so:
_______________________________________________________________________________________
|FREE                        |length|vector---------------|length|vector---------------|
````````````````````````````````````````````````````````````````````````````````````````
When our regex is executed, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 match will be written one dword past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocated offset_vector, corrupting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length field of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first vector:
_______________________________________________________________________________________
|offset_vector---------------|corrupt|vector--------------|length|vector---------------|
````````````````````````````````````````````````````````````````````````````````````````

We only need to increase cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first vector by 1, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n we can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first vector to completely control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second vector:
_______________________________________________________________________________________
|offset_vector---------------|length+1|vector--------------------|vector---------------|
````````````````````````````````````````````````````````````````````````````````````````
_______________________________________________________________________________________
|offset_vector---------------|length+1|vector---------------|UINT_MAX|vector-----------------------
````````````````````````````````````````````````````````````````````````````````````````

At this point, we have read-write access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire address space of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 running Flash process, and it’s pretty much game over; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only remaining major issue is that we don’t know exactly where our extra-large Vector. is based, so any memory accesses we do are relative to that buffer.

3 - Where is our corrupted Vector?

Conveniently, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PCRE code deterministically frees cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer that was allocated for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 oversized offset vector immediately before returning to actionscript. This means that we can look back behind our vector and grab a freelist pointer from inside that free block.

_______________________________________________________________________________________
|FREE   |ptr|                |length|vector-------------|UINT_MAX|vector---------------|
````````````````````````````````````````````````````````````````````````````````````````

This pointer will point to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next available block, which will most likely be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block following our extra-large vector; we can sanity check this a little, but it’s not really necessary - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block size is large, and this is a pretty safe bet. As we know cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 precise size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap allocations, we can use this to compute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of our extra-large vector, and turn our relative read-write primitive into an absolute read-write.

_______________________________________________________________________________________________________
|FREE   |ptr|                |length|vector-------------|UINT_MAX|vector---------------|FREE|ptr|      
``````````|`````````````````````````````````````````````````````````````````````````````^``````````````
         |_____________________________________________________________________________|

4 - Formalities

The rest of this is really a 101 on exploiting a userland Windows arbitrary read/write; feel free to skip if you get bored...

4 (i) Finding a module

We’ve sort-of bypassed ASLR by locating our Vector object; but we don’t really know where everything is yet; ideally we need a pointer into a loaded module that we can use for code-reuse techniques. One way to get such a pointer would be to spray cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap some more with objects containing pointers, but we don’t need to do this today.

As it happens, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a nice structure at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start of every page used by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash FixedAlloc allocator that contains a pointer that eventually chains to a static instance of a C++ class; this is inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash module, so we can use this to locate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash module in memory. See cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit code…

Once we have a pointer inside a module, we can scan backwards from that pointer, checking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start of each page for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 magic MZ header to locate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module base. It’s cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n just a matter of parsing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PE file format to locate useful imports and byte sequences that we can use in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final stage of our exploit.

4 (ii) Something to overwrite

Again, we’ve sort-of bypassed ASLR… If this was a linux exploit, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re was no RELRO, we could just overwrite a function pointer in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GOT section like in Chris’ previous blog post; on Windows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s not quite such a convenient technique. With some reverse engineering of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash binary, we’d probably find a global function pointer somewhere that we could overwrite, but it’s easier to arrange for something on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap.

If we create anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r ActionScript class, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n when we instantiate this class, this will be an allocation on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap, and it will contain a vtable pointer that’s used to resolve method invocations on that object. We can make a class with some readily signaturable bytes in it, and make it easy to find; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n by walking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap structures we can safely locate this class instance without risk of touching unmapped memory and crashing.

4 (iii) Getting control of execution

An interesting and useful feature of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash JIT is that if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 arguments to a method invocation can be determined to be simple native types, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y will actually be pushed onto cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native stack (as in a normal, native function call). This means that by overwriting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function pointer for a function with a lot of uint parameters, we can control a large block of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native stack when that function is called, letting us ROP directly on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 legitimate program stack.

All we need to do is make a call to VirtualProtect to mark cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 page with our Vector in it as executable, and we can put our shellcode in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re and just jump to that buffer.

A slight trick is that by arranging for lots of stack space to be used by nonsense arguments; we can make enough stack space so that when VirtualProtect is called, it won’t damage cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real Flash stack frames (which are both above and below our fake stack frames…).

4 (iv) Returning control of execution

So, we’ve successfully redirected execution - all that remains is to return control of execution to Flash, and tie up a few loose ends. Taking stock of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 damage that we’ve done to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process; if everything went well, we’ve only corrupted 3 dwords of process memory that are actually being used by Flash, so it should be fairly easy to clean up and continue execution:

  1. The length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first vector was increased by 1
  2. The length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second vector was increased to UINT_MAX
  3. The function pointer for our method

1 is cleaned up immediately by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit once we have overwritten cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second vector; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s no need to leave that as is. 2 needs to be cleaned up, since when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vector is free’d Flash will try to clear all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory… This can be done trivially from actionscript though, once we no longer need cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vector; in fact we fix this before getting control of execution, since we can be sure that 3 will never be used again, and so don’t need to fix it.

This means that if we can just line up things right, we can just return back as though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method invocation succeeded, and Flash will keep running as though everything is just fine. Practically, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 simplest way to achieve this was to fix up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack frame to contain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct function pointer, and jump to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual method implementation; so essentially our ROP payload and shellcode act as a transparent function hook applied to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method.

Monday, February 9, 2015

A Token’s Tale

Posted by James Forshaw currently impersonating NT AUTHORITY\SYSTEM.


Much as I enjoy cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process of vulnerability research sometimes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a significant disparity between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 difficulty of finding a vulnerability and exploiting it. The Project Zero blog contains numerous examples of complex exploits for seemingly trivial vulnerabilities. You might wonder why we’d go to this level of effort to prove exploitability, surely we don’t need to do so? Hopefully by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of this blog post you’ll have a better understanding of why it’s often cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case we spend a significant effort to demonstrate a security issue by developing a working proof of concept.

Our primary target for a PoC is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r benefits for developing one. A customer of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor’s system can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC to test whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’re vulnerable to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue and ensure any patch has been correctly applied. And cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security industry can use it to develop mitigations and signatures for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability even if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor is not willing or able to patch. Without cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC being made available only people who reverse engineer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch are likely to know about it, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y might not have your best interests in mind.

I don’t want this blog post to get bogged down in too much technical detail about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug (CVE-2015-0002 for reference). Instead I’m going to focus on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process of taking that relatively simple vulnerability, determining exploitability and developing a PoC. This PoC should be sufficient for a vendor to make a reasonable assessment of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 presented vulnerability to minimize cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir triage efforts. I’ll also explain my rationale for taking various shortcuts in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC development and why it has to be so.

Reporting a Vulnerability

One of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 biggest issues with vulnerability research on closed or proprietary systems is dealing with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual reporting process to get a vulnerability fixed. This is especially cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case in complex or non-obvious vulnerabilities. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system is open source, I could develop a patch, submit it and it stands a chance of getting fixed. For a closed source system I will have to go through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process of reporting. To understand this better let’s think about what a typical large vendor might need to do when receiving external security vulnerability reports.

Vendor Vulnerability Response.png

This is a really simplified view on vulnerability response handling but it’s sufficient to explain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 principles. For a company which develops cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 majority of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir software internally I would have little influence over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patching cycle, but I can make a difference in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 triage cycle. The easier I can make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor’s life cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shorter cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 triage cycle can be and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 quicker we can get a patch released. Everyone wins, except hopefully cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 people who might be using this vulnerability already. Don’t forget just because I didn’t know about this vulnerability before doesn’t mean it isn’t already known about.

In an ideal vulnerability research world (i.e. one in which I have to do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least amount of non-research work) if I find a bug all I’d need to do is write up some quick notes about it, send it to a vendor, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’ll understand cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’ll immediately move heaven and earth to develop cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch, job done. Of course it doesn’t work that way, sometimes just getting a vendor to recognize cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s even a security issue is an important first step. There can be a significant barrier between moving from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 triage cycle to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch cycle, especially as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’re usually separate entities inside a company. To provide for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best chance possible I’ll do two things:

  1. Put togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r a report of sufficient detail so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor understands cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability
  2. Develop a PoC which unequivocally demonstrates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security impact

Writing up a Report

Writing up a report for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor is pretty crucial to getting an issue fixed, although it isn’t sufficient in many cases. You can imagine if I wrote something like, “Bug in ahcache.sys, fixit, *lol*” that doesn’t really help cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor much. At cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 very least I’d want to provide some context such as what systems cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability affects (and doesn’t affect), what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impact of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability is (to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best of my knowledge) and what area of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue resides.

Why wouldn’t just cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 report be sufficient? Think about how a large modern software product is developed. It’s likely developed between a team of people who might work on individual parts. Depending on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 age of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerable code cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original developer might have moved on to ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r projects, left cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 company entirely or been hit by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number 42 bus. Even if it’s relatively recent code written by a single person who’s still around to talk to it doesn’t mean cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y remember how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code works. Anyone who’s developed software of any size will have come across code cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y wrote, a month, week or even a day ago and wondered how it works. There’s a real possibility that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security researcher who’s spent time going through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 executable instruction by instruction might know it better than anyone in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 world.

Also you can think about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 report in a scientific sense, it’s your vulnerability hypocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365sis. Some vulnerabilities can be proven, for example a buffer overflow can typically be proven macá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365matically, placing 10 things into space for 5 doesn’t work. But in many cases cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s nothing better than empirical proof of exploitability. If done right it can be experimentally validated by both cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 reporter and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor, this is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of a proof-of-concept. Correctly developed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor can observe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 effects of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 experiment, converting my hypocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365sis to a cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ory which no-one can disprove.

Proving Exploitability through Experimentation

So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hypocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365sis posits that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability has a real-world security impact, we’ll prove it objectively using our PoC. In order to do this we need to provide cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor not just with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mechanism to prove that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability is real but also clear observations that can be made and why those observations constitute a security issue.

What observations need to be made depend on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type of vulnerability. For memory corruption vulnerabilities it might be sufficient to demonstrate an application crashing in response to certain input. This isn’t always cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case, some memory corruptions don’t provide cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker any useful control. Therefore demonstrating control over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current execution flow, such as controlling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 EIP register is usually cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ideal.

For logical vulnerabilities it might be more nuanced, such as you can write a file to a location you shouldn’t be able to or cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 calculator application ends up running with elevated privileges. There’s no one-size-fits-all approach, however at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 very least you want to demonstrate some security impact which can be observed objectively.

The thing to understand is I’m not developing a PoC for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 purposes of being a useful exploit (from an attacker perspective) but to prove it’s a security issue to a sufficient level of confidence that it will get fixed. Unfortunately it isn’t always easy to separate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se two aspects and sometimes without demonstrating local privilege escalation or remote code execution it isn’t taken as seriously as it should be.

Developing a Proof of Concept

Now let’s go into some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 challenges I faced in developing a PoC for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ahcache vulnerability I identified. Let’s not forget cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a trade off between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time spent developing a PoC and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chance of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability being fixed. If I don’t spend enough time to develop a working PoC cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor could turn around and not fix cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability, on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r hand cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 more time I spend cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 longer this vulnerability exists which is potentially as bad for users.

Vulnerability Technical Details

Having a bit of understanding of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability will help us frame cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 discussion later. You can view cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue here with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attached PoC that I sent to Microsoft. The vulnerability exists in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ahcache.sys driver which was introduced in Windows 8.1 but in essence this driver implements cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows native system call NtApphelpCacheControl. This system call handles a local cache for application compatibility information which is used to correct application behaviour on newer versions of Windows. You can read more about application compatibility here.

Some operations of this system call are privileged so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 driver does a check of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current calling application to ensure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y have administrator privileges. This is done in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function AhcVerifyAdminContext which looks something like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following code:

BOOLEAN AhcVerifyAdminContext()
{
   BOOLEAN CopyOnOpen;
   BOOLEAN EffectiveOnly;
   SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;

   PACCESS_TOKEN token = PsReferenceImpersonationToken(
           NtCurrentThread(),
           &CopyOnOpen,
           &EffectiveOnly,
           &ImpersonationLevel);
   if (token == NULL) {
       token = PsReferencePrimaryToken(NtCurrentProcess());
   }
   PSID user = GetTokenUser(token);

   if(RtlEqualSid(user, LocalSystemSid) || SeTokenIsAdmin(token)) {
       return TRUE;
   }

   return FALSE;
}

This code queries to see if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current thread is impersonating anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r user. Windows allows a thread to pretend to be someone else on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system so that security operations can be correctly evaluated. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread is impersonating a pointer to an access token is returned. If NULL is returned from PsReferenceImpersonationToken cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code queries for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current process’ access token. Finally cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code checks whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access token’s user is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 local system user or cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token is a member of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Administrators group. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function returns TRUE cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 privileged operation is allowed to go ahead.

This all seems fine, so what’s cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue? While full impersonation is a privileged operation limited to users which have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impersonate privilege in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir token, a normal user without cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 privilege can impersonate ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r users for non-security related functions. The kernel differentiates between privileged and unprivileged impersonation by assigning a security level to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token when impersonation is enabled. To understand cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s only two levels of interest, SecurityImpersonation which means cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impersonation is privileged and SecurityIdentification which is unprivileged.

If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token is assigned SecurityIdentification only operations such as querying for token information, such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token’s user is allowed. If you try and open a secured resource such as a file cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel will deny access. This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying vulnerability, if you look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PsReferenceImpersonationToken returns a copy of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security level assigned to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token, however cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code fails to verify it’s at SecurityImpersonation level. This means a normal user, who was able to get hold of a Local System access token could impersonate at SecurityIdentification and still pass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check as querying for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user is permitted.

Proving Trivial Exploitation

Exploiting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug requires capturing a Local System access token, impersonating it and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call with appropriate parameters. This must be achievable from normal user privilege ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise it isn’t a security vulnerability. The system call is undocumented so if we wanted to take a shortcut could we just demonstrate that we can capture cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token and leave it at that?

Well not really, what this PoC would demonstrate is that something which is documented as possible is indeed possible. Namely that it’s possible from a normal user to capture cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token and impersonate it, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impersonation system is designed this would not cause a security issue. I knew already that COM supports impersonation, that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a number of complex system privileged services (for example BITS) we can communicate with as a normal user that we could convince to communicate back to our application in order to perform cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impersonation. This wouldn’t demonstrate that we can even reach cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerable AhcVerifyAdminContext method in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel let alone successfully bypass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check.

So starts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 long process of reverse engineering to work out how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call works and what parameters you need to pass to get it to do something useful. There’s some existing work from ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r researchers (such as this) but certainly nothing concrete to take forward. The system call supports a number of different operations, it turned out that not all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 operations needed complex parameters. For example cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AppHelpNotifyStart and AppHelpNotifyStop operations could be easily called, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y relied on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AhcVerifyAdminContext function. I could now produce a PoC which we can verify bypasses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check by observing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call’s return code.

BOOL IsSecurityVulnerability() {
ImpersonateLocalSystem();

NTSTATUS status = NtApphelpCacheControl(AppHelpNotifyStop, NULL);

return status != STATUS_ACCESS_DENIED;
}

Is this sufficient to prove exploitability? History has taught me no, for example this issue has almost cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact same sort of operation, namely you can bypass an administrator check through impersonation. In this case I couldn’t produce sufficient evidence that it was exploitable for anything ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than information disclosure. So in turn it was not fixed, even though it was effectively a security issue. To give ourselves cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best chance of proving exploitability we need to spend more time on this PoC.

Improving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Proof-of-Concept

In order to improve upon cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first PoC I would need to get a better understanding of what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call is doing. The application compatibility cache is used to store cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lookup data from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application compatibility database. This database contains rules which tell cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application compatibility system what executables to apply “shims” to in order implement custom behaviours, such as lying about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 operating system’s version number to circumvent an incorrect check. The lookup is made every time a process is created, if a suitable matching entry is found it’ll be applied to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process. The new process will cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n lookup cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shim data it needs to apply from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 database.

Application Compatibility no cache.png
As this occurs every time a new process is created cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a significant performance impact in going to database file every time. The cache is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re to reduce this impact, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 database lookup can be added to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cache. If that executable is created later cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cached lookup can quickly eliminate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 expensive database lookup and eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r apply a set of shims or not.

Application Compatibility (1).png

Therefore we should be able to cache an existing lookup and apply it to an arbitrary executable. So I spent some time working out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 format of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parameters to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call in order to add my own cached lookup. The resulting structure for Windows 8.1 32 bit looked like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:

struct ApphelpCacheControlData {
       BYTE           unk0[0x98];
       DWORD          query_flags;
       DWORD          cache_flags;
       HANDLE         file_handle;
       HANDLE         process_handle;
       UNICODE_STRING file_name;
       UNICODE_STRING package_name;
       DWORD          buf_len;
       LPVOID         buffer;
       BYTE           unkC0[0x2C];
       UNICODE_STRING module_name;
       BYTE           unkF4[0x14];
};

You can see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s an awful lot of unknown parts in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 structure. This causes a problem if you were to apply this to Windows 7 (which has a slightly different structure) or 64 bit (which has a different sized structure) but for our purposes it doesn’t matter. We’re not supposed to be writing code to exploit all versions of Windows, all we need to do is prove cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security issue to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor. As long as you inform cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC limitations (and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y pay attention to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m) we can do this. The vendor’s still better placed to determine if this PoC proves exploitability across versions of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OS, it’s cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir product after all.

So I could now add an arbitrary cached entry but what can we actually add? I could only add an entry which would have been cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result of an existing lookup. You could modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 database to do something like patch running code (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application compatibility system is also used for hotfixes) but that would require administrator privileges. So I needed an existing shim to repurpose.

I built a copy of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SDB explorer tool (available from here) so that I could dump cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 existing database looking for any useful existing shim. I found that for 32 bit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a shim which will cause a process to start cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 executable regsvr32.exe passing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original command line. This tool will load a DLL passed on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command line and execute specific exported methods, if we could control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command line of a privileged process we could redirect it and elevate privileges.

AppCompat Regsvr32 (3).png
This again limits cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC to only 32 bit processes but that’s fine. The final step, and what caused a lot of confusion was what process to choose to redirect. I could have spent a lot of time investigating ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r ways of achieving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 requirement of starting a process where I control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command line. I already knew one way of doing it, UAC auto elevation. Auto elevation is a feature added to Windows 7 to reduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number of UAC dialogs a typical user sees. The OS defines a fixed list of allowed auto elevating applications, when UAC is at it’s default setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n requests to elevate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se applications do not show a dialog when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user’s an administrator. I can abuse this by applying a cache entry for an existing auto elevating application (in this case I chose ComputerDefaults.exe) and requesting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application runs elevated. This elevated application redirects to regsvr32 passing our fully controlled command line, regsvr32 loads my DLL and we’ve now got code executing with elevated privileges.

The PoC didn’t give someone anything cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y couldn’t already do through various ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r mechanisms (such as this metasploit module) but it was never meant to. It sufficiently demonstrated cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue by providing an observable result (arbitrary code running as an administrator), from this Microsoft were able to reproduce it and fix it.

Final Bit of Fun


As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re was some confusion on whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r this was only a UAC bypass I decided to spend a little time to develop a new PoC which gets local system privileges without any reliance on UAC. Sometimes I enjoy writing exploits, if only to prove that it can be done. To convert cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original PoC to one which gets local system privileges I need a different application to redirect. I decided cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most likely target was a registered scheduled task as you can sometimes pass arbitrary arguments to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 task handler process. So we’ve got three criteria for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ideal task, a normal user must be able to start it, it must result in a process starting as local system and that process must have an arbitrary command line specified by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user. After a bit of searching I found cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ideal candidate, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows Store Maintenance Task. As we can see if runs as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 local system user.

wstask.PNG

We can determine that a normal user can start it by looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 task file’s DACL using a tool such as icacls. Notice cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entry in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following screenshot for NT AUTHORITY\Aucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticated Users with Read and Execute (RX) permissions.

dacl.PNG

Finally we can check whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r a normal user can pass any arguments to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 task by checking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 XML task file. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case of WSTask it uses a custom COM handler, but allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user to specify two command line arguments. This results in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 executable c:\windows\system32\taskhost.exe executing with an arbitrary command line as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 local system user.

task_xml.PNG

It was just a case of modifying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC to add a cache entry for taskhost.exe and start cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 task with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 path to our DLL. This still has a limitation, specifically it only works on 32 bit Windows 8.1 (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s no 32 bit taskhost.exe on 64 bit platforms to redirect). Still I’m sure it can be made to work on 64 bit with a bit more effort. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability is now fixed I’ve made available cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new PoC, it’s attached to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original issue here.

Conclusions

I hope I’ve demonstrated some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 effort a vulnerability researcher would go to in order to ensure a vulnerability will be fixed. It’s ultimately a trade off between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time spent developing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chances of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability being fixed, especially when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability is complex or non-obvious.

In this case I felt I made cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right trade-off. Even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC I sent to Microsoft looked, on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 surface to only be a UAC bypass combined with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 report cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were able to determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 true severity and develop cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch. Of course if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’d pushed back and claimed it was not exploitable cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n I would have developed a more robust PoC. As a furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r demonstration of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 severity I did produce a working exploit which gained local system privileges from a normal user account.

Disclosing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC exploit is of value to aid in a user’s or security company’s mitigation of a public vulnerability. Without a PoC it’s quite difficult to verify that a security issue has been patched or mitigated. It also helps to inform researchers and developers what types of issues to look out for when developing certain security sensitive applications. Bug hunting is not cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sole approach for Project Zero to help secure software, education is just as important.

Project Zero’s mission involves tackling software vulnerabilities, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 development of PoCs can be an important part of our duty to help software vendors or open source projects take informed action to fix vulnerabilities.