Skip to content
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

sniff() with an offline pcap file and BPF filter can fail validation and raise an exception #3093

Closed
ctenglish opened this issue Feb 9, 2021 · 2 comments · Fixed by #3109
Labels

Comments

@ctenglish
Copy link

ctenglish commented Feb 9, 2021

Brief description

Calling sniff() using an offline pcap file and also specifying a BPF filter can lead to an exception during validation of the filter as it appears the associated linktype may be guessed incorrectly under some conditions.

For example, providing a pcap with raw WiFi packets and using a filter of "subtype probe-req" to select only probe request frames should work, but the additional validation performed in compile_filter() before calling tcpdump with the filter raises an exception.

Environment

  • Scapy version: 2.4.4
  • Python version: 3.8.5
  • Operating System: Ubuntu 20.04

How to reproduce

  1. capture a WiFi pcap using (for example) tshark, eg tshark -i wlan0 -w capture.pcap
  2. using offline mode with a filter, scapy.sniff(offline="path/to/capture.pcap", filter="subtype probe-req", ...)

Actual result

  File "<snip>/lib/python3.8/site-packages/scapy/sendrecv.py", line 1195, in sniff
    sniffer._run(*args, **kwargs)
  File "<snip>/lib/python3.8/site-packages/scapy/sendrecv.py", line 987, in _run
    sniff_sockets.update(
  File "<snip>/lib/python3.8/site-packages/scapy/sendrecv.py", line 992, in <genexpr>
    else tcpdump(
  File "<snip>/lib/python3.8/site-packages/scapy/utils.py", line 1867, in tcpdump
    compile_filter(flt)
  File "<snip>/lib/python3.8/site-packages/scapy/arch/common.py", line 123, in compile_filter
    raise Scapy_Exception(
scapy.error.Scapy_Exception: Failed to compile filter expression subtype probe-req (-1)

Expected result

no exception

note: This exception isn't always raised, under some conditions it works, possibly the linktype is guessed correctly under some code paths.

Related resources

The tcpdump implementation in scapy/utils.py tries to validate the BPF filter before executing tcpdump by calling compile_filter() (see https://github.com/secdev/scapy/blob/master/scapy/utils.py#L2079)

Internally it looks like compile_filter() makes some educated guesses about the linktype for the filter but if it gets the linktype wrong then the exception is raised. If sniff() is modified take a linktype that is then passed to tcpdump() that is then passed to compile_filter this exception could be avoided.

For example in sendrecv.py (AsyncSniff._run()):

857d856
<             linktype = karg.get("linktype")
863c862
<                     tcpdump(fname, args=["-w", "-"], flt=flt, linktype=linktype, getfd=True)
---
>                     tcpdump(fname, args=["-w", "-"], flt=flt, getfd=True)
868c867
<                     tcpdump(fname, args=["-w", "-"], flt=flt, linktype=linktype, getfd=True)
---
>                     tcpdump(fname, args=["-w", "-"], flt=flt, getfd=True)
888d886
<                             linktype=linktype,

and in utils.py (tcpdump):

1781c1781
<         compile_filter(flt, linktype=linktype)
---
>         compile_filter(flt)

sniff could be invoked with a known linktype, DLT_IEEE802_11 in this case:

scapy.sniff(offline="path/to/capture.pcap", filter="subtype probe-req", linktype=DLT_IEEE802_11, ...)
@guedou
Copy link
Member

guedou commented Feb 20, 2021

Thanks for your report. Do you want to provide a PR with your changes?

@ctenglish
Copy link
Author

Thanks for the response! That PR to magically figure out the linktype from the pcap file looks much better than my suggestion which needs the user to supply the linktype.

Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants