[pcre-dev] [Bug 1592] New: PCRE Library Heap overflow Vulner…

Top Page
Delete this message
Author: secresearch
Date:  
To: pcre-dev
Subject: [pcre-dev] [Bug 1592] New: PCRE Library Heap overflow Vulnerability II
------- You are receiving this mail because: -------
You are on the CC list for the bug.

http://bugs.exim.org/show_bug.cgi?id=1592
           Summary: PCRE Library Heap overflow Vulnerability II
           Product: PCRE
           Version: 8.36
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: security
          Priority: high
         Component: Code
        AssignedTo: ph10@???
        ReportedBy: secresearch@???
                CC: pcre-dev@???



PCRE Library Heap overflow Vulnerability II
------------------------------------------------------------------------
Summary

PCRE library is prone to a vulnerability which leads to Heap overflow. Without
enough bound checking inside pcre_compile2(), the heap memory could be
overflowed via a crafted regular expression. Since PCRE library is widely used,
this vulnerability should affect many applications. An attacker may exploit
this issue to execute arbitrary code in the context of the user running the
affected application.
------------------------------------------------------------------------

Description

PCRE is a regular expression C library inspired by the regular expression
capabilities in the Perl programming language. The PCRE library is incorporated
into a number of prominent programs, such as the Adobe Flash, Apache HTTP
Server, Nginx HTTP server,MongoDB,MariaDB,PHP. Latest version of
PCRE is prone to a Heap Overflow vulnerability which could caused by the
following regular expression.

/((?i)(?+1)a(a|b\1))\s+\1/

The simplest PoC is /((?+1)(\1))/

To reproduce the problem, we could use pcretest or pcregrep provide by PCRE
library. For pcretest, simply type the regular expression after the re> . For
pcregrep, run the following command line:
pcregrep.exe "((?+1)(\1))" test.txt



The latest version of PCRE is tested on Windows 7 and Windows 8.1.
Other versions and applications may also be affected.

The version of pcretest and pcregrep is 8.36.(from
http://www.rexegg.com/pcregrep-pcretest.html)

The details about crash attached.

------------------------------------------------------------------------

Analysis:

cd is a compile_data object
cd->start_code is the start of the compiled code and the memory data shows
below:

00824740  83 00 1F 81 00 19 85 00 13 00 06 75 00 02 85 00  ??????.?u.??
00824750  08 00 02 71 00 01 78 00 08 78 00 13 78 00 19 78  ?.?q.?x.?x.?x.?x
00824760  00 1F 00                                         .?.




In the following sniple code, call into the function could_be_empty_branch()

do
  {
  if (could_be_empty_branch(codestart, code, utf, cd, NULL))
    {
    re->flags |= PCRE_MATCH_EMPTY;
    break;
    }
  codestart += GET(codestart, 1);
  }
while (*codestart == OP_ALT);


In function could_be_empty_branch(),

BOOL could_be_empty_branch(const pcre_uchar *code, const pcre_uchar
*endcode,BOOL utf, compile_data *cd, recurse_check *recurses)
{
        ...
        ...
        ...
if (c == OP_RECURSE)
    {
    const pcre_uchar *scode = cd->start_code + GET(code, 1);
    const pcre_uchar *endgroup = scode;
    BOOL empty_branch;


    /* Test for forward reference or uncompleted reference. This is disabled
    when called to scan a completed pattern by setting cd->start_workspace to
    NULL. */


    if (cd->start_workspace != NULL)
      {
      const pcre_uchar *tcode;
      for (tcode = cd->start_workspace; tcode < cd->hwm; tcode += LINK_SIZE)
        if ((int)GET(tcode, 0) == (int)(code + 1 - cd->start_code)) return
TRUE;
      if (GET(scode, 1) == 0) return TRUE;    /* Unclosed */
      }


    /* If the reference is to a completed group, we need to detect whether this
    is a recursive call, as otherwise there will be an infinite loop. If it is
    a recursion, just skip over it. Simple recursions are easily detected. For
    mutual recursions we keep a chain on the stack. */


    do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);


...
}

When the variable c is equal to 0x75(OP_RECURSE), the c points the memoery data
|75 00 02|, and the value of GET(code, 1) is 2. So the pointer scode points
cd->start_code+2(|1F 81 00 19 ...|), endgroup points the memory data |1F 81 00
19 ...|, next run endgroup += GET(endgroup, 1), the value of GET(endgroup, 1)
is 0x81<<8(0x8100), it's too large, it causes that endgroup points a invalid
memory address.
So when reading data from the invalid memory address(*endgroup == OP_ALT), it
causes a read exception.


------------------------------------------------------------------------

Type of Vulnerability & Repercussions:
Heap Overflow
------------------------------------------------------------------------

Affected Software:
Latest version of PCRE library (8.36).
Other versions and applications using it may also be affected.
------------------------------------------------------------------------

Credits:
This vulnerability was discovered by Kai Lu of Fortinet's FortiGuard Labs.


--
Configure bugmail: http://bugs.exim.org/userprefs.cgi?tab=email