
OPNsense 26.7.6 - Alto - Remoto - Bypass dell'accesso alla rete - captive lastseen roam
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · opnsense-captive-lastseen-roam
Classe: Bypass del controllo di accesso alla rete Portata: Remoto
OPNsense core 26.7.6 (a842fe48) - opnsense.org
Il roaming del portale captive eredita ancora una sessione per l'IPv4 più recente di hostwatch su un MAC, più ogni IPv6. GHSA-864r (26.7.3) ha fermato "aggiungi ogni IPv4". L'IPv4 residuo è list_hosts.py ORDER BY last_seen DESC. L'IP primario viene poi assegnato da current_ips[0] non filtrato. Un ARP gratuito attacker_IP is-at victim_MAC aggiorna last_seen. Dopo la 26.7.3 quell'IPv4 non è uno tra tanti; è l'IPv4 che il filtro mantiene se è più recente dell'ARP della vittima stessa. L'NDP IPv6 non è mai stato limitato. Roaming e hostwatch attivi di default.
Questo pacchetto GitHub resta privato fino alla divulgazione coordinata.
| ID | nessuna CVE al momento |
| Classe | Bypass del controllo di accesso alla rete |
| Portata | Remoto (adiacente al L2, zona captive-portal) |
| CWE | CWE-345 / CWE-863 |
| CVSS | Alto: 7.4 CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:N |
| Prodotto | OPNsense core |
| Affetto | 26.7.6 (a842fe48c21288d11a422cb944678e8eb308becf) captive portal roaming |
| Auth | Host non autenticato adiacente al L2 su una zona captive-portal; roaming attivo |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Ho fissato il tag 26.7.6 peel a842fe48. Il lab è un gadget Python delle righe fissate _filter_addresses / list_hosts.py / arp.py, attesa su loopback 127.0.0.1:18820.
| Metodo | Sink | Privilegio |
|---|---|---|
| IPv4 più recente di hostwatch per un MAC con roaming=1 | pin _filter_addresses / list_hosts.py ORDER BY last_seen DESC; primario da current_ips[0] non filtrato | Integrità (dimostrato in lab): attaccante 192.0.2.99 mantenuto, vittima 192.0.2.10 scartata, primario=192.0.2.99. Lab: attacker-ipv4-kept=192.0.2.99 victim-ipv4-dropped=yes roaming=1. |
| Stesso MAC, roaming=0 | _filter_addresses restituisce [addresses[0]] | Negativo (dimostrato in lab): primo IPv4 192.0.2.10 mantenuto. |
| IPv6 sullo stesso MAC, roaming=1 | _filter_addresses mantiene ogni non-v4 | Integrità (dimostrato in lab): tutti gli IPv6 mantenuti (2001:db8::10 e 2001:db8::99). |
| GARP / NDP falsificato che hostwatch memorizza sotto il MAC della vittima | PF.add_to_table / IPFW.add_accounting live su __captiveportal_zone_N | Integrità (inferito): l'IP sorgente dell'attaccante corrisponde alla tabella di passaggio del portale. Username e quota della sessione restano della vittima. GARP live sul filo e passaggio live della tabella di zona non vengono eseguiti in questo gadget. |
| Stessa aggiunta alla tabella | numero di regola di accounting ipfw per sessione | Integrità (inferito): i byte dell'attaccante contano sulla sessione della vittima. |
| IPv4 della vittima non più primo | _remove_client / eliminazione pf degli indirizzi non presenti in list_session_ips | Disponibilità (inferito): l'IPv4 della vittima può cadere dalla tabella di zona mentre l'IPv4 dell'attaccante resta. |
Dimostrato in lab vs inferito: mantenimento/scarto dell'IPv4 last_seen, primo-IP con roaming=0 e IPv6-tutti sono SUCCESS in lab. GARP falsificato sul filo, passaggio pf/ipfw live e contaminazione dell'accounting sono inferiti. Gadget, non una VM OPNsense FreeBSD completa.
Richiede: host non autenticato adiacente al L2 su una zona captive-portal. Roaming attivo (default). Hostwatch attivo (default). Una sessione già autorizzata su quella zona.
| Superficie | Lab |
|---|---|
| GHSA-864r add-every-IPv4 | chiuso sulla 26.7.3; questo residuo è l'IPv4 last_seen più tutti gli IPv6 |
| roaming=0 | primo IPv4 mantenuto; IPv4 dell'attaccante non selezionato |
Spoof XFF / X-Real-Ip di un IP di logon diverso | il proxy di zona accoda; non è un CIDR pf pulito |
logon non autenticato dell'IP del chiamante | login documentato del portale di getClientIp() |
| Brute force voucher su CSPRNG default 8+10 | non questo residuo |
| Zip-slip del template | realpath più upload admin |
| XSS dello splash del portale verso l'origine WebGUI | porta / chroot diversi |
| WAN non autenticato | adiacente al L2 sulla zona |
| WebGUI / root / conio voucher | resta chiuso |
Nessuna WebGUI non autenticata. Nessun root. Nessun salto del portale da WAN.
cd lab
./run.sh
Attesa su loopback 127.0.0.1:18820. Progetto Compose opnsense-captive-lastseen-roam. Tag immagine da quel compose. Witness OPNSENSE-CAPTIVE-LASTSEEN-ROAM-WITNESS. Ultima riga:
SUCCESS opnsense-captive-lastseen-roam attacker-ipv4-kept=192.0.2.99 victim-ipv4-dropped=yes roaming=1 OPNSENSE-CAPTIVE-LASTSEEN-ROAM-WITNESS
Launcher root: python3 opnsense-captive-lastseen-roam-Abraxas-Labs.py.
Scegliere l'IPv4 che la sessione ha già autorizzato, non la riga hostwatch più recente per quel MAC. Limitare l'IPv6 allo stesso modo, o richiedere NDP che il kernel detiene ancora. Non assegnare il primario da current_ips[0] non filtrato quando il filtro ha già scelto un indirizzo diverso. Trattare un GARP che aggiorna solo last_seen come osservazione non attendibile, che è l'invariante di GHSA-864r.
a842fe48c21288d11a422cb944678e8eb308becfcp-background-process.py _filter_addresses e riscrittura dell'IP primariolist_hosts.py ORDER BY last_seen DESClib/arp.py get_all_addresses_by_mac