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.

Author Ned Williamson
Recipients Ned Williamson
Date 2015-12-25.04:12:37
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1451016760.11.0.799942941118.issue25944@psf.upfronthosting.co.za>
In-reply-to
Content
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.
History
Date User Action Args
2015-12-25 04:12:40Ned Williamsonsetrecipients: + Ned Williamson
2015-12-25 04:12:40Ned Williamsonsetmessageid: <1451016760.11.0.799942941118.issue25944@psf.upfronthosting.co.za>
2015-12-25 04:12:40Ned Williamsonlinkissue25944 messages
2015-12-25 04:12:39Ned Williamsoncreate