Skip to content

Possible out-of-bounds write to header_data in PcapSession::PacketReady #305

Description

@OvOhao

Possible out-of-bounds write to header_data in PcapSession::PacketReady

I found a possible OOB write (CWE-787) in PcapSession::PacketReady. Dispatch records the
caller's packet buffer and its length (buffer_data/buffer_length) but records only the
pointer of the second "header" buffer (header_data) — never its length. When a packet arrives,
PacketReady clamps the copy into buffer_data to buffer_length, but then unconditionally
writes 16 fixed bytes (four 4-byte fields) into header_data with no size check. If the caller
passes a header Buffer smaller than 16 bytes, those memcpys write past the end of the Buffer's
backing store — a heap out-of-bounds write. The asymmetry with the properly-clamped
buffer_data path confirms the missing check.

File: pcap_session.cc

Function: PcapSession::PacketReady (destination captured in PcapSession::Dispatch)

// Dispatch(): buffer length is captured, header length is NOT
session->buffer_data = node::Buffer::Data(buffer_obj);
session->buffer_length = node::Buffer::Length(buffer_obj);
Local<Object> header_obj = info[1]->ToObject(...).FromMaybe(Local<v8::Object>());
session->header_data = node::Buffer::Data(header_obj);   // no header length stored

// PacketReady(): buffer_data copy is clamped, header_data is not
size_t copy_len = pkthdr->caplen;
if (copy_len > session->buffer_length) copy_len = session->buffer_length;
memcpy(session->buffer_data, packet, copy_len);           // bounded

memcpy(session->header_data,      &(pkthdr->ts.tv_sec),  4);
memcpy(session->header_data + 4,  &(pkthdr->ts.tv_usec), 4);
memcpy(session->header_data + 8,  &(pkthdr->caplen),     4);
memcpy(session->header_data + 12, &(pkthdr->len),        4); // writes bytes 12..15 unconditionally
  1. Dispatch validates both arguments are Buffers but stores no length for the header buffer.
  2. PacketReady writes 16 bytes total to header_data (offsets 0, 4, 8, 12) every time a
    packet is dispatched, with no comparison against the header Buffer's real size.
  3. A header Buffer shorter than 16 bytes therefore takes an out-of-bounds heap write of up to
    16 bytes past its end.

JS trigger (if applicable):

const binding = require('./build/Release/pcap_binding');
const session = new binding.PcapSession();
// ... session.open_live(...) ...
const packetBuf = Buffer.alloc(65535);
const headerBuf = Buffer.alloc(4);       // < 16 bytes
session.dispatch(packetBuf, headerBuf);  // PacketReady writes 16 bytes into a 4-byte buffer

Suggested fix: in Dispatch, capture header_length = node::Buffer::Length(header_obj) and
require it to be at least 16 (throw otherwise), or have PacketReady bound its header writes to
the stored header length before each memcpy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions