openssl / openssl/openssl

BIO buffer APIs allow negative length → heap corruption, missing input validation (OpenSSL 3.0.2, 3.6.1)

Open
#30,725 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

branch: 3.0 branch: 3.3 branch: 3.4 branch: 3.5 branch: 3.6 branch: 4.0 branch: master good first issue triaged: bug
Dominant language
C
Stars
30.8k
Forks
11.5k
Avg merge
10m
Merged PRs (30d)
1

Description

BIO buffer APIs allow negative length → heap corruption, missing input validation (OpenSSL 3.0.2, 3.6.1)

While testing BIO buffer APIs in OpenSSL 3.6.1, I encountered a crash caused by passing a negative length parameter to public API macros.

The issue appears to originate from missing validation of the long num parameter inside buffer_ctrl() in crypto/bio/bf_buff.c.

This report is submitted as a bug / robustness issue, not a confirmed vulnerability.

Environment

  • Ubuntu 22.04.5 LTS (x86_64)
  • Kernel: 6.8.0-1050-aws
  • GCC: 11.4.0
  • OpenSSL (system): 3.0.2
  • OpenSSL (tested): 3.6.1 (manual build)

Summary of Issue

Two BIO control paths accept a signed long num parameter but do not properly validate negative values:

Negative values bypass guard conditions and later reach memcpy() with an implicitly converted large size_t, resulting in crash (heap corruption / invalid memory access).

Affected Code

Heap OOB WRITE (approx. lines 288–301)

case BIO_C_SET_BUFF_READ_DATA:
    if (num > ctx->ibuf_size) {
        if (num <= 0)
            return 0;
        p1 = OPENSSL_malloc((size_t)num);
    }
    ctx->ibuf_off = 0;
    ctx->ibuf_len = (int)num;
    memcpy(ctx->ibuf, ptr, (int)num);

Heap OOB READ (approx. lines 391–401)

case BIO_CTRL_PEEK:
    {
        char fake_buf[1];
        (void)buffer_read(b, fake_buf, 0);
    }
    if (num > ctx->ibuf_len)
        num = ctx->ibuf_len;
    memcpy(ptr, &(ctx->ibuf[ctx->ibuf_off]), num);

Public API Usage

#define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf)
#define BIO_buffer_peek(b,s,l)              BIO_ctrl(b,BIO_CTRL_PEEK,(l),(s))

The large parameter is signed, and negative values are not explicitly rejected in these paths.

**Reproduction **

poc_bio_heap_read.c
poc_bio_heap_write.c

Build

gcc -Wall -g -o poc_bio_heap_write poc_bio_heap_write.c -lssl -lcrypto
gcc -Wall -g -o poc_bio_heap_read  poc_bio_heap_read.c  -lssl -lcrypto

Run

./poc_bio_heap_write
# Result: SIGABRT (heap corruption)
./poc_bio_heap_read
# Result: SIGSEGV
Image

Expected Behavior

The API should reject invalid negative lengths early, for example:

Return error (0 or negative)
Or explicitly validate num >= 0 before use

Actual Behavior
Negative values:
Bypass checks (num > ctx->ibuf_size)
Are cast to int and then implicitly to size_t
Reach memcpy() → crash

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in crypto/bio/bf_buff.c and trace buffer_ctrl() for BIO_C_SET_BUFF_READ_DATA and BIO_CTRL_PEEK. Build and run the two linked proof-of-concept programs first, then inspect the existing tests for BIO buffer controls. Done means invalid negative lengths no longer reach unsafe memory operations and the reproductions complete without a crash, with regression coverage added.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
api, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.