New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.
Starred by 2 users
Status: Fixed
Owner:
Email to this user bounced
Closed: Feb 2015
Cc:



Sign in to add a comment
Flash PCRE pcre_compile character class/ims options heap overflow
Project Member Reported by markbrand@google.com, Dec 3 2014 Back to list
An issue exists in the handling of special regex character sets containing the \r or \n characters in conjunction with regex options, which can result in an exploitable heap overflow condition.

An example regex to trigger this issue is the following:

[\D](?i)||

During precompilation, when we compute the space required for the compiled regex, we skip some computation during compilation of the character class [\D] (inside compile_branch) 

(pcre_compile.cpp:3112)

/* Save time by not doing this in the pre-compile phase. */

if (lengthptr == NULL) switch (-c)
  {
  case ESC_d:
  for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit];
  continue;

  case ESC_D:
  for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit];
  inverted_class = TRUE;
  continue;

  … 
  }

/* In the pre-compile phase, just do the recognition. */

else if (c == -ESC_d || c == -ESC_D || c == -ESC_w ||
         c == -ESC_W || c == -ESC_s || c == -ESC_S) continue;


However, later in the same function we use the results of this computation: to set an external options flag, depending on whether this class can contain the \r or \n characters. 

(pcre/pcre_compile.cpp:3555)

/* Remember whether \r or \n are in this class */

if (negate_class)
  {
  if ((classbits[1] & 0x24) != 0x24) cd->external_options |= PCRE_HASCRORLF;
  }
else
  {
  if ((classbits[1] & 0x24) != 0) cd->external_options |= PCRE_HASCRORLF;
  }

This means that during precompilation, cd->external_options is not set to include the PCRE_HASCRORLF flag, but during the actual compilation of the regex, it is.

In compile_regex, the following code is used to emit an OP_OPT for each branch where it is required. 

(beautified extract from pcre_compile.cpp)

if ((options & PCRE_IMS) != oldims)
{
    oldims = options & PCRE_IMS;
    *code++ = OP_OPT;
    *code++ = oldims;
    length += 2;
}
…
if (!compile_branch(&options, … ))
{
… 
}

if (old_external_options != cd->external_options)
    oldims = cd->external_options & PCRE_IMS;

During the first pass, we will not enter the old_external_options case, since cd->external_options has not been changed. 

However during the second pass, we enter this case and set only the PCRE_IMS options - overwriting the updated PCRE_IMS options with the previous options. This doesn’t update the PCRE_HASCRORLF component that is causing us to decide that the options have changed, so for every following branch we will need to emit the OP_OPT and options constant during the first condition to fix the PCRE_IMS options; and so for the regex provided we will emit two bytes more than the original, computed length, overflowing into the following heap buffer.

Changing the check: 

if ((old_external_options & PCRE_IMS) != (cd->external_options & PCRE_IMS))
    oldims = cd->external_options & PCRE_IMS;

seems like a reasonable fix and will prevent the overflow from occurring. A patch is provided (bug.patch) against the github avmplus source code to apply this fix.

However, this will still leave a case where different external_options set during the first and second passes, which may result in other similar issues. It may additionally be necessary to always perform the full character class computation during the precompilation step to ensure that the options are consistent between both passes.

See attached for a .swf demonstrating the issue that has been verified to crash the latest Flash release.

Also attached is another patch which changes the behaviour on detection of an overflow during regex compilation to abort instead of returning an errorcode to Flash, making exploitation of issues similar to this significantly harder.

This bug was found using AFL, written by lcamtuf.

This bug is subject to a 90 day disclosure deadline. If 90 days elapse
without a broadly available patch, then the bug report will automatically
become visible to the public.

 
abort.patch
501 bytes Download
Main.as
276 bytes Download
bug.patch
477 bytes Download
test.swf
792 bytes Download
Comment 1 by cevans@google.com, Dec 4 2014
Labels: Id-3169
Adobe tracking as PSIRT-3169.
Comment 2 by cevans@google.com, Dec 4 2014
Mark noted that the regex to trigger this new bug bears a certain similarity to the regex bug that turned up as an 0-day.

(Details of that 0-day are covered in the paper http://0xfeedface.org/sites/default/files/smashing_the_heap_with_vector_Li.pdf)
Comment 3 by cevans@google.com, Dec 11 2014
Cc: yangding...@gmail.com
cc:ing Yang Dingning, who filed a duplicate issue as https://code.google.com/p/chromium/issues/detail?id=440205
Project Member Comment 4 by markbrand@google.com, Dec 18 2014
Supplied another crash poc to adobe.
psirt-3169.tar.gz
1.8 KB Download
Comment 5 by cevans@google.com, Feb 4 2015
Labels: CVE-2015-0323
Comment 6 by cevans@google.com, Feb 6 2015
Labels: Fixed-2015-Feb-5
Status: Fixed
https://helpx.adobe.com/security/products/flash-player/apsb15-04.html
Comment 7 by cevans@google.com, Feb 12 2015
Labels: -Restrict-View-Commit
Sign in to add a comment