curl / Docs / Security Problems / SMTP send heap buffer overflow

SMTP send heap buffer overflow

Project curl Security Advisory, July 11th 2018 - Permalink

VULNERABILITY

curl might overflow a heap based memory buffer when sending data over SMTP and using a reduced read buffer.

When sending data over SMTP, curl allocates a separate "scratch area" on the heap to be able to escape the uploaded data properly if the uploaded data contains data that requires it.

The size of this temporary scratch area was mistakenly made to be 2 * sizeof(download_buffer) when it should have been made 2 * sizeof(upload_buffer).

The upload and the download buffer sizes are identically sized by default (16KB) but since version 7.54.1, curl can resize the download buffer into a smaller buffer (as well as larger). If the download buffer size is set to a value smaller than 10923, the Curl_smtp_escape_eob() function might overflow the scratch buffer when sending contents of sufficient size and contents.

The curl command line tool lowers the buffer size when --limit-rate is set to a value smaller than 16KB.

We are not aware of any exploit of this flaw.

TEST CASES

Here's a shell script

# Setup an SMTP end-point, make file, run curl
$ printf '220 Hi\n250 SIZE 10000\n250 OK\n250 OK\n354 send data\n' | nc -l -p 2525 >/dev/null &
$ printf '%5000s' > mail.txt
$ curl -v smtp://localhost:2525 --mail-from me --mail-rcpt root@localhost --upload-file mail.txt --limit-rate 1024

PHP code:

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "smtp://localhost:2525");
curl_setopt($ch, CURLOPT_BUFFERSIZE, 1024);
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_MAIL_FROM, "me");
curl_setopt($ch, CURLOPT_MAIL_RCPT, ["root@localhost"]);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
$eof = false;
curl_setopt($ch, CURLOPT_READFUNCTION, function($ch, $stream, $maxSize) {
    global $eof;
    echo "Max Size: [$maxSize]\n";
    if ($eof) {
        return "";
    }
    $eof = true;
    return str_repeat(" ", $maxSize);
});
curl_exec($ch);
curl_close($ch);

INFO

This bug was introduced in April 2017 in this commit when we introduced support for buffer resize. The scratch buffer was mistakenly made to use the dynamic size when it should kept using the fixed upload buffer size.

The Common Vulnerabilities and Exposures (CVE) project has assigned the name CVE-2018-0500 to this issue.

CWE-122: Heap-based Buffer Overflow

AFFECTED VERSIONS

libcurl is used by many applications, but not always advertised as such.

THE SOLUTION

In curl version 7.61.0, curl will use the upload buffer size as base for the scratch area allocation.

A patch for CVE-2018-0500 is available.

RECOMMENDATIONS

We suggest you take one of the following actions immediately, in order of preference:

A - Upgrade curl to version 7.61.0

B - Apply the patch to your version and rebuild

C - Avoid using SMTP uploads with CURLOPT_BUFFERSIZE set below 10923

TIME LINE

It was reported to the curl project on June 11, 2018

We contacted distros@openwall on July 1, 2018.

curl 7.61.0 was released on July 11 2018, coordinated with the publication of this advisory.

CREDITS

Detected and researched by Peter Wu. Patch by Daniel Stenberg.

Thanks a lot!