classification
Title: heap overflow in zipimporter module
Type: security Stage: resolved
Components: Versions: Python 3.6, Python 3.5, Python 3.4, Python 3.3, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: Insu Yun, Parvesh jain, berker.peksag, georg.brandl, ned.deily, python-dev, vladk
Priority: Keywords:

Created on 2016-01-21 03:52 by Insu Yun, last changed 2017-05-21 16:21 by berker.peksag. This issue is now closed.

Files
File name Uploaded Description Edit
crash.py Insu Yun, 2016-01-21 03:52
patch-Modules_zipimport-CVE-2016-5636.c vladk, 2016-06-16 21:29 Modules/zipimport.c patch for CVE-2016-5636
Messages (11)
msg258733 - (view) Author: Insu Yun (Insu Yun) Date: 2016-01-21 03:52
in zipimport.c
  1116     bytes_size = compress == 0 ? data_size : data_size + 1;
  1117     if (bytes_size == 0)
  1118         bytes_size++;
  1119     raw_data = PyBytes_FromStringAndSize((char *)NULL, bytes_size);

If compress != 0, then bytes_size = data_size + 1
data_size is not sanitized, so if data_size = -1, then it overflows and becomes 0.
In that case bytes_size becomes 1 and python allocates small heap, but after that in fread, it overflows heap.
msg258736 - (view) Author: Roundup Robot (python-dev) Date: 2016-01-21 06:26
New changeset 01ddd608b85c by Benjamin Peterson in branch '3.4':
prevent buffer overflow in get_data (closes #26171)
https://hg.python.org/cpython/rev/01ddd608b85c

New changeset 985fc64c60d6 by Benjamin Peterson in branch '2.7':
prevent buffer overflow in get_data (closes #26171)
https://hg.python.org/cpython/rev/985fc64c60d6

New changeset 10dad6da1b28 by Benjamin Peterson in branch '3.5':
merge 3.4 (#26171)
https://hg.python.org/cpython/rev/10dad6da1b28

New changeset 2df462852464 by Benjamin Peterson in branch 'default':
merge 3.5 (#26171)
https://hg.python.org/cpython/rev/2df462852464
msg258779 - (view) Author: Insu Yun (Insu Yun) Date: 2016-01-21 23:40
in zipimport.c
  1116     bytes_size = compress == 0 ? data_size : data_size + 1;
  1117     if (bytes_size == 0)
  1118         bytes_size++;
  1119     raw_data = PyBytes_FromStringAndSize((char *)NULL, bytes_size);

If compress != 0, then bytes_size = data_size + 1
data_size is not sanitized, so if data_size = -1, then it overflows and becomes 0.
In that case bytes_size becomes 1 and python allocates small heap, but after that in fread, it overflows heap.
msg268693 - (view) Author: Vlad K. (vladk) Date: 2016-06-16 20:24
I believe this should be applied to Python 3.3 as well, since the same problem (unchecked data_size before adding +1 for bytes_size) exists there too, and is thus a security issue.
msg268698 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2016-06-16 21:19
reopening for 3.3.7 evaluation.  Georg?
msg268700 - (view) Author: Vlad K. (vladk) Date: 2016-06-16 21:29
Here's the patch that I made for FreeBSD's Python 3.3 port. With this patch, on FreeBSD, Python 3.3 built fine and passed the zipimport related unit tests. It's basically the same code from 3.4, 3.5 and 2.7, just placed at appropriate place in the source.
msg269194 - (view) Author: Vlad K. (vladk) Date: 2016-06-24 17:10
Any updates on this? We've committed the patch for Python 3.3 as well in FreeBSD.

https://svnweb.freebsd.org/ports?view=revision&revision=417019
msg276380 - (view) Author: Roundup Robot (python-dev) Date: 2016-09-14 05:39
New changeset 5ae8756a1ae0 by Berker Peksag in branch '3.3':
Issue #26171: Prevent buffer overflow in get_data
https://hg.python.org/cpython/rev/5ae8756a1ae0

New changeset fa006d671f41 by Berker Peksag in branch '3.4':
Issue #26171: Null merge
https://hg.python.org/cpython/rev/fa006d671f41

New changeset 2fb148cd95a2 by Berker Peksag in branch '3.5':
Issue #26171: Null merge
https://hg.python.org/cpython/rev/2fb148cd95a2

New changeset aa0c49b8edae by Berker Peksag in branch '3.6':
Issue #26171: Null merge
https://hg.python.org/cpython/rev/aa0c49b8edae

New changeset f3df6b16af7d by Berker Peksag in branch 'default':
Issue #26171: Null merge
https://hg.python.org/cpython/rev/f3df6b16af7d
msg276381 - (view) Author: Berker Peksag (berker.peksag) * (Python committer) Date: 2016-09-14 05:41
Thanks!
msg278228 - (view) Author: Parvesh jain (Parvesh jain) Date: 2016-10-07 03:57
I think patches put up in http://bugs.python.org/msg258736 is at least not sufficient enough for Python 2.7. 
POC script(crash.py) provided with the issue calls get_data with data_size = -1.
I am using Python 2.7.8 . I patched the same with the solution provided in https://hg.python.org/cpython/rev/985fc64c60d6 . I was still able to reproduce the issue and it failed with 

Traceback (most recent call last):
  File "crash.py", line 25, in <module>
    print(importer.get_data(FILE))
IOError: zipimport: can't read data
Segmentation fault (core dumped)


but I couldn't reproduce the same with latest 2.7.12:-

jchang@qasus-ubun12x64-001:~/Downloads/Python-2.7.12$ python2.7 -V
Python 2.7.12
jchang@qasus-ubun12x64-001:~/Downloads/Python-2.7.12$ python2.7 crash.py
Traceback (most recent call last):
  File "crash.py", line 25, in <module>
    print(importer.get_data(FILE))
zipimport.ZipImportError: negative data size

As we can see issue does happen in 2.7.12 because of following extra check :-

if (data_size < 0) {
        PyErr_Format(ZipImportError, "negative data size");
        return NULL;
    }

which was merged in https://hg.python.org/cpython/rev/2edbdb79cd6d. 

I was thinking of backporting the same to Python 2.7.8 as well to completely address this issue. Could you guys confirm if my understanding is correct on this ? Thanks
msg278324 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2016-10-08 20:04
Parvesh, we only maintain the latest micro release of a release cycle; for 2.7, that is currently 2.7.12.  In other words, once 2.7.9 was released, 2.7.8 was no longer supported by us (although, of course, downstream distributors of Cpython can choose to backport fixes to older releases on their own).
History
Date User Action Args
2017-05-21 16:21:43berker.peksagsetpull_requests: - pull_request1794
2017-05-21 13:41:01jimmylaisetpull_requests: + pull_request1794
2016-10-08 20:07:42ned.deilysetpriority: release blocker ->
versions: + Python 2.7, Python 3.4, Python 3.5, Python 3.6
2016-10-08 20:04:37ned.deilysetmessages: + msg278324
2016-10-07 03:57:43Parvesh jainsetnosy: + Parvesh jain
messages: + msg278228
2016-09-14 05:41:18berker.peksagsetstatus: open -> closed

nosy: + berker.peksag
messages: + msg276381

resolution: fixed
stage: needs patch -> resolved
2016-09-14 05:39:46python-devsetmessages: + msg276380
2016-09-09 08:37:34christian.heimessetpriority: release blocker
versions: + Python 3.3, - Python 2.7, Python 3.4, Python 3.5, Python 3.6
2016-06-24 17:10:12vladksetmessages: + msg269194
2016-06-16 21:29:24vladksetfiles: + patch-Modules_zipimport-CVE-2016-5636.c

messages: + msg268700
versions: - Python 3.3
2016-06-16 21:19:43ned.deilysetstatus: closed -> open
priority: normal -> (no value)

versions: + Python 3.3
nosy: + georg.brandl, ned.deily

messages: + msg268698
resolution: fixed -> (no value)
stage: resolved -> needs patch
2016-06-16 20:24:23vladksetnosy: + vladk
messages: + msg268693
2016-06-16 15:37:13hayposetversions: + Python 2.7, Python 3.4, Python 3.5
2016-01-21 23:40:14Insu Yunsetmessages: + msg258779
2016-01-21 06:26:00python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg258736

resolution: fixed
stage: resolved
2016-01-21 03:52:33Insu Yuncreate