New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SECURITY: malloc((uint64_t)length + 1) is unsafe, especially on 32-bit systems #273

Closed
solardiz opened this Issue Dec 13, 2018 · 9 comments

Comments

Projects
None yet
5 participants
@solardiz
Copy link

solardiz commented Dec 13, 2018

The fixes for #247 are incomplete, as I explained in:

https://www.openwall.com/lists/oss-security/2018/12/10/8

"Upstream's fix appears to be to add casts to (uint64_t) before adding 1 in those many malloc() calls. On platforms with larger than 32-bit size_t, this should be sufficient against integer overflows since the sizes are read from 32-bit protocol fields, but it isn't sufficient to prevent maliciously large memory allocation on the client by a rogue server. On a platform with 32-bit size_t, this isn't even sufficient to prevent the integer overflows."

Edit: I've just realized the fixes were the issue reporter's, and were merely accepted upstream. But that doesn't change anything with respect to the project needing even further fixes.

@bk138

This comment has been minimized.

Copy link
Member

bk138 commented Dec 13, 2018

Thanks for reporting. What fix do you propose?

@bk138

This comment has been minimized.

Copy link
Member

bk138 commented Dec 13, 2018

One more question @solardiz: How did you get to know that a uint_64t, when availabale, is actually 32 bits on 32-bit systems?

@solardiz

This comment has been minimized.

Copy link
Author

solardiz commented Dec 13, 2018

Considering that (part of) the fix should be sanity-limiting the allocation size (since it's not great to let the remote system cause us to allocate almost 4 GiB), we can do just that and with a sane limit (applied prior to any typecasts or math) it'll also prevent 32-bit integer overflows and thus be a complete fix. I don't currently have time to propose a specific patch. Maybe @PaulCher will, as it's his incomplete fixes that we'll be fixing now?

I sure hope uint64_t is indeed 64-bit on any system. I didn't imply otherwise. The problem is that malloc is defined to accept a size_t, and that is often 32-bit. So we may have a 64-bit value of 2^32 that becomes a 32-bit value of 0 as it's passed to malloc.

@PaulCher

This comment has been minimized.

Copy link

PaulCher commented Dec 13, 2018

My bad, I completely forgot about 32-bit platforms... Actually before proposing the patch I took a glance at how previous integer overflow issues were fixed in libvnc, so there must be even more.

Well, I looked up how they deal with this kind of problems in other VNC projects. In ultravnc every temporary allocations are limited to 100MB (function CheckBufferSize ClientConnection.cpp:6809). ~100 megabytes seems acceptable the frame buffer according to the modern screen sizes, do you agree? Testing is required to ensure that this memory limit will not break any functionality.

Probably for things like "reason of connection loss" more strict limitations can be enforced. As @solardiz stated in another issue Qemu is using limit of 1MB for cut text buffer.

@bk138

This comment has been minimized.

Copy link
Member

bk138 commented Dec 13, 2018

@solardiz thanks for the explanation, makes sense!

@bk138 bk138 added this to the Release 0.9.12 milestone Dec 28, 2018

bk138 added a commit that referenced this issue Dec 29, 2018

LibVNCClient: ignore server-sent cut text longer than 1MB
This is in line with how LibVNCServer does it
(28afb6c) and fixes part of #273.

@bk138 bk138 closed this in e34bcbb Dec 29, 2018

@solardiz

This comment has been minimized.

Copy link
Author

solardiz commented Dec 29, 2018

I think this issue isn't fully fixed yet. Please re-open.

There are more instances of the vulnerable pattern in the tree:

$ grep -rn 'malloc.*uint64_t' .
./libvncclient/rfbproto.c:1228:  client->desktopName = malloc((uint64_t)client->si.nameLength + 1);
./libvncclient/rfbproto.c:2226:    buffer = malloc((uint64_t)msg.sct.length+1);
./libvncserver/rfbserver.c:1468:        buffer=malloc((uint64_t)length+1);

Also, while 045a044 does avoid the integer overflow in MallocFrameBuffer (assuming the comment is correct, which I didn't verify), it allows for allocation of a potentially very large framebuffer, allowing a server to crash the client system. I think its check of allocSize >= SIZE_MAX should be changed to a check against some sane limit, e.g. something in the range of 100 MiB to 1 GiB.

The above list of remaining issues is probably non-exhaustive.

@ppisar

This comment has been minimized.

Copy link
Contributor

ppisar commented Jan 4, 2019

Regarding the rfbProcessFileTransferReadBuffer(), what's the reasonable file size?

I can imagine people could want to transfer 4-GiB files (even larger but that's not supported by the protocol).

Even if we choose a smaller limit, a user can connect multiple times, ask for a large file transfer and that will exhaust the physical memory. We could implement some per-user limit, but some VNC authentication methods do not have a concept of user accounts. I think this is out of scope of the VNC server. This can be easily implemented on an operating system level by setting the process memory limits (ulimit -m -v). Then the malloc() fails and the server refuses the transfer.

Even if we choose some arbitrary limit, being it a compile-time option will make hard times for users willing to change the limit (they can have a system with smaller or larger memory). Shouldn't the file size limit be a run-time option?

ppisar added a commit to ppisar/libvncserver that referenced this issue Jan 4, 2019

Limit malloc() size to SIZE_MAX - 1 bytes
This ammends a 5028218 fix for a heap
out-of-bound write access in rfbProcessFileTransferReadBuffer() when
reading a transfered file content in a server. The former fix did not
work on platforms with a 32-bit size_t type (expected by malloc()) or
with a 32-bit int type (expected by rfbReadExact());

It also fixes the same issue in InitialiseRFBConnection() when
reading a display name in a client.

It also corrects a cast in HandleRFBServerMessage() when a client
reads a cut text from a server. This allocation is already guarded
since commit c5ba3fe.

CVE-2018-15127
<LibVNC#243>
<LibVNC#273>

@bk138 bk138 reopened this Jan 5, 2019

bk138 added a commit that referenced this issue Jan 6, 2019

bk138 added a commit that referenced this issue Jan 6, 2019

bk138 added a commit that referenced this issue Jan 6, 2019

@bk138

This comment has been minimized.

Copy link
Member

bk138 commented Jan 6, 2019

Closing this now, futher sanity checking for plausible allocation sizes should be collected in #275

@bk138 bk138 closed this Jan 6, 2019

ppisar added a commit to ppisar/libvncserver that referenced this issue Jan 7, 2019

Limit lenght to INT_MAX bytes in rfbProcessFileTransferReadBuffer()
This ammends 15bb719 fix for a heap
out-of-bound write access in rfbProcessFileTransferReadBuffer() when
reading a transfered file content in a server. The former fix did not
work on platforms with a 32-bit int type (expected by rfbReadExact()).

CVE-2018-15127
<LibVNC#243>
<LibVNC#273>

ppisar added a commit to ppisar/libvncserver that referenced this issue Jan 8, 2019

Limit lenght to INT_MAX bytes in rfbProcessFileTransferReadBuffer()
This ammends 15bb719 fix for a heap
out-of-bound write access in rfbProcessFileTransferReadBuffer() when
reading a transfered file content in a server. The former fix did not
work on platforms with a 32-bit int type (expected by rfbReadExact()).

CVE-2018-15127
<LibVNC#243>
<LibVNC#273>
@mdeslaur

This comment has been minimized.

Copy link

mdeslaur commented Jan 30, 2019

The following CVEs were assigned for the incomplete fixes:


CVE-2018-20748:
LibVNC before 0.9.12 contains multiple heap out-of-bounds write vulnerabilities in
libvncclient/rfbproto.c. The fix for CVE-2018-20019 was incomplete.

c5ba3fe
e34bcbb
c2c4b81
a64c3b3


CVE-2018-20749:
LibVNC before 0.9.12 contains a heap out-of-bounds write vulnerability in
libvncserver/rfbserver.c. The fix for CVE-2018-15127 was incomplete.

15bb719


CVE-2018-20750:
LibVNC through 0.9.12 contains a heap out-of-bounds write vulnerability in
libvncserver/rfbserver.c. The fix for CVE-2018-15127 was incomplete.

09e8fc0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment