
OPNsense 26.7.6 – Hoch – Remote – Umgehung der Netzwerkzugriffskontrolle – Captive Lastseen Roam
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · opnsense-captive-lastseen-roam
Klasse: Umgehung der Netzwerkzugriffskontrolle Reichweite: Remote
OPNsense-Kern 26.7.6 (a842fe48) - opnsense.org
Captive-Portal-Roaming erbt weiterhin eine Sitzung für den neuesten hostwatch-IPv4 auf einer MAC, plus jeden IPv6. GHSA-864r (26.7.3) hat „jeden IPv4 hinzufügen" gestoppt. Der übrig gebliebene IPv4 ist list_hosts.py ORDER BY last_seen DESC. Die primäre IP wird dann aus dem ungefilterten current_ips[0] zugewiesen. Gratuitous ARP attacker_IP is-at victim_MAC aktualisiert last_seen. Nach 26.7.3 ist dieser IPv4 nicht einer von vielen; es ist der IPv4, den der Filter behält, wenn er neuer ist als das eigene ARP des Opfers. IPv6-NDP wurde nie begrenzt. Roaming und hostwatch standardmäßig aktiviert.
Dieses GitHub-Paket bleibt privat bis zur koordinierten Offenlegung.
| ID | noch keine CVE |
| Klasse | Umgehung der Netzwerkzugriffskontrolle |
| Reichweite | Remote (L2-angrenzend, Captive-Portal-Zone) |
| CWE | CWE-345 / CWE-863 |
| CVSS | Hoch: 7.4 CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:N |
| Produkt | OPNsense core |
| Betroffen | 26.7.6 (a842fe48c21288d11a422cb944678e8eb308becf) Captive-Portal-Roaming |
| Auth | Unauth L2-angrenzender Host in einer Captive-Portal-Zone; Roaming aktiv |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1 |
Ich habe den Tag 26.7.6 gepinnt, Peel a842fe48. Das Lab ist ein Python-Gadget der gepinnten _filter_addresses / list_hosts.py / arp.py-Zeilen, Loopback-Wait auf 127.0.0.1:18820.
| Methode | Sink | Privileg |
|---|---|---|
| Neuester hostwatch-IPv4 für eine MAC mit roaming=1 | pin _filter_addresses / list_hosts.py ORDER BY last_seen DESC; primär aus ungefiltertem current_ips[0] | Integrität (lab-belegt): Angreifer 192.0.2.99 behalten, Opfer 192.0.2.10 verworfen, primär=192.0.2.99. Lab: attacker-ipv4-kept=192.0.2.99 victim-ipv4-dropped=yes roaming=1. |
| Gleiche MAC, roaming=0 | _filter_addresses gibt [addresses[0]] zurück | Negativ (lab-belegt): erster IPv4 192.0.2.10 behalten. |
| IPv6 auf derselben MAC, roaming=1 | _filter_addresses behält jeden Nicht-v4 | Integrität (lab-belegt): alle IPv6 behalten (2001:db8::10 und 2001:db8::99). |
| Gefälschtes GARP / NDP, das hostwatch unter der Opfer-MAC speichert | live PF.add_to_table / IPFW.add_accounting auf __captiveportal_zone_N | Integrität (abgeleitet): Angreifer-Quell-IP stimmt mit der Portal-Pass-Tabelle überein. Sitzungs-Benutzername und Quota bleiben die des Opfers. Live-GARP auf dem Draht und Live-Zonen-Tabellen-Pass werden in diesem Gadget nicht ausgeführt. |
| Gleicher Tabelleneintrag | ipfw-Accounting-Regelnummer pro Sitzung | Integrität (abgeleitet): Angreifer-Bytes zählen auf der Opfer-Sitzung. |
| Opfer-IPv4 nicht mehr an erster Stelle | _remove_client / pf-Löschung von Adressen, die nicht in list_session_ips sind | Verfügbarkeit (abgeleitet): Opfer-IPv4 kann aus der Zonentabelle fallen, während der Angreifer-IPv4 bleibt. |
Lab-belegt vs. abgeleitet: last_seen IPv4 behalten/verwerfen, roaming=0 erste-IP und IPv6-alle sind Lab-ERFOLG. Gefälschtes GARP auf dem Draht, Live-pf/ipfw-Pass und Accounting-Smear sind abgeleitet. Gadget, keine vollständige OPNsense-FreeBSD-VM.
Erfordert: L2-angrenzender unauth Host in einer Captive-Portal-Zone. Roaming aktiv (Standard). Hostwatch aktiv (Standard). Eine bereits autorisierte Sitzung in dieser Zone.
| Angriffsfläche | Lab |
|---|---|
| GHSA-864r add-every-IPv4 | geschlossen in 26.7.3; dieser Rest ist der last_seen-IPv4 plus alle IPv6 |
| roaming=0 | erster IPv4 behalten; Angreifer-IPv4 nicht ausgewählt |
XFF / X-Real-Ip-Spoof einer anderen Logon-IP | Zonen-Proxy hängt an; kein sauberes pf-CIDR |
Unauth logon der Aufrufer-IP | dokumentierter Portal-Login von getClientIp() |
| Voucher-Brute auf Standard 8+10 CSPRNG | nicht dieser Rest |
| Template-Zip-Slip | realpath plus Admin-Upload |
| Portal-Splash-XSS zum WebGUI-Origin | anderer Port / chroot |
| WAN-unauth | L2-angrenzend in der Zone |
| WebGUI / root / Voucher-Mint | bleibt geschlossen |
Kein unauth WebGUI. Kein root. Kein WAN-Umgehen des Portals.
cd lab
./run.sh
Loopback-Wait 127.0.0.1:18820. Compose-Projekt opnsense-captive-lastseen-roam. Image-Tag aus diesem Compose. Witness OPNSENSE-CAPTIVE-LASTSEEN-ROAM-WITNESS. Letzte Zeile:
SUCCESS opnsense-captive-lastseen-roam attacker-ipv4-kept=192.0.2.99 victim-ipv4-dropped=yes roaming=1 OPNSENSE-CAPTIVE-LASTSEEN-ROAM-WITNESS
Root-Launcher: python3 opnsense-captive-lastseen-roam-Abraxas-Labs.py.
Wähle den IPv4, den die Sitzung bereits autorisiert hat, nicht die neueste hostwatch-Zeile für diese MAC. Begrenze IPv6 auf dieselbe Weise, oder erfordere NDP, das der Kernel noch hält. Weise nicht primär aus ungefiltertem current_ips[0] zu, wenn der Filter bereits eine andere Adresse gewählt hat. Behandle ein GARP, das nur last_seen aktualisiert, als nicht vertrauenswürdige Beobachtung, was die GHSA-864r-Invariante ist.
a842fe48c21288d11a422cb944678e8eb308becfcp-background-process.py _filter_addresses und Primary-IP-Rewritelist_hosts.py ORDER BY last_seen DESClib/arp.py get_all_addresses_by_mac