
PoC & Exploit per CVE-2025-32023 / PlaidCTF 2025 "Zerodeo"
PoC & Exploit per CVE-2025-32023 (GHSA-rp2m-q4j6-gr43) / PlaidCTF 2025 "Zerodeo"
Testato contro redis:7.4.2-alpine3.21@sha256:02419de7eddf55aa5bcf49efb74e88fa8d931b4d77c07eff8a6b2144472b6952
Riguarda le versioni di Redis >= 2.8. Corretto in 8.0.3, 7.4.5, 7.2.10, 6.2.19, vedi redis/redis@5018874.
L'HyperLogLog in Redis è semplicemente un'altra stringa con le sue codifiche personalizzate. Iterare su una codifica HLL sparsa richiede di sommare le lunghezze dei run di ciascuna rappresentazione sparsa, il che può far traboccare la lunghezza totale contata in int i in un valore negativo quando si opera su un HLL malformato. Ciò consente a un attaccante di scrivere a offset negativi sulla struttura HLL, portando a una scrittura fuori dai limiti sullo stack/heap a seconda della provenienza della struttura HLL (ad es. hllMerge() ne usa una allocata sullo stack, hllSparseToDense() ne usa una allocata sull'heap).
Vedi il frammento di patch qui sotto:
int hllMerge(uint8_t *max, robj *hll) {
struct hllhdr *hdr = hll->ptr;
int i;
if (hdr->encoding == HLL_DENSE) {
hllMergeDense(max, hdr->registers);
} else {
uint8_t *p = hll->ptr, *end = p + sdslen(hll->ptr);
long runlen, regval;
+ int valid = 1;
p += HLL_HDR_SIZE;
i = 0;
while(p < end) {
if (HLL_SPARSE_IS_ZERO(p)) {
runlen = HLL_SPARSE_ZERO_LEN(p);
+ if ((runlen + i) > HLL_REGISTERS) { /* Overflow. */
+ valid = 0;
+ break;
+ }
i += runlen;
p++;
} else if (HLL_SPARSE_IS_XZERO(p)) {
runlen = HLL_SPARSE_XZERO_LEN(p);
+ if ((runlen + i) > HLL_REGISTERS) { /* Overflow. */
+ valid = 0;
+ break;
+ }
i += runlen;
p += 2;
} else {
runlen = HLL_SPARSE_VAL_LEN(p);
regval = HLL_SPARSE_VAL_VALUE(p);
- if ((runlen + i) > HLL_REGISTERS) break; /* Overflow. */
+ if ((runlen + i) > HLL_REGISTERS) { /* Overflow. */
+ valid = 0;
+ break;
+ }
while(runlen--) {
if (regval > max[i]) max[i] = regval;
i++;
}
p++;
}
}
- if (i != HLL_REGISTERS) return C_ERR;
+ if (!valid || i != HLL_REGISTERS) return C_ERR;
}
return C_OK;
}
Questo exploit è un pwnable Redis standard: