Multiple vulnerabilities in radare2
CENSUS ID: | CENSUS-2022-0001 |
CVE IDs: | CVE-2022-0419, CVE-2021-44974, CVE-2021-44975 |
Affected Products: | radare2 versions prior to 5.6.0 |
Class: | NULL pointer dereference (CWE-476), Heap-based buffer overflow (CWE-122) |
Discovered by: | Angelos T. Kalaitzidis |
CENSUS identified a number of NULL pointer dereference and Heap buffer overflow bugs in the radare2 project code. Radare2 is a popular reverse engineering framework. CENSUS has verified that release 5.6.0 of radare2 carries the appropriate fixes to remediate all of the identified issues.
CVE-2022-0419 Vulnerability Details
Function load_buffer of radare2/libr/bin/p/bin_xnu_kernelcache.c uses a pointer (obj) which remains initialized to NULL, when a call to function get_prelink_info_range_from_mach0() fails (i.e. returns NULL). The code snippet below shows this problematic code path:
static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadaddr, Sdb *sdb) {
...
189 RKernelCacheObj *obj = NULL; // 1
191 RPrelinkRange *prelink_range = get_prelink_info_range_from_mach0 (main_mach0);
192 if (!prelink_range) {
193 goto beach; // 2
194 }
....
243 beach:
244 r_buf_free (fbuf);
245 obj->cache_buf = NULL; // 3
244 MACH0_(mach0_free) (main_mach0);
245 return false;
When get_prelink_info_range_from_mach0() returns NULL, obj remains NULL and the code branches to line 243. There an access to the obj pointer is made on line 245, resulting to a NULL pointer dereference and a program crash.
The issue has been patched in version 5.6.0 of radare2.
CVE-2021-44975 Vulnerability Details
The objc_build_refs function is responsible for building the references of a mach-o file as its name suggests. The function can be found out at /radare2/libr/core/anal_objc.c
static bool objc_build_refs(RCoreObjc *objc) {
...
size_t ss_selrefs = objc->_selrefs->vsize;
size_t maxsize = R_MAX (ss_const, ss_selrefs); // 1
maxsize = R_MIN (maxsize, objc->file_size);
ut8 *buf = calloc (1, maxsize);
if (!buf) {
return false;
}
...
if (!r_io_read_at (objc->core->io, va_selrefs, buf, ss_selrefs)) { // 2
eprintf ("aao: Cannot read the whole selrefs section\n");
return false;
}
...
free (buf);
return true;
}
At comment #1 the maxsize quantity is calculated based on the largest value between ss_const and ss_selrefs (see R_MAX macro). Lets consider that the largest of the two is ss_selrefs. Then maxsize is recalculated based on the lowest value (see R_MIN macro) between the previously calculated maxsize and objc->file_size. Therefore, there may be a case where ss_selrefs will be greater than objc->file_size and in that case maxsize will be equal to objc->file_size.
In the above case, buffer buf is dynamically allocated with maxsize (i.e. objc->file_size) bytes. However the r_io_read_at() operation at comment #2 will copy ss_selrefs bytes to the buffer, resulting to a heap buffer overflow as ss_selrefs would be greater than objc->file_size.
A similar vulnerability also exists in other code of the same function:
size_t ss_const = objc->_const->vsize;
....
if (!r_io_read_at (objc->core->io, objc->_const->vaddr, buf, ss_const)) {
eprintf ("aao: Cannot read the whole const section %zu\n", ss_const);
return false;
}
Again, ss_const can be greater than objc->file_size resulting to a heap buffer overflow.
Version 5.6.0 of radare2 comes with the appropriate fix for these issues.
CVE-2021-44974 Vulnerability Details
A NULL pointer dereference vulnerability exists in the symbols() function of /radare2/libr/bin/bin_symbols.c.
static RList *symbols(RBinFile *bf) {
RCoreSymCacheElement *element = bf->o->bin_obj;
...
// Parse symbols to a hash table
for (i = 0; i < element->hdr->n_symbols; i++) {
RCoreSymCacheElementSymbol *sym = &element->symbols[i]; // 1
ht_uu_find (hash, sym->paddr, &found);
if (found) {
continue;
}
RBinSymbol *s = bin_symbol_from_symbol (element, sym);
if (s) {
r_list_append (res, s);
}
}
ht_uu_free (hash);
return res;
}
As illustrated in the code snippet above, the element pointer points to adversary-controlled data (as bf->o->bin_obj essentially points to data of the binary file). The element->symbols array, is an array of symbols for an object of the file that is being loaded for analysis. In the case where the pointer element->symbols[0] is NULL (which is possible as we are talking about adversary-controlled data) the sym pointer would also be set to NULL (see comment #1). Then in the next line sym is accessed through the sym->paddr expression and this leads to a NULL pointer dereference and a program crash.
This issue has been patched in version 5.5.4 of radare2.
Recommendation
CENSUS advises users to use a radare2 version greater or equal to 5.6.0, as this version carries appropriate patches that remediate correctly all of the aforementioned issues.
Disclosure Timeline
Vendor Contact: | December 7, 2021 |
CVE Allocation: | December 13, 2021 |
Vendor Fix Released: | February 2, 2022 |
Public Advisory: | May 24, 2022 |