Bug 1081493 - (CVE-2018-7225) VUL-0: CVE-2018-7225: LibVNCServer: rfbserver.c: rfbProcessClientNormalMessage() case rfbClientCutText doesn't sanitize msg.cct.length
(CVE-2018-7225)
VUL-0: CVE-2018-7225: LibVNCServer: rfbserver.c: rfbProcessClientNormalMessag...
Status: RESOLVED FIXED
Classification: Novell Products
Product: SUSE Security Incidents
Classification: Novell Products
Component: Incidents
unspecified
Other Other
: P3 - Medium : Normal
: ---
Assigned To: Security Team bot
Security Team bot
CVSSv3:RedHat:CVE-2018-7225:5.5:(AV:N...
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2018-02-19 06:12 UTC by Karol Babioch
Modified: 2018-09-07 12:47 UTC (History)
3 users (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 Karol Babioch 2018-02-19 06:12:09 UTC
Hi,

I've just created the below GitHub issue, and I'm also posting its
description in here.  This applies at least to LibVNCServer versions
0.9.9 (RHEL7) to latest in the GitHub repo as of this writing (and thus
probably including latest release, which is 0.9.11, but I didn't check
the release specifically).

https://github.com/LibVNC/libvncserver/issues/218

While I consider this a security-relevant issue, I feel there's no
overall benefit from reporting it under an embargo, so here goes.

libvncserver/rfbserver.c: rfbProcessClientNormalMessage() contains the
following code:

    case rfbClientCutText:

        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
                           sz_rfbClientCutTextMsg - 1)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            rfbCloseClient(cl);
            return;
        }

        msg.cct.length = Swap32IfLE(msg.cct.length);

        str = (char *)malloc(msg.cct.length);
        if (str == NULL) {
                rfbLogPerror("rfbProcessClientNormalMessage: not enough memory");
                rfbCloseClient(cl);
                return;
        }

        if ((n = rfbReadExact(cl, str, msg.cct.length)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            free(str);
            rfbCloseClient(cl);
            return;
        }
        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbClientCutTextMsg+msg.cct.length, sz_rfbClientCutTextMsg+msg.cct.length);
        if(!cl->viewOnly) {
            cl->screen->setXCutText(str, msg.cct.length, cl);
        }
        free(str);

        return;

This passes the client-provided 32-bit message length field's value
directly into malloc(), reads up to this many bytes from the client, and
then passes the full value to the library-user-provided setXCutText()
callback (where the value might be higher than the number of bytes
actually read - with uninitialized and potentially sensitive data
afterwards - and it might also be too high for the callback's
implementation to handle safely).  There may also be integer overflow in
the addition of sz_rfbClientCutTextMsg (which is 8) to the value in the
call to rfbStatRecordMessageRcvd(); I did not look into what
consequences this might have.

I first found the issue during Openwall's security audit of the
Virtuozzo 7 product, which uses a RHEL7-derived package of
LibVNCServer-0.9.9 from its prl-vzvncserver component.  A corresponding
Virtuozzo 7 fix is:

https://src.openvz.org/projects/OVZ/repos/prl-vzvncserver/commits/1204a8872d90c78a2be404dd4b025124bb01b2c5

which hardens prl-vzvncserver's setXCutText() callback - but the rest of
the issue needs to be fixed in LibVNCServer itself, hence the (belated)
report to them and in here.

We would like to thank the Virtuozzo company for funding the effort.

Included below is the relevant excerpt from our Virtuozzo 7 report:

--- cut ---
01090, PSBM-58099: prl-vzvncserver and LibVNCServer integer overflows, unlimited memory allocations, and unchecked malloc()
Severity: medium
Thread: 20161226 "prl-vzvncserver"

A particular combination of these 3 problems is demonstrated by sending the
output of "echo -e "RFB 003.003\n\001\006\0\0\0\xff\xff\xff\xff"" to
prl-vzvncserver's TCP port, when prl-vzvncserver is running without password.
(When running with password, authentication would be needed before the specific
vulnerable code can be reached, and the string to send would accordingly be
longer.)  This first causes LibVNCServer to allocate 4 GiB of address space and
then to hand out this uninitialized memory to the prl-vzvncserver/console.c:
vcSetXCutTextProc() callback, which would attempt to make another similar
allocation and make a copy of the data.  Unfortunately, this LibVNCServer API,
as well as many others, is defined to use "int" rather than "size_t" for data
sizes, and indeed prl-vzvncserver uses "int" too.  For this particular request,
this results in a zero byte allocation with malloc(), which succeeds, and then
in a memcpy() of (size_t)-1 bytes to it.  With a range of other similar
requests, malloc() may instead be made to fail (for trying to allocate a
ridiculous amount of address space, sign-extended to 64-bit), in which case the
memcpy() more reliably fails on a NULL pointer dereference.  Either way, the
service crashes.  Finally, it is possible to have the process actually write to
(and thus allocate for real) almost 4 GiB of memory with one request, by making
the length field just below 2 GiB.  If no data is sent, then 2 GiB would be
written from the uninitialized memory (likely mostly read-as-zero) to the
memory allocated by prl-vzvncserver's callback.  If the data is actually sent,
then first it is written to memory by LibVNCServer and then is copied by the
callback, for 4 GiB total.  Exploitability of this specific issue into
something worse than these varying possibilities is highly doubtful (although
exploitation of unlimited size memcpy() is not unheard of), but all 3 of these
issues are prevalent in prl-vzvncserver and LibVNCServer code in general, so
maybe the impact of another similar issue would more obviously be worse.

We recommend that sanity checks be introduced into LibVNCServer so that it
doesn't try to allocate unreasonable amounts of memory and pass unsafe sizes to
callbacks.  We also recommend prl-vzvncserver to sanity-check its inputs
(including received from LibVNCServer) and in this way avoid integer overflows
and unreasonably large allocations.  Finally, it is good practice to check
whether a malloc() succeeded before writing to the memory.  The function
vcSetXCutTextProc() came from LibVNCServer-0.9.9/vncterm/VNConsole.c, so its
shortcomings also need to be reported to LibVNCServer upstream.

Fix: Some aspects of this issue, most importantly covering prl-vzvncserver's
vcSetXCutTextProc() callback, have been addressed with commit
1204a8872d90c78a2be404dd4b025124bb01b2c5 on 20170130.

Related:
https://googleprojectzero.blogspot.com/2015/03/taming-wild-copy-parallel-thread.html
http://www.giac.org/paper/gcih/361/port-80-apache-http-daemon-exploit/103818
--- cut ---

LibVNCServer-0.9.9/vncterm/VNConsole.c mentioned above is not currently
part of the libvncserver repo, hence is not otherwise included in
description of this issue.  However, vncterm exists as a separate repo,
so I might report its issues in there: https://github.com/LibVNC/vncterm

Timeline:

201612xx - issue found while auditing prl-vzvncserver
20161226 - report to Virtuozzo with a focus on prl-vzvncserver specifics
20170130 - a relevant prl-vzvncserver fix committed in Virtuozzo
20180218 - public report to LibVNCServer and oss-security

The ridiculous delay in making this report to LibVNCServer and
oss-security is unintentional.  I just didn't get around to doing this
sooner, and I'm sorry about that.

In case anyone cares and would have asked, no, I did not request CVE
ID(s) for this, and I don't intend to do so.  I also don't know if this
is CVE-worthy.  Please feel free to track the LibVNCServer issue(s)
described here (rfbClientCutText's lack of sanity-checking of the length
field, passing of the full specified rather than actual read byte count
to other functions, and the +8 integer overflow) as OVE-20180218-0001.

Alexander
Comment 2 Karol Babioch 2018-02-19 15:06:45 UTC
This has been assigned: CVE-2018-7225
Comment 3 Karol Babioch 2018-02-26 10:34:28 UTC
Affected codestreams:

SUSE:SLE-12:Update 
SUSE:SLE-11:Update
Comment 7 Petr Gajdos 2018-02-27 07:18:20 UTC
(In reply to Karol Babioch from comment #6)
> There seems to be an upstream fix now:
> 
> https://github.com/ppisar/libvncserver/commit/
> 0073e4f694d5a51bb72ff12a5e8364b6e752e094

I would exclude 'upstream' word from above statement. But let's see whether libVNC maintainer accepts it.

From the description of the fix:

"Whether a client can make the server allocate up to 2 GB and cause
a denial of service on memory-tight systems is kept without answer.
A possible solution would be adding an arbitrary memory limit that is
deemed safe."

This is discussed later in the commit proposing to limit the allocation to 1MB.
Comment 8 Petr Gajdos 2018-03-02 07:47:56 UTC
Corresponding pull request, no news so far.
Comment 9 Petr Gajdos 2018-03-10 13:07:43 UTC
Now the corresponding pull request:
https://github.com/LibVNC/libvncserver/pull/221

Some discussion there, but it seems to be almost done.
Comment 12 Petr Gajdos 2018-03-19 18:36:42 UTC
Packages submitted: 12/LibVNCServer, 11/LibVNCServer. 

I will ensure tomorrow that the fix will also get into sle15.
Comment 14 Petr Gajdos 2018-03-20 08:00:53 UTC
Submitted to sle15 (sr#159661). As long as the patch is from pull request and author almost agree with submitter, this will end up in factory one day, not submitting there.
Comment 16 Petr Gajdos 2018-03-20 08:06:22 UTC
Reassigning.
Comment 18 Swamp Workflow Management 2018-03-27 19:08:12 UTC
SUSE-SU-2018:0830-1: An update that fixes three vulnerabilities is now available.

Category: security (important)
Bug References: 1017711,1017712,1081493
CVE References: CVE-2016-9941,CVE-2016-9942,CVE-2018-7225
Sources used:
SUSE Linux Enterprise Software Development Kit 12-SP3 (src):    LibVNCServer-0.9.9-17.5.1
SUSE Linux Enterprise Software Development Kit 12-SP2 (src):    LibVNCServer-0.9.9-17.5.1
SUSE Linux Enterprise Server for Raspberry Pi 12-SP2 (src):    LibVNCServer-0.9.9-17.5.1
SUSE Linux Enterprise Server 12-SP3 (src):    LibVNCServer-0.9.9-17.5.1
SUSE Linux Enterprise Server 12-SP2 (src):    LibVNCServer-0.9.9-17.5.1
Comment 19 Swamp Workflow Management 2018-03-29 22:07:38 UTC
openSUSE-SU-2018:0851-1: An update that fixes three vulnerabilities is now available.

Category: security (important)
Bug References: 1017711,1017712,1081493
CVE References: CVE-2016-9941,CVE-2016-9942,CVE-2018-7225
Sources used:
openSUSE Leap 42.3 (src):    LibVNCServer-0.9.9-16.3.1
Comment 20 Swamp Workflow Management 2018-04-05 19:08:04 UTC
SUSE-SU-2018:0875-1: An update that fixes one vulnerability is now available.

Category: security (moderate)
Bug References: 1081493
CVE References: CVE-2018-7225
Sources used:
SUSE Linux Enterprise Software Development Kit 11-SP4 (src):    LibVNCServer-0.9.1-160.3.1
SUSE Linux Enterprise Server 11-SP4 (src):    LibVNCServer-0.9.1-160.3.1
SUSE Linux Enterprise Debuginfo 11-SP4 (src):    LibVNCServer-0.9.1-160.3.1
Comment 21 Marcus Meissner 2018-09-07 12:47:10 UTC
done