Bug 917760 (CVE-2015-1315) - VUL-0: CVE-2015-1315: unzip: DOS, possible RCE by out-of-bounds write
Summary: VUL-0: CVE-2015-1315: unzip: DOS, possible RCE by out-of-bounds write
Status: RESOLVED INVALID
Alias: CVE-2015-1315
Product: SUSE Security Incidents
Classification: Novell Products
Component: Incidents (show other bugs)
Version: unspecified
Hardware: Other Other
: P3 - Medium : Normal
Target Milestone: ---
Assignee: Thorsten Behrens
QA Contact: Security Team bot
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-02-13 08:22 UTC by Johannes Segitz
Modified: 2015-02-18 08:34 UTC (History)
1 user (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Johannes Segitz 2015-02-13 08:22:55 UTC
Date: Fri, 13 Feb 2015 00:02:14 +0100
From: William Robinet <william.robinet@conostix.com>

Here is a crash file [0] for Info-ZIP unzip. I tested it on Ubuntu 14.04.1 LTS
amd64 with unzip-6.0-9ubuntu1.2.

$ unzip -l crash.zip
Archive:  crash.zip
Segmentation fault (core dumped)
$ echo $?
139

$ unzip crash.zip
Archive:  crash.zip
Segmentation fault (core dumped)
$ echo $?
139

The problem comes from the "unix/unix.c:charset_to_intern()" function from the
"06-unzip60-alt-iconv-utf8" patch (cfr relevant excerpt at [1]).

Arbitrary code execution is most probably possible. It's just a matter of time
in order to get a working exploit.

Here are the details.

Please refer to the code of the "unix/unix.c:charset_to_intern()" function in
[1].

The problem is triggered during string conversion from CP866 to UTF-8:
(gdb) p local_charset
$2 = 0x7ffff755330c "UTF-8"
(gdb) p from_charset
$3 = 0x62bda0 <OEM_CP> "CP866"

The "string" variable is allocated at:
fileio.c:2207             G.filename_full = malloc(fnbufsiz);

Size of the allocation is defined by
fileio.c:2201             extent fnbufsiz = FILNAMSIZ;
and
unzpriv.h:1198 #define FILNAMSIZ  PATH_MAX

Finally "string" has a maximum size of:
(gdb) p PATH_MAX
$1 = 4096

The "buf" variable is used as the destination buffer for the result of the
string conversion of the "string" variable by the "iconv" function at
unix/unix.c:1948.

"buf" is allocated with a size of twice (+1) the actual size of the string
referenced by the "string" variable at unix/unix.c:1942.

Finally, after conversion, the actual string referenced by "buf" is
copied to "string" at unix/unix.c:1950.

The problem is that, in some case and after conversion, the actual size
of the string referenced by "buf" can be larger that the maximum size of
the "string" buffer (4096). This leads to a heap-based buffer overflow.

Here is an example gdb session (unzip has been recompiled with -g -ggdb3).
RIP control can be easily achieved. As an example, with the attached crash.zip
file, RIP is set to 0x414141 (just before crashing). The 0x414141 value can be
changed at offset 0x1599 in the crash.zip file.

$ gdb -q unzip
Reading symbols from unzip...done.
(gdb) b unix/unix.c:1950
Breakpoint 1 at 0x41ef32: file unix/unix.c, line 1950.
(gdb) r -l crash.zip
Starting program: /usr/bin/unzip -l crash.zip
Archive:  crash.zip
  Length      Date    Time    Name
---------  ---------- -----   ----

Breakpoint 1, charset_to_intern (string=0x71c120 <G+983872> '\313' <repeats 199 times>, <incomplete sequence \313>..., from_charset=0x62bda0 <OEM_CP> "CP866")
    at unix/unix.c:1950
1950        strncpy(string, buf, buflen);
(gdb) p strlen(string)
$1 = 2714
(gdb) p strlen(buf)
$2 = 4395
(gdb) n
1953        free(buf);
(gdb) p strlen(string)
$4 = 4395   <--------------- Overflow has occurred
(gdb) p strlen(buf)
$5 = 4395
(gdb) b *0x414141  <-------- Let's break at the selected arbitrary address
Breakpoint 2 at 0x414141: file process.c, line 1364.
(gdb) c
Comment 1 Johannes Segitz 2015-02-13 08:24:08 UTC
so this "Enter" should not have send the bug report ...

==========

Continuing.

Breakpoint 2, 0x0000000000414141 in find_ecrec64 (searchlen=1423209390) at process.c:1364
1364          Info(slide, 0x401, ((char *)slide,
(gdb) info reg
rax            0x1e     30
rbx            0x20     32
rcx            0x0      0
rdx            0x1e     30
rsi            0x70bee0 7388896
rdi            0x62bde0 6471136
rbp            0x7fffffffe430   0x7fffffffe430
rsp            0x7fffffffe2a8   0x7fffffffe2a8
r8             0x7ffff7972840   140737347266624
r9             0x2      2
r10            0x7ffff7bb9760   140737349654368
r11            0x0      0
r12            0x414141 4276545
r13            0x2d     45
r14            0x2d     45
r15            0x0      0
rip            0x414141 0x414141 <find_ecrec64+2537> <--  RIP was redirected to the arbitrary address 0x414141
eflags         0x202    [ IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb)

At this point, getting arbitrary code execution is just a matter of
time.

The locale config of my test systems is en_US.UTF-8 .

[0] Attachment: crash.zip
    (SHA256: d79d6612ffabe7906f0afdf7293de819950623ffc2004fa501f874a42547d7d8)
[1] Attachment: 06-unzip60-alt-iconv-utf8.excerpt
    (SHA256: 7043a3cd71618085281400ed1ae576964ae5067e7a28cf664510ab20f9ef055e)
Comment 2 Johannes Segitz 2015-02-13 08:24:33 UTC
Created attachment 623175 [details]
Crasher
Comment 3 Johannes Segitz 2015-02-13 08:26:31 UTC
CRD: 2015-02-17

Crasher doesn't work on openSUSE 13.2. I checked SLE 12 and we don't have the patch that introduces the vulnerability, so we're probably not vulnerable. Please check older versions and close this bug if we're not vulnerable.
Comment 4 Swamp Workflow Management 2015-02-13 23:00:14 UTC
bugbot adjusting priority
Comment 5 Johannes Segitz 2015-02-14 15:08:39 UTC
Introduced in 6.1, doesn't affect us.
Comment 6 Johannes Segitz 2015-02-18 08:34:26 UTC
public