Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type confusion in partial_setstate and partial_repr leads to control flow hijack #70132

Closed
NedWilliamson mannequin opened this issue Dec 25, 2015 · 4 comments
Closed
Labels
extension-modules C modules in the Modules dir type-crash A hard crash of the interpreter, possibly with a core dump

Comments

@NedWilliamson
Copy link
Mannequin

NedWilliamson mannequin commented Dec 25, 2015

BPO 25944
Nosy @vadmium, @serhiy-storchaka
Superseder
  • bpo-25945: Type confusion in partial_setstate and partial_call leads to memory corruption
  • Files
  • partialpoc.py
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2015-12-25.11:13:07.174>
    created_at = <Date 2015-12-25.04:12:40.085>
    labels = ['extension-modules', 'type-crash']
    title = 'Type confusion in partial_setstate and partial_repr leads to control flow hijack'
    updated_at = <Date 2016-01-03.06:42:42.674>
    user = 'https://bugs.python.org/NedWilliamson'

    bugs.python.org fields:

    activity = <Date 2016-01-03.06:42:42.674>
    actor = 'serhiy.storchaka'
    assignee = 'none'
    closed = True
    closed_date = <Date 2015-12-25.11:13:07.174>
    closer = 'serhiy.storchaka'
    components = ['Extension Modules']
    creation = <Date 2015-12-25.04:12:40.085>
    creator = 'Ned Williamson'
    dependencies = []
    files = ['41409']
    hgrepos = []
    issue_num = 25944
    keywords = []
    message_count = 4.0
    messages = ['256975', '256986', '257392', '257401']
    nosy_count = 3.0
    nosy_names = ['martin.panter', 'serhiy.storchaka', 'Ned Williamson']
    pr_nums = []
    priority = 'normal'
    resolution = 'duplicate'
    stage = 'resolved'
    status = 'closed'
    superseder = '25945'
    type = 'crash'
    url = 'https://bugs.python.org/issue25944'
    versions = ['Python 3.5', 'Python 3.6']

    @NedWilliamson
    Copy link
    Mannequin Author

    NedWilliamson mannequin commented Dec 25, 2015

    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.

    @NedWilliamson NedWilliamson mannequin added stdlib Python modules in the Lib dir type-crash A hard crash of the interpreter, possibly with a core dump labels Dec 25, 2015
    @serhiy-storchaka
    Copy link
    Member

    Merged with bpo-25943. This is the same bug.

    @serhiy-storchaka serhiy-storchaka added extension-modules C modules in the Modules dir and removed stdlib Python modules in the Lib dir labels Dec 25, 2015
    @vadmium
    Copy link
    Member

    vadmium commented Jan 3, 2016

    I presume you meant bpo-25945, also about partial_setstate(). Issue 25943 is about the bsddb module.

    @serhiy-storchaka
    Copy link
    Member

    Yes, thank you Martin.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    extension-modules C modules in the Modules dir type-crash A hard crash of the interpreter, possibly with a core dump
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants