In vquic-tls.c
curl_wssl_init_ctx
errors are handled by goto out
and having result
be set to an error code to be returned. At the beginning of the function result
is correctly set to CURLE_FAILED_INIT
which allows for goto out
to work correctly without having to set result
however, result
’s value is overridden at a certain point if ctx_setup
is passed to the function. If ctx_setup
returns 0 (the expected result) then it’s assigned to result
and any attempt after that to goto out
without setting result
to an error code will make the function skip the rest of its initialization and return with an error code indicating success.
Unfortunately the last thing curl_wssl_init_ctx
is supposed to setup for the ssl context is the certificate verification requirements. There are 4 places goto out
is used without setting result
, of those 3 can result from bad user input (bad tls13-ciphers, curves, or cafile/capath) and 1 is from trying to setup ssl key logging when having a WolfSSL build that doesn’t have wolfSSL_CTX_set_keylog_callback
.
Luckily this does require the user to have passed in bogus values for one of the above parameters which I find very unlikely. Also very fortunately WolfSSL attempts to default to verify a cert rather than OpenSSL’s default of not verifying. There is an option to make WolfSSL have OpenSSL compatible defaults but I don’t know how common it is to have WolfSSL configured like that so I’m not sure how likely it is that people could run into this.
Given the unlikely set of configurations required to encounter this I don’t think this is a “high” vulnerability like the CVSS claims but there is no way of manually setting the score, honestly I would have just submitted a patch to fix this but I’m not to sure on how common having WolfSSL in OpenSSL compatible mode is so I’m err’ing on the side of caution and submitting it here.
I checked the other initialization functions in vquic-tls.c
and it doesn’t look like the same mistake was made in them. result
is assigned before each use of goto out
.
Build WolfSSL with something that sets OPENSSL_COMPATIBLE_DEFAULTS
(I used --enable-nginx
) and build curl with the WolfSSL backend.
Setup a QUIC webserver with a self signed cert that matches the domain being spoofed and attempt to make a HTTP/3 connection to it using curl with a bad --curves
list. curl connects to the site without having set --insecure
, taking out the bad --curves
argument curl will complain about the invalid cert.
ex:
./curl -v --http3-only 'https://example.com/' -o /dev/null -s --resolve example.com:443:192.168.1.24 --curves blah
* Added example.com:443:192.168.1.24 to DNS cache
* Hostname example.com was found in DNS cache
* Trying 192.168.1.24:443...
* wolfSSL failed to set curves
* Verified certificate just fine
* Connected to example.com (192.168.1.24) port 443
* using HTTP/3
* [HTTP/3] [0] OPENED stream for https://example.com/
* [HTTP/3] [0] [:method: GET]
* [HTTP/3] [0] [:scheme: https]
* [HTTP/3] [0] [:authority: example.com]
* [HTTP/3] [0] [:path: /]
* [HTTP/3] [0] [user-agent: curl/8.7.0-DEV]
* [HTTP/3] [0] [accept: */*]
> GET / HTTP/3
> Host: example.com
> User-Agent: curl/8.7.0-DEV
> Accept: */*
>
* We are completely uploaded and fine
< HTTP/3 200
< server: nginx/1.25.4
< date: Sun, 10 Mar 2024 21:02:39 GMT
< content-type: text/html
< content-length: 615
< last-modified: Wed, 14 Feb 2024 16:03:00 GMT
< etag: "65cce434-267"
< accept-ranges: bytes
<
{ [615 bytes data]
* Connection #0 to host example.com left intact
vs
./curl -v --http3-only 'https://example.com/' -o /dev/null -s --resolve example.com:443:192.168.1.24
* Added example.com:443:192.168.1.24 to DNS cache
* Hostname example.com was found in DNS cache
* Trying 192.168.1.24:443...
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* QUIC connect to 192.168.1.24 port 443 failed: SSL peer certificate or SSH remote key was not OK
* Failed to connect to example.com port 443 after 12 ms: SSL peer certificate or SSH remote key was not OK
* Closing connection
This was introduced in https://github.com/curl/curl/pull/12678 so the only vulnerable version to be released is 8.6.0
If the stars align and the user is using such a configuration and passing bad arguments then they would be vulnerable to MITM attacks.