Loading HuntDB...

CVE-2024-7264: ASN.1 date parser overread

Low
C
curl
Submitted None
Reported by dubek

Vulnerability Details

Technical details and impact analysis

Buffer Over-read
## Summary: When a specially-crafted certificate is passed to `Curl_extract_certinfo` to parse, it may read bytes beyond the end of the buffer in which the certificate is held. According to the application, this may be a stack read overflow or a heap read overflow. Specifically the issue is in function `GTime2str`, in which the specially-crafted input may cause it to set `fracl = -1` and then pass it to `Curl_dyn_addf`, which in turn treats this `-1` as "no length given" and goes on to run `strlen(tzp)` which goes beyond the end of the certificate buffer (assuming there are no null bytes). I believe the issue is in this loop (in `lib/vtls/x509asn1.c`): ``` 524 /* Strip leading zeroes in fractional seconds. */ 525 for(fracl = tzp - fracp - 1; fracl && fracp[fracl - 1] == '0'; fracl--) 526 ; ``` If `tzp == fracp`, then `fracl` is set to -1 in the loop initialization. I tested this on curl 8.9.0 commit `2a59c8d4cebfd199f930213ee82ae95f71e44578` (2024-07-24). I haven't looked when the issue was introduced. ## Steps To Reproduce: 1. Compile libcurl with `-fsanitize=address` and with gnutls. I used clang. `CC=clang CFLAGS=-fsanitize=address ../configure --disable-shared --enable-debug --with-gnutls=/usr/lib/aarch64-linux-gnu` 1. Compile the attached `poc.c` program which uses libcurl's `Curl_extract_certinfo`. 1. Run `./poc bad_cert_1.bin` The resulting report from AddressSanitizer: ``` ================================================================= ==2166==ERROR: AddressSanitizer: stack-buffer-overflow on address 0xffffaae02020 at pc 0xaaaad3fedb44 bp 0xffffee270350 sp 0xffffee26fb40 READ of size 4471 at 0xffffaae02020 thread T0 #0 0xaaaad3fedb40 in strlen (/root/work/curl/fuzz2/tests/unit/poc+0x11db40) (BuildId: 950d22dbc354c1f19b0a0459aa9b72f968a5aff4) #1 0xaaaad40dfb58 in formatf /root/work/curl/fuzz2/lib/../../lib/mprintf.c:883:15 #2 0xaaaad40e1f14 in Curl_dyn_vprintf /root/work/curl/fuzz2/lib/../../lib/mprintf.c:1105:9 #3 0xaaaad427c2ec in Curl_dyn_vaddf /root/work/curl/fuzz2/lib/../../lib/dynbuf.c:198:8 #4 0xaaaad427c844 in Curl_dyn_addf /root/work/curl/fuzz2/lib/../../lib/dynbuf.c:231:12 #5 0xaaaad41f0338 in GTime2str /root/work/curl/fuzz2/lib/../../lib/vtls/x509asn1.c:542:10 #6 0xaaaad41ec5fc in ASN1tostr /root/work/curl/fuzz2/lib/../../lib/vtls/x509asn1.c:632:14 #7 0xaaaad41eb410 in Curl_extract_certinfo /root/work/curl/fuzz2/lib/../../lib/vtls/x509asn1.c:1185:12 #8 0xaaaad40b4f4c in main /root/work/curl/fuzz2/tests/unit/poc.c:36:14 #9 0xffffac9b84c0 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #10 0xffffac9b8594 in __libc_start_main csu/../csu/libc-start.c:360:3 #11 0xaaaad3fd886c in _start (/root/work/curl/fuzz2/tests/unit/poc+0x10886c) (BuildId: 950d22dbc354c1f19b0a0459aa9b72f968a5aff4) Address 0xffffaae02020 is located in stack of thread T0 at offset 8224 in frame #0 0xaaaad40b4cc8 in main /root/work/curl/fuzz2/tests/unit/poc.c:9 This frame has 1 object(s): [32, 8224) 'buf' (line 14) <== Memory access at offset 8224 overflows this variable HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow (/root/work/curl/fuzz2/tests/unit/poc+0x11db40) (BuildId: 950d22dbc354c1f19b0a0459aa9b72f968a5aff4) in strlen Shadow bytes around the buggy address: 0xffffaae01d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xffffaae01e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xffffaae01e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xffffaae01f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xffffaae01f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0xffffaae02000: 00 00 00 00[f3]f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 0xffffaae02080: f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 0xffffaae02100: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 0xffffaae02180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xffffaae02200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xffffaae02280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==2166==ABORTING ``` Note that this will only affect libcurl when built with gnutls, schannel, sectransp, mbedtls (only then it'll use `Curl_extract_certinfo`). ## Supporting Material/References: * `poc.c`: The client code to reproduce; it simply reads a file and passes its content to `Curl_extract_certinfo`. The code uses a buffer on the stack, but it also works if you switch it to be a heap buffer (see the commented-out malloc call). * `bad_cert_1.bin`: The certificate with which causes the memory over-read. ## Submitter info * I used LLVM libFuzzer to find this. * If this is accepted, please credit the finding to Dov Murik from Transmit Security. * If this is eligible for any bug bounty, please donate it to the curl project. ## Impact Attacker-controller HTTPS server can return a specially-crafted certificates that can crash libcurl-based clients when fetching the certificates and parsing them. I couldn't see a way where the remote attacker can actually get the content of the over-read memory bytes.

Report Details

Additional information and metadata

State

Closed

Substate

Resolved

Submitted

Weakness

Buffer Over-read