Skip to content

Check added to PcapNg processing #4373

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 37 additions & 11 deletions scapy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1603,9 +1603,14 @@ def _read_block(self, size=MTU):
warning("PcapNg: Error reading blocklen before block body")
raise EOFError
if blocklen < 12:
warning("Invalid block length !")
warning("PcapNg: Invalid block length !")
raise EOFError
block = self.f.read(blocklen - 12)

_block_body_length = blocklen - 12
block = self.f.read(_block_body_length)
if len(block) != _block_body_length:
raise Scapy_Exception("PcapNg: Invalid Block body length "
"(too short)")
self._read_block_tail(blocklen)
if blocktype in self.blocktypes:
return self.blocktypes[blocktype](block, size)
Expand Down Expand Up @@ -1635,25 +1640,41 @@ def _read_block_shb(self):
elif endian == b"\x4d\x3c\x2b\x1a":
self.endian = "<"
else:
warning("Bad magic in Section Header block (not a pcapng file?)")
warning("PcapNg: Bad magic in Section Header Block"
" (not a pcapng file?)")
raise EOFError

blocklen = struct.unpack(self.endian + "I", _blocklen)[0]
try:
blocklen = struct.unpack(self.endian + "I", _blocklen)[0]
except struct.error:
warning("PcapNg: Could not read blocklen")
raise EOFError
if blocklen < 28:
warning(f"Invalid SHB block length ({blocklen})!")
warning(f"PcapNg: Invalid Section Header Block length ({blocklen})!") # noqa: E501
raise EOFError

# Major version must be 1
_major = self.f.read(2)
major = struct.unpack(self.endian + "H", _major)[0]
try:
major = struct.unpack(self.endian + "H", _major)[0]
except struct.error:
warning("PcapNg: Could not read major value")
raise EOFError
if major != 1:
warning(f"SHB Major version {major} unsupported !")
warning(f"PcapNg: SHB Major version {major} unsupported !")
raise EOFError

# Skip minor version & section length
self.f.read(10)
skipped = self.f.read(10)
if len(skipped) != 10:
warning("PcapNg: Could not read minor value & section length")
raise EOFError

options = self.f.read(blocklen - 28)
_options_len = blocklen - 28
options = self.f.read(_options_len)
if len(options) != _options_len:
raise Scapy_Exception("PcapNg: Invalid Section Header Block "
" options (too short)")
self._read_block_tail(blocklen)
self._read_options(options)

Expand All @@ -1673,7 +1694,12 @@ def _read_options(self, options):
# type: (bytes) -> Dict[int, bytes]
opts = dict()
while len(options) >= 4:
code, length = struct.unpack(self.endian + "HH", options[:4])
try:
code, length = struct.unpack(self.endian + "HH", options[:4])
except struct.error:
warning("PcapNg: options header is too small "
"%d !" % len(options))
raise EOFError
if code != 0 and 4 + length < len(options):
opts[code] = options[4:4 + length]
if code == 0:
Expand Down Expand Up @@ -1910,7 +1936,7 @@ def read_packet(self, size=MTU, **kwargs):
p.comment = comment
p.direction = direction
if ifname is not None:
p.sniffed_on = ifname.decode('utf-8')
p.sniffed_on = ifname.decode('utf-8', 'backslashreplace')
return p

def recv(self, size: int = MTU, **kwargs: Any) -> 'Packet': # type: ignore
Expand Down
13 changes: 13 additions & 0 deletions test/regression.uts
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,19 @@ for i in range(len(plist)):
assert type(plist_check[i]) == type(plist[0])
assert bytes(plist_check[i]) == bytes(plist[i])

= OSS-Fuzz Findings

from io import BytesIO
# Issue 68352
file = BytesIO(b"\n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00\x01\x00\x00\x00\x14\x00\x00\x00\xe4\x00\x00\x00\x00\x00\x04\x00\x14\x00\x00\x00\x01\x00\x00\x00(\x00\x00\x00\xe4\x00\x00\x00\x00\x00\x04\x00\x02\x00\t\x00b'ens16\xb0'\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00\x06\x00\x00\x004\x00\x00\x00\x01\x00\x00\x00}\x17\x06\x00\xb5t\x1d\x85\x14\x00\x00\x00\x14\x00\x00\x00E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x014\x00\x00\x00")
rdpcap(file)
# Issue 68354
file = BytesIO(b'\n\r\r\n\xff\xfe\xfe\xffM<+\x1a')
try:
rdpcap(file)
except Scapy_Exception:
pass

= Read a pcap file with wirelen != captured len
pktpcapwirelen = rdpcap(pcapwirelenfile)

Expand Down