This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Type confusion in partial_setstate and partial_repr leads to control flow hijack
Type: crash Stage: resolved
Components: Extension Modules Versions: Python 3.6, Python 3.5
process
Status: closed Resolution: duplicate
Dependencies: Superseder: Type confusion in partial_setstate and partial_call leads to memory corruption
View: 25945
Assigned To: Nosy List: Ned Williamson, martin.panter, serhiy.storchaka
Priority: normal Keywords:

Created on 2015-12-25 04:12 by Ned Williamson, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
partialpoc.py Ned Williamson, 2015-12-25 04:12
Messages (4)
msg256975 - (view) Author: Ned Williamson (Ned Williamson) Date: 2015-12-25 04:12
static PyObject *
partial_setstate(partialobject *pto, PyObject *state)
{
    PyObject *fn, *fnargs, *kw, *dict;
    if (!PyArg_ParseTuple(state, "OOOO",
                          &fn, &fnargs, &kw, &dict))
        return NULL;
    Py_XDECREF(pto->fn);
    Py_XDECREF(pto->args);
    Py_XDECREF(pto->kw);
    Py_XDECREF(pto->dict);
    pto->fn = fn;
    pto->args = fnargs; //we control pto->args here

`partial_setstate` performs no checks on the objects
it is passed as an argument.

static PyObject *
partial_repr(partialobject *pto)
{
    PyObject *result;
    PyObject *arglist;
    PyObject *tmp;
    Py_ssize_t i, n;
    arglist = PyUnicode_FromString("");
    if (arglist == NULL) {
        return NULL;
    }
    /* Pack positional arguments */
    assert (PyTuple_Check(pto->args)); //not compiled in release build
    n = PyTuple_GET_SIZE(pto->args);
    for (i = 0; i < n; i++) {
        tmp = PyUnicode_FromFormat("%U, %R", arglist,
                                   PyTuple_GET_ITEM(pto->args, i));

In partial_repr, `pto->args` is assumed to be a tuple and
unsafe functions `PyTuple_GET_SIZE` and `PyTuple_GET_ITEM`
are called on `pto->args`. This bug is particularly bad
because `PyUnicode_FromFormat` will call the object's repr
function. In this case, the attacker gains complete control
over the program counter.

vagrant@vagrant-ubuntu-wily-64:/vagrant/Python-3.5.1$ gdb -q ./python.exe
...
(gdb) r partialpoc.py
Starting program: /vagrant/Python-3.5.1/python.exe partialpoc.py
...
Program received signal SIGSEGV, Segmentation fault.
0x00000000004851f6 in PyObject_Repr (v=0x972c90) at Objects/object.c:482
482	    res = (*v->ob_type->tp_repr)(v);
(gdb) i r
rax            0x4141414141414141	4702111234474983745
rbx            0x972c90	9907344
rcx            0x52	82
rdx            0x7ffff7026718	140737337517848
rsi            0x0	0
rdi            0x972c90	9907344
rbp            0x6666666666666667	0x6666666666666667
rsp            0x7fffffffdb60	0x7fffffffdb60
r8             0x0	0
r9             0x6049a8	6310312
r10            0xffffffffffffffff	-1
r11            0xffffffffffffffff	-1
r12            0x7fffffffffffffff	9223372036854775807
r13            0x7fffffffdbe0	140737488346080
r14            0x6049a7	6310311
r15            0x0	0
rip            0x4851f6	0x4851f6 <PyObject_Repr+38>
eflags         0x10206	[ PF IF RF ]
cs             0x33	51
ss             0x2b	43
ds             0x0	0
es             0x0	0
fs             0x0	0
gs             0x0	0
(gdb) x/3i $pc
=> 0x4851f6 <PyObject_Repr+38>:	callq  *%rax
   0x4851f8 <PyObject_Repr+40>:	test   %rax,%rax
   0x4851fb <PyObject_Repr+43>:	mov    %rax,%rbx

Please see the attached POC.
msg256986 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2015-12-25 11:13
Merged with issue25943. This is the same bug.
msg257392 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2016-01-03 02:03
I presume you meant Issue 25945, also about partial_setstate(). Issue  25943 is about the bsddb module.
msg257401 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-01-03 06:42
Yes, thank you Martin.
History
Date User Action Args
2022-04-11 14:58:25adminsetgithub: 70132
2016-01-03 06:42:42serhiy.storchakasetmessages: + msg257401
2016-01-03 02:03:00martin.pantersetsuperseder: Integer overflow in _bsddb leads to heap corruption -> Type confusion in partial_setstate and partial_call leads to memory corruption

messages: + msg257392
nosy: + martin.panter
2015-12-25 11:13:07serhiy.storchakasetstatus: open -> closed

superseder: Integer overflow in _bsddb leads to heap corruption
components: + Extension Modules, - Library (Lib)

nosy: + serhiy.storchaka
messages: + msg256986
resolution: duplicate
stage: resolved
2015-12-25 04:12:40Ned Williamsoncreate