# HTTP2Shell: la vulnerabilità di Brotli che colpisce anche WordPress

> HTTP2Shell (CVE-2026-111497, CVSS 9.2) è una falla nel decoder Brotli che Wordfence ha sfruttato in laboratorio contro WordPress tramite i pingback XML-RPC, anche con PHP 8.3.36 aggiornato. Chi è esposto, come verificarlo e come correggerla.

- Autore / Author: Diego Betto (https://diegobetto.com/about/)
- Pubblicato / Published: 2026-11-03
- URL: https://diegobetto.com/http2shell-vulnerabilita-brotli-wordpress/
- Tag: wordpress, security, php

A due settimane da [PHP2Shell](/php2shell-vulnerabilita-critiche-php/), un altro bug "2Shell" preoccupa chi gestisce siti WordPress. Si chiama **HTTP2Shell** (anche Node2Shell o Brotli2Shell), è tracciato come **CVE-2026-111497** con punteggio **CVSS v4.0 9.2** e non sta né in WordPress né in PHP: sta in **Brotli**, la libreria di compressione di Google che mezzo stack web usa per decodificare le risposte HTTP compresse.

Il <time datetime="2026-11-02">2 novembre 2026</time> Alex Thomas del team Threat Intelligence di Wordfence ha pubblicato un'[analisi di cosa significa per WordPress](https://www.wordfence.com/blog/2026/11/http2shell-wordpress-brotli/): in un laboratorio isolato ha ottenuto l'**esecuzione di codice senza autenticazione** su un sito WordPress sfruttando i pingback XML-RPC, su un server con **PHP 8.3.36**, cioè la release che corregge già PHP2Shell.

> **Aggiornare PHP non basta**
>
> La falla è nella libreria Brotli di sistema, non in PHP o in WordPress. Un WordPress aggiornato su un PHP corretto può essere comunque esposto se il server carica una `libbrotli` vulnerabile. La correzione è **aggiornare Brotli e riavviare** i processi che la usano.

## In sintesi

| | |
| --- | --- |
| **Nome** | HTTP2Shell, anche Node2Shell / Brotli2Shell (HTTP/2 non c'entra) |
| **CVE** | CVE-2026-111497 (pubblicata da Google) |
| **Gravità** | CVSS v4.0 9.2 |
| **Tipo** | Scrittura fuori dai limiti nel decoder Brotli: crash, fuga di memoria o RCE |
| **Versioni vulnerabili** | Brotli **1.0.3 – 1.0.9**, **1.1.0**, **1.2.0** |
| **Versioni corrette** | Brotli **1.0.10**, **1.1.1**, **1.2.1** (e backport delle distribuzioni) |
| **Percorso in WordPress** | `pingback.ping` non autenticato via `xmlrpc.php`, riprodotto in laboratorio da Wordfence |
| **Sfruttamento** | Nel catalogo CISA KEV dal 27 ottobre 2026; scansioni e tentativi osservati, nessuna compromissione in produzione via WordPress documentata in modo verificabile |

## Qual è il bug

Brotli è un formato di compressione usato da browser e server come alternativa a gzip (`Content-Encoding: br`). Il bug è in `DecodeBlockTypeAndLength()` nel decoder C: un valore di ritorno non viene controllato (CWE-252), quindi il decoder non distingue "dati malformati" da "servono altri dati" e finisce per **scrivere fuori dai limiti** del buffer (CWE-787). Un flusso compresso costruito ad arte può corrompere la memoria del processo che lo decodifica.

Secondo [Upwind](https://www.upwind.io/feed/http2shell-cve-2026-111497-one-brotli-bug-rce-across-the-http-stack), il bug è stato segnalato da OpenAI a febbraio 2026 e corretto nel codice già allora, ma nessuna release ha incluso la correzione fino a ottobre. È emerso il <time datetime="2026-10-21">21 ottobre</time> come bug di Node.js (da qui "Node2Shell") e si è capito presto che il problema sta nella libreria C condivisa: sono coinvolti Node.js, i pacchetti Python (`Brotli`, `brotlicffi`), Bun, Envoy e ogni programma collegato a una `libbrotli` vulnerabile, curl compreso.

## Cosa c'entra WordPress

WordPress non decomprime Brotli da solo. Però fa **richieste HTTP in uscita**, e il client HTTP sottostante (sulla maggior parte dei server l'estensione curl di PHP, cioè libcurl) può passare una risposta compressa `br` al decoder Brotli di sistema. Se un attaccante riesce a far **scaricare a WordPress un URL che controlla**, può servire una risposta compressa malevola e raggiungere il codice vulnerabile dall'interno del worker PHP.

Nel WordPress standard, Wordfence ha trovato un solo percorso chiaro senza autenticazione: i **pingback**. Quando qualcuno chiama `pingback.ping` su `xmlrpc.php`, WordPress scarica la pagina sorgente per verificare che contenga davvero un link al tuo articolo. Quell'URL sorgente lo sceglie l'attaccante.

Perché l'attacco funzioni devono essere vere tutte queste condizioni:

- `xmlrpc.php` è raggiungibile;
- il metodo `pingback.ping` è registrato;
- l'articolo bersaglio accetta i ping;
- il server può fare richieste in uscita;
- il client HTTP usa il decoder Brotli vulnerabile;
- il payload corrisponde alla build di PHP e alla disposizione della memoria del server.

Le altre funzioni del core che scaricano URL richiedono autenticazione, permessi aggiuntivi o controllo sui contenuti. **Plugin e temi possono però aggiungere nuovi percorsi**: qualunque funzione che scarica un URL fornito da un visitatore è un candidato.

> **'Disable XML-RPC authentication' non blocca i pingback**
>
> Wordfence sottolinea che la sua opzione **Disable XML-RPC authentication** blocca i tentativi di login via XML-RPC, ma **non disattiva i pingback non autenticati**. Non darti per protetto solo perché quella casella è spuntata.

## Cosa ha dimostrato Wordfence in laboratorio

L'ambiente di test era volutamente realistico: container isolati con **WordPress 7.1.3**, **Debian 13.7**, **Apache 2.4.69**, **PHP 8.3.36 (mod_php)** e `libbrotli1` **1.1.0-2+b7**, con ASLR attivo.

- **Brotli vulnerabile**: il proof of concept pubblico ha eseguito codice senza autenticazione.
- **Brotli aggiornato** al pacchetto corretto di Debian, senza cambiare altro: la stessa sequenza non ha eseguito codice e il server è rimasto in salute.
- **PHP 8.3.35**: il payload non ha eseguito codice; in un ambiente ha **mandato in crash il worker PHP**.

La conclusione: il payload pubblico **non è universale**, dipende dalla build esatta. Ma i server costruiti dalle stesse immagini (stessa base Docker, stessi pacchetti della distribuzione) condividono la stessa disposizione della memoria, quindi un payload funzionante può essere riutilizzato su molti di loro.

Wordfence fa notare anche che dall'esterno un attaccante di solito riesce a capire che il sito usa WordPress, quale PHP e quale web server, se XML-RPC è aperto e come fa le richieste in uscita: abbastanza per scegliere un payload preparato per un'immagine server diffusa. Quello che le normali richieste non rivelano è la build binaria esatta e la disposizione della memoria necessarie per adattare il payload a un server qualsiasi, e Wordfence non ha dimostrato di poterlo fare. Gli attacchi indiscriminati sono quindi meno affidabili, quelli mirati contro immagini standard restano plausibili.

## Viene sfruttata?

Il quadro al <time datetime="2026-11-02">2 novembre 2026</time>, secondo Wordfence:

- **CISA** ha aggiunto CVE-2026-111497 al catalogo **Known Exploited Vulnerabilities** il <time datetime="2026-10-27">27 ottobre</time>, senza indicare applicazione, percorso o esito.
- **Check Point** segnala scansioni automatiche e payload sospetti, nessuna compromissione confermata. **Previdian** continua a osservare tentativi, ma non può dire se i bersagli fossero vulnerabili.
- **ELLIO** ha catturato un tentativo contro Node.js il cui payload non ha prodotto una shell in 50 ripetizioni su un bersaglio vulnerabile equivalente. **Imperva** ed ELLIO hanno dimostrato una RCE su build vulnerabili di Node.js, in laboratorio.
- Nessuna segnalazione verificabile in modo indipendente di una compromissione in produzione, e nessuna tramite i pingback di WordPress.

Dato che la scheda CISA non dà dettagli, l'assenza di un caso pubblico **non significa che nessuno sia stato compromesso**. In breve: i tentativi ci sono, compromissioni di massa non sono documentate. Non è un buon motivo per aspettare.

## Sono esposto?

La versione di WordPress non dice nulla: conta la libreria Brotli caricata dal processo che serve il sito.

### Hosting gestito o condiviso

Fai al provider due domande precise: il processo che serve il mio sito usa un **decoder Brotli corretto**? I servizi sono stati **riavviati o rideployati** dopo l'aggiornamento?

### Server tuo

Controlla il pacchetto Brotli installato. Le distribuzioni fanno **backport** della correzione senza cambiare la versione base, quindi confronta la revisione completa con il bollettino del tuo vendor (per esempio su Debian 13 la correzione è in `libbrotli1` **1.1.0-2+deb13u1**; vedi anche [Ubuntu USN-8956-1](https://ubuntu.com/security/notices/USN-8956-1) e [Amazon Linux ALAS2023-2026-3334](https://alas.aws.amazon.com/AL2023/ALAS2023-2026-3334.html)):

```bash
# Debian/Ubuntu
dpkg -l 'libbrotli*'

# RHEL, Alma, Rocky, Amazon Linux
rpm -qa 'brotli*' 'libbrotli*'

# curl (e quindi l'estensione curl di PHP) supporta brotli?
curl -V | grep -io brotli
```

Per verificare se `pingback.ping` è disponibile sul tuo sito, usa la chiamata non autenticata `system.listMethods`. Ti dice solo che il metodo esiste, non che il sito sia sfruttabile:

```bash
curl -s https://example.com/xmlrpc.php \
  -H 'Content-Type: text/xml' \
  --data '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName></methodCall>' \
  | grep -o 'pingback.ping'
```

## Come correggere

### 1. Aggiorna Brotli e riavvia

Installa il pacchetto corretto del tuo vendor, poi **riavvia ogni processo che aveva caricato la vecchia libreria**: Apache, PHP-FPM e qualunque altro. Finché non riavvii, il vecchio codice resta in memoria.

```bash
# Debian/Ubuntu
sudo apt update && sudo apt install --only-upgrade 'libbrotli*'
sudo systemctl restart apache2        # se usi mod_php
sudo systemctl restart php8.3-fpm     # adatta alle tue versioni

# processi che usano ancora la vecchia libreria cancellata
sudo lsof 2>/dev/null | grep -i 'libbrotli.*deleted'
```

- **Container**: ricostruisci e rideploya da un'immagine base aggiornata. Riavviare il container esistente non basta.
- **CloudLinux e stack simili**: possono esserci più copie di Brotli (sistema, web server, PHP incluso nel pannello). Aggiornale tutte; CloudLinux ha una [lista dedicata dei pacchetti](https://cloudlinux.zendesk.com/hc/en-us/articles/31345594031132-Brotli-CVE-2026-111497-on-CloudLinux-OS-affected-packages-and-fixed-versions).
- **Agenzie e hosting provider**: controlla ogni ambiente, produzione, **staging** e vecchie installazioni. Un solo controllo dei pacchetti non copre tutti i pool PHP, i container o le immagini server.
- **Node.js sullo stesso server**: corretto in 22.23.4, 24.22.1 e 26.12.1. Le linee 20, 23 e 25 sono a fine vita e non riceveranno correzioni.

### 2. Chiudi il percorso di WordPress (come tampone)

Se non usi i pingback (e quasi nessuno li usa), disattivarli elimina il percorso dimostrato da Wordfence. **Non corregge la libreria**, toglie solo una strada per arrivarci. Il modo più rapido è un mu-plugin:

```php
<?php
// wp-content/mu-plugins/disable-pingbacks.php
add_filter('xmlrpc_methods', function (array $methods): array {
    unset($methods['pingback.ping'], $methods['pingback.extensions.getPingbacks']);
    return $methods;
});
```

Attenzione: il filtro `xmlrpc_enabled`, spesso consigliato per "spegnere XML-RPC", agisce solo sui metodi che richiedono autenticazione e, come dice la documentazione di WordPress, **non disattiva `pingback.ping`**. Per questo lo snippet qui sopra rimuove il metodo in modo esplicito.

Se XML-RPC non ti serve affatto (niente Jetpack, niente vecchie app mobile), puoi bloccare `xmlrpc.php` a livello di web server. Ricorda che **Impostazioni → Discussione** vale solo per i nuovi articoli: quelli esistenti mantengono la propria impostazione sui ping. E verifica prima di spegnere qualcosa: cambiare il comportamento di XML-RPC o dei pingback può rompere integrazioni legittime.

### 3. Cerca segni di compromissione

- **Conserva i log** (web server, PHP, processi, firewall, traffico in uscita) dal periodo precedente alla divulgazione fino all'aggiornamento e al riavvio.
- Cerca **richieste di pingback inattese**, **connessioni in uscita insolite** dall'utente PHP e **crash o riavvii** dei worker PHP o Apache. La loro assenza non dimostra che non sia successo nulla.
- Se sospetti una compromissione, **isola prima il sistema**, poi ruota credenziali, chiavi e salt. Nell'ordine inverso, un attaccante ancora dentro vede i nuovi segreti.

> **Non eseguire PoC trovati su GitHub**
>
> Come per PHP2Shell, esiste un proof of concept pubblico per WordPress, e parecchi finti. Non eseguirli in produzione: se vuoi fare test, usa un ambiente isolato e codice che hai letto riga per riga.

## Cronologia

- **Febbraio 2026** — OpenAI segnala il bug; Brotli corregge il codice, ma senza una release.
- **<time datetime="2026-10-21">21 ottobre 2026</time>** — Node.js divulga e corregge il bug ("Node2Shell"); escono Brotli 1.0.10, 1.1.1 e 1.2.1.
- **<time datetime="2026-10-22">22 ottobre 2026</time>** — Google pubblica CVE-2026-111497; un advisory GitHub conferma che sono coinvolti i pacchetti Python `Brotli` e `brotlicffi`.
- **<time datetime="2026-10-23">23 ottobre 2026</time>** — Il bug viene soprannominato HTTP2Shell.
- **<time datetime="2026-10-27">27 ottobre 2026</time>** — CISA lo aggiunge al catalogo KEV.
- **<time datetime="2026-11-02">2 novembre 2026</time>** — Wordfence pubblica l'analisi per WordPress e i risultati di laboratorio.

## Fonti

- [Wordfence — HTTP2Shell: What the Critical Brotli Vulnerability Means for WordPress Sites](https://www.wordfence.com/blog/2026/11/http2shell-wordpress-brotli/)
- [CVE.org — CVE-2026-111497](https://www.cve.org/CVERecord?id=CVE-2026-111497)
- [GitHub — Release Brotli 1.2.1](https://github.com/google/brotli/releases/tag/v1.2.1)
- [GitHub — Correzione upstream di Brotli](https://github.com/google/brotli/commit/0ed4268a4401abcb4472096340477cf4af7d1a2b)
- [CISA — Known Exploited Vulnerabilities catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-111497)
- [Debian Security Tracker — CVE-2026-111497](https://security-tracker.debian.org/tracker/CVE-2026-111497)
- [Ubuntu — USN-8956-1](https://ubuntu.com/security/notices/USN-8956-1)
- [Amazon Linux — ALAS2023-2026-3334](https://alas.aws.amazon.com/AL2023/ALAS2023-2026-3334.html)
- [Upwind — HTTP2Shell: one Brotli bug, RCE across the HTTP stack](https://www.upwind.io/feed/http2shell-cve-2026-111497-one-brotli-bug-rce-across-the-http-stack)
- [Check Point — HTTP2Shell: the Brotli vulnerability that extends beyond Node.js](https://blog.checkpoint.com/security/http2shell-the-brotli-vulnerability-that-extends-beyond-node-js/)
- [Tenable — Brotli2Shell FAQ](https://www.tenable.com/blog/brotli2shell-frequently-asked-questions-for-google-brotli-decoder-cve-2026-111497)
- [WordPress Developer Resources — xmlrpc_enabled](https://developer.wordpress.org/reference/hooks/xmlrpc_enabled/)
- [WordPress Developer Resources — pingback_ping()](https://developer.wordpress.org/reference/classes/wp_xmlrpc_server/pingback_ping/)

Se non l'hai ancora fatto, ripassa anche la mia [checklist di sicurezza WordPress](https://diegobetto.com/wordpress-security-checklist/) e verifica che il server sia su una release di PHP che corregge [PHP2Shell](/php2shell-vulnerabilita-critiche-php/): i due bug sono indipendenti e servono entrambe le correzioni.
