12

I'm wondering if there is any possibility to run Scapy's 'sniff(...)' without root priveleges.

It is used in an application, where certain packages are captured. But I don't want to run the whole application with root permissions or change anything on scapy itselfe.

Thanks in advance!

EDIT:

For testing I use following code:

from scapy.all import *

def arp_monitor_callback(pkt):
    if ARP in pkt and pkt[ARP].op in (1,2): #who-has or is-at
        return pkt.sprintf("%ARP.hwsrc% %ARP.psrc%")

sniff(prn=arp_monitor_callback, filter="arp", store=0)

I'm only able to run it using sudo.

I tried to set capabilities with sudo setcap 'cap_net_admin=+eip' test.py. But it doesn't show any effects. Even the all capablity doesn't help.

4
  • sniff() needs to set promiscuous mode so capability CAP_NET_ADMIN should be enough for your program to run (see man capabilities(7)) Commented Mar 25, 2016 at 7:54
  • sorry, but I'm not very familiar with capabilities: do I have to set these on to my script, to the scapy lib or even somewhere else? Commented Mar 28, 2016 at 11:23
  • You can set the script capabilities with setcap(8) as root if you want regular users to use the program without privilege elevation (example here). Commented Mar 29, 2016 at 14:18
  • Thanks for the guide, but it doesn't poses any reactions. I added some more information and the test I ran. Commented Apr 1, 2016 at 10:06

2 Answers 2

18

You need to set capabilities for binaries running your script i-e: python and tcpdump if you want to be able to just execute your script as ./test.py :

setcap cap_net_raw=eip /usr/bin/pythonX.X
setcap cap_net_raw=eip /usr/bin/tcpdump

Where X.X is the python version you use to run the script.

(note that path could be different on your system)

Please note that this allow anyone to open raw sockets on your system.

Sign up to request clarification or add additional context in comments.

1 Comment

I just tried it on a virtualenv python and it works as well. This somehow feels better to me than doing it for the global python command.
12

Although solution provided by @Jeff is technically correct, because of setting the file capabilities directly on binaries in /usr/bin, it has a drawback of allowing anyone in the system to open raw sockets.

Another way of achieving the desired outcome - script running with just the CAP_NET_RAW - is to use ambient capabilities. This can be done by leveraging a small helper binary that sets up ambient capabilities and exec()'s into python interpreter. For a reference please see this gist.

Using the reference implementation, assuming that that proper file capabilities are assigned to ./ambient:

$ sudo setcap 'cap_net_raw=p' ambient

your script would be launched as:

$ ./ambient -c '13' /usr/bin/python ./test.py

Please note that:

  • 13 is the integer value of CAP_NET_RAW as per capability.h
  • ambient capabilities are available since kernel 4.3
  • you can use pscap to verify if the process was launched with desired capabilities in its effective set

Why does this method work?

Ambient capabilities are preserved across exec() calls (hence passed to all subsequently created subprocesses) and raised in their effective set, e.g. a python interpreter invoked by the binary or tcpdump invoked by python script. This is of course a simplification, for a full description of transitions between capability sets see capabilities(7)

2 Comments

This works great for my jupyter notebook setup (py 3.6.5, scapy 2.4.3, jupyter core 4.5.0, jupyter-notebook : 6.0.1)
It didn't work for me $ uname -r 4.4.224-1.el7.elrepo.x86_64 maybe it needs so other specific versions of packages?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.