CVE-2021-27219 (GHSL-2021-045): integer overflow in g_bytes_new/g_memdup
GHSL-2021-045
GitHub Security Lab (GHSL) Vulnerability Report: The GitHub Security Lab team has identified a potential security vulnerability in GLib.
We are committed to working with you to help resolve these issues. In this report you will find everything you need to effectively coordinate a resolution of these issues with the GHSL team.
If at any point you have concerns or questions about this process, please do not hesitate to reach out to us at securitylab@github.com
(please include GHSL-2021-045
as a reference).
If you are NOT the correct point of contact for this report, please let us know!
Summary
The function g_bytes_new
has an integer overflow due to an implicit cast from 64 bits to 32 bits. The overflow could potentially lead to a memory corruption vulnerability.
Product
GLib
Tested Versions
- Ubuntu 20.04 (x86_64): version 2.64.6-1
- CentOS Stream (x86_64): version 2.56.4-9
- archlinux (x86_64): 2.66.4-2
Details
Issue 1: Integer overflow in g_bytes_new (GHSL-2021-045)
On 64-bit platforms, an integer overflow can occur in g_bytes_new
, due to an implicit cast from gsize
to guint
. The overflow happens in the call to g_memdup
(gbytes.c, line 98). The reason is that size
is a 64-bit gsize
, but g_memdup
takes a 32-bit guint
.
GBytes *
g_bytes_new (gconstpointer data,
gsize size)
{
g_return_val_if_fail (data != NULL || size == 0, NULL);
return g_bytes_new_take (g_memdup (data, size), size); <=== integer overflow
}
When the overflow occurs, it does not cause the code to crash immediately. Instead, g_memdup
creates a much smaller buffer than it should. This causes g_bytes_new
to return a GBytes
object containing a much smaller data buffer than it's size would suggest. For example, if size
is 0x100000008
then g_bytes_new
will return a GBytes
object that claims to contain a 4GB buffer, but actually contains an 8 byte buffer.
We have attached a proof-of-concept which demonstrates that it is possible to trigger the overflow. The proof-of-concept triggers the overflow via polkit-agent-helper-1
, which is a SUID binary. Luckily the poc only causes polkit-agent-helper-1
to crash with a SIGABRT
, due to an assertion failure. However, GLib is a very widely used library, so it is possible that other attack vectors exist.
To run the poc:
gcc polkithelperabort.c -o polkithelperabort
./polkithelperabort <username>
The poc will ask for the user's password, which is sent to polkit-agent-helper-1
in the normal way, along with a 4GB "cookie", which triggers the overflow. Although the poc will only work with a valid password, it will work for any user account. So if you are worried about plugging a genuine password into the poc, just create a temporary user account for running the poc, and delete it when you are done.
The poc should trigger an assertion failure, with an error message like this:
GLib-GIO:ERROR:../glib/gio/gdbusmessage.c:2399:append_value_to_blob: assertion failed: (g_utf8_validate (v, -1, &end) && (end == v + len))
Bail out! GLib-GIO:ERROR:../glib/gio/gdbusmessage.c:2399:append_value_to_blob: assertion failed: (g_utf8_validate (v, -1, &end) && (end == v + len))
Impact
The poc which we have provided only causes a harmless crash. We are not currently aware of an exploitable attack vector for this issue. However, there is a risk that it could lead to memory corruption vulnerability, which could potentially be used to gain code execution in an application that uses GLib.
Remediation
The issue looks easy to fix by changing the type of the byte_size
parameter of g_memdup
, so we have a posted a merge request with that change.
Resources
Source code for poc: polkithelperabort.c
Credit
This issue was discovered and reported by GHSL team member @kevinbackhouse (Kevin Backhouse).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2021-045
in any communication regarding this issue.
Disclosure Policy
This report is subject to our coordinated disclosure policy.