Bug 1595595 (CVE-2018-1000517) - CVE-2018-1000517 busybox: wget: Heap-based buffer overflow in the retrieve_file_data() function
Summary: CVE-2018-1000517 busybox: wget: Heap-based buffer overflow in the retrieve_fi...
Alias: CVE-2018-1000517
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
Depends On: 1595679
Blocks: 1595598
TreeView+ depends on / blocked
Reported: 2018-06-27 08:11 UTC by Andrej Nemec
Modified: 2019-09-29 14:43 UTC (History)
5 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Last Closed: 2018-06-29 18:44:25 UTC

Attachments (Terms of Use)

Description Andrej Nemec 2018-06-27 08:11:29 UTC
A heap buffer overflow vulnerability was found in wget.

Upstream patch:


Comment 1 Andrej Nemec 2018-06-27 08:11:57 UTC
Created wget tracking bugs for this issue:

Affects: fedora-all [bug 1595596]

Comment 3 Tomáš Hozza 2018-06-27 10:50:40 UTC
(In reply to Andrej Nemec from comment #0)
> A heap buffer overflow vulnerability was found in wget.
> Upstream patch:
> https://git.busybox.net/busybox/commit/
> ?id=8e2174e9bd836e53c8b9c6e00d1bc6e2a718686e

That is definitely not an upstream git and that file does not exist in wget. It is probably some "custom" busybox implementation of "wget" command, but it does not seem to have much in common with GNU wget we ship in RHEL and Fedora.

Comment 4 Andrej Nemec 2018-06-27 10:55:02 UTC
Yep, this is not upstream wget but a busybox wget. I'm changing the whiteboard to reflect this. Thanks!

Comment 5 Andrej Nemec 2018-06-27 10:55:20 UTC
Created busybox tracking bugs for this issue:

Affects: fedora-all [bug 1595679]

Comment 9 Scott Gayou 2018-07-02 17:06:41 UTC
The flaw appears to be that when HTTP chunks are sent, the chunk size is implicitly trusted and cast to off_t, which is signed. A specific range of values can bypass multiple checks and get a large, attacker-controlled value to a fread which can result in a heap buffer overflow.

The reason for the newer build crash is as follows:

if (G.got_clen) {
        if (G.content_len < (off_t)sizeof(G.wget_buf)) {
                if ((int)G.content_len <= 0)
                rdsz = (unsigned)G.content_len;

G.content_len is attacker-controlled. got_clen is set after we control content_len. content_len is a off_t, so it can be negative. If an attacker makes it negative, we bypass the first check (<= sizeof(G.wget_buf)). The second check casts an off_t to an int, which is a truncation.

You'd see this warning without the explicit cast:

implicit conversion loses integer precision: 'off_t' (aka 'long') to 'int'

Thus, if it truncates to become a positive value, we bypass the next check (<= 0) and now control rdsz. This then buffer overflows char wget_buf[CONFIG_FEATURE_COPYBUF_KB*1024]; CONFIG_FEATURE_COPYBUF_KB seems to usually between 4 and 8 based on build options.

So if we pass in 0xffffffff0001f400, it truncates to 0x0001f400, which is roughly 128KB. Heap overflow.

In RHEL6 we don't do the truncation:

unsigned rdsz = sizeof(buf);
if (content_len < sizeof(buf) && (G.chunked || G.got_clen))
    rdsz = (unsigned)content_len;
n = safe_fread(buf, rdsz, dfp);

content_len (signed long) will be converted to an unsigned long. If content_len was negative, this would result in a large positive value, and the < sizeof(buf) check will capture this edge case and prevent attacker control of rdsz.

Furthermore, several lines up, there is the following line:

while (content_len > 0 || !G.got_clen) {

This will prevent content_len from being negative unless !G.got_clen is true. 

The vulnerable code can only be hit during chunked transmission. However, G.got_clen is set when chunked is enabled.

As such, this does not appear to affect RHEL6. The RHEL5 anaylsis follows from the above.

Note You need to log in before you can comment on or make changes to this bug.