Linux Raw Socket Permissions Issue - c

I'm creating a raw ethernet socket in a C application, e.g.
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
and its returning -1 indicating an error
I'm pretty sure its a permissions issue - You can only open a raw socket if you have a UID of 0 (root) or have the CAP_NET_RAW capability
I don't think running the application as root is reasonable, therefore my question is how can I 'add' the CAP_NET_RAW capability permission to my user account?
From http://manpages.ubuntu.com/manpages/zesty/en/man7/packet.7.html
In order to create a packet socket, a process must have the CAP_NET_RAW
capability in the user namespace that governs its network namespace.
But how does one achieve that end?

You set the capabilities on the executable that needs that capability, not a user account. The syntax is
setcap cap_net_raw,cap_net_admin=eip ./your_exeutable
(Note, you need to run setcap as root, so use e.g. sudo setcap ... Also make sure there are no space characters in cap_net_raw,cap_net_admin=eip

Being able to read all network packets is considered a severe security risk, that is why this needs a privileged account.
You can make the application "suid root" to elevate your own rights when starting this application as a "normal" user. But that is a security risk as well and needs a bit of thorough thinking when designing the application (it should at least give up the higher privilege as soon as it doesn't need it any more - i.e. after having opened the raw socket).

You cannot add the CAP_NET_RAW permission to your account, because capabilities on Linux do not follow users. They follow executables.
To make this work, you need to add the CAP_NET_RAW capability to your compiled executable. See the setcap command in order to see how to do that.

Related

Request Linux Capabilities During Runtime

I am developing a program in C that requires temporary use of some capabilities that require elevation to acquire and would rather not just have users issue sudo because it will be one time setup.
How would I go about granting capabilities such as CAP_CHOWN to enable changing file ownership or similar actions guarded by a capability?
A note on possible duplicates
When I asked this before it got closed as a duplicate. The question that was cited as the original question isn't the same question I had posted. I want a very specific set of capabilities, not root access.
The most common method to do provide extra capabilities to a process is to assign filesystem capabilities to its binary.
For example, if you want the processes executing /sbin/yourprog to have the CAP_CHOWN capability, add that capability to the permitted and effective sets of that file: sudo setcap cap_chown=ep /sbin/yourprog.
The setcap utility is provided by the libcap2-bin package, and is installed by default on most Linux distributions.
It is also possible to provide the capabilities to the original process, and have that process manipulate its effective capability set as needed. For example, Wireshark's dumpcap is typically installed with CAP_NET_ADMIN and CAP_NET_RAW filesystem capabilities in the effective, permitted, and inheritable sets.
I dislike the idea of adding any filesystem capabilities to the inheritable set. When the capabilities are not in the inheritable set, executing another binary causes the kernel to drop those capabilities (assuming KEEPCAPS is zero; see prctl(PR_SET_KEEPCAPS) and man 7 capabilities for details).
As an example, if you granted /sbin/yourprog only the CAP_CHOWN capability and only in the permitted set (sudo setcap cap_chown=p /sbin/yourprog), then the CAP_CHOWN capability will not be automatically effective, and it will be dropped if the process executes some other binary. To use the CAP_CHOWN capability, a thread can add the capability to its effective set for the duration of the operations needed, then remove it from the effective set (but keep it in the permitted set), via prctl() calls. Note that the libcap cap_get_proc()/cap_set_proc() interface applies the changes to all threads in the process, which may not be what you want.
For temporarily granting a capability, a worker sub-process can be used. This makes sense for a complex process, as it allows delegating/separating the privileged operations to a separate binary. A child process is forked, connected to the parent via an Unix domain stream or datagram socket created via socketpair(), and executes the helper binary that grants it the necessary capabilities. It then uses the Unix domain stream socket to verify the identity (process ID, user ID, group ID, and via the process ID, the executable the other end of the socket is executing). The reason a pipe is not used, is that an Unix domain stream socket or datagram socketpair socket is needed to use the SO_PEERCRED socket option to query the kernel the identity of the other end of the socket.
There are known attack patterns that need to be anticipated and thwarted. The most common attack pattern is causing the parent process to immediately execute a compromised binary after forking and executing the privileged child process, timed just right so the capabled child process trusts the other end is its proper parent executing the proper binary, but in fact control has been transferred to a completely different, compromised or untrustworthy binary.
The details on exactly how to do this securely are a software engineering question much more than a programming question, but using socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fdpair) and verifying the socket peer is the parent process still executing the expected binary more than just once at the beginning, are the key steps needed.
The simplest example I can think of is using prctl() and CAP_NET_BIND_SERVICE filesystem capability only in the permitted set, so that an otherwise unprivileged process can use a privileged port (1-1024, preferably a system-wide subset defined/listed in a root or admin-owned configuration file somewhere under /etc) to provide a network service. If the service will close and reopen its listening socket when told to do so (perhaps via SIGUSR1 signal), the listening socket cannot simply be created once at the beginning then dropped. It is a pretty good match for the "keep in permitted set, but only add to effective set of the thread that actually needs it, then drop it immediately afterwards" pattern.
For CAP_CHOWN, an example program might acquire it into its effective and permitted sets via the filesystem capability, but use a trusted configuration file (root/admin modifiable only) to list the ownership changes it is allowed to do based on the real user and group identity running the process. Consider a dedicated "sudo"-style "chown" utility, intended for say organizations to allow team leads to shift file ownership between their team members, but one that does not use sudo.)
It is not realistically possible to gain capabilities during runtime. The capabilities need to be already set before your software is started.
Some API functions like capset and cap_set_proc exist, but don't expect magic because the situation in which you could gain more capabilities will be both rare and a security oversight.
There are a few general ways of giving your software the required capabilities.
Set a specific capability on your binary with the setcap tool.
Use sudo to call your program. You already mentioned this yourself.
Set the setuid bit on your binary and set ownership to root. In this particular case that will be largely equivalent to calling your program with sudo.
Create a utility program that you apply one of the other methods on. Typically you would find such utility in a place like /usr/libexec. You then call the utility as a subprocess. I would consider this unnecessarily complex for simple situations. However, depending on the situations, this may be preferred over having a potential security risk of your software constantly running with too many privileges.
The first method should be considered the desired way. Your software should drop the capability as soon as it no longer requires it.
The CAP_CHOWN could be used for example to change ownership of /etc/shadow. The new owner could then change password for other users such as root, so effectively it could be equivalent to granting all capabilities. Hence, this capability is -like many others- potentially dangerous.

Control GPIO through sysfs, mmap, or device driver on program run as non-root user?

I am trying to make a c program to access GPIOs on an embedded linux system which will be run by a non root user. I can already access the GPIOs through sysfs (/sys/class/gpio) and have made a simple program that used mmap (through /dev/mem/) to control the GPIOs. However to write to /sys/class/gpio/ and /dev/mem/ you must have root privileges. What would be the most "correct" or standard way to access the GPIO in a program run as a non-root user?Writing a device driver?
Giving the user read/write access to /sys/class/gpio/ so the program can use sysfs?
Or Giving the user read/write access to /dev/mem/ so the program can use mmap()?
Thanks
One potential option is to make a process setuid by setting the s bit.
e.g.
chmod +s myExectuable
However, this has terrible security implications as the process then runs as root - with all the hazards that entails. Only an option if you really trust the user-space app, and even then, risky.
I don't think changing the default ownership and permissions of sysfs is possible without hacking up your kernel, and even then it would be tricky: sysfs is intricately connected with object model of the the Linux Driver model.
You may have more luck with the permissions on /dev/.
Ultimately, the correct way of solving this problem is a kernel-mode driver - in which you can implement whatever finely grained security (or lack thereof) you wish. Furthermore, you can implement mitigation against any potential ill-effects of allowing a user-mode application to control hardware.
Granting a custom user group access to specifically needed nodes under /sys/class/gpio is a fairly solid solution where applicable - it can be done entirely from boot scripts, needing no kernel-level programming.

Bind a web server to port 80 without being root

I've written my own web server in C. How can I bind it to port 80 without being root so that the security is not being compromised (buffer overflows etc.)?
Should I simply forward any traffic from another "stable" server that runs on port 80?
Using a forward proxy is indeed the easiest and most recommended solution. It also has the advantage of filtering horribly invalid requests before they even reach your self-written server.
In case your application uses the user's ip address for something remember to retrieve it from whatever header your webserver uses (X-Client-IP etc.). However, only do so for requests that really come from your webserver, otherwise users can spoof their IP. You can do so by checking if the request came from your IP and only check the header in this case or simply make your application bind to localhost.
Another solution would be granting the program the CAP_NET_BIND_SERVICE capability. This requires root to use setcap cap_net_bind_service=ep /path/to/the/executable - since the flag is stored in a filesystem attribute, it will be lost when copying the file to another system or recompiling the application.
Of course you could also make your program setuid root and then switch to an unprivileged user right after calling bind(). However, depending on how your program works and what it does this might not be a good idea - for example, if it needs to close and reopen the listening socket for some reason it would require a full restart of the process.
An alternative to calling bind() as root, then dropping privileges, is to have a root process that creates the socket and binds it, and then passes the listening socket to the unprivileged process over a UNIX-domain socket connection using a SCM_RIGHTS message.
if you want to bind your server to port 80 you must do that as root and afterwards drop the privileges.
bind(sockfd, addr, addrlen);
/* process is running as root, drop privileges after bind*/
if (setgid(groupid) != 0)
errx(1, "setgid: Unable to drop group privileges: %s", strerror(errno));
if (setuid(userid) != 0)
errx(1, "setuid: Unable to drop user privileges: %S", strerror(errno));
How can I bind it to port 80 without being root so that the security is not being compromised (buffer overflows etc.)
not running as root does not make your system more secure it just adds another layer to exploit.
So instead of thinking about how not to run as root, please ensure that you do not use any known-insecure functions like strcpy(), sprintf(), etc. but instead use strncpy(), snprintf(), etc.
Well as you know all ports under 1024 in Unix require root privileges to open.
On a Unix system you do not want as few applications as possible running with root privileges.
It is and will always be a big safety risk.
An alternative is to use iptables to redirect the port 80 traffic to a more harmless port like 8080. Here is a description on how to set it up.
Iptables is not the easiest tool to setup, but once you have mastered it, it is very useful and powerful (and secure).
I worked on this problem for quite some time and came to the conclusion that systemd + iptables is the solution, and not Capabilities, as elaborated in great detail here.

how can I change the permissions of a linux socket file?

I have a program which creates a socket, and then I want to change the permissions of the socket file:
ret_val = chmod(filename, 0777);
, but it doesn't change, even though ret_val will be 0. If I try the same thing on a regular file, it works.
Any ideas?
P.S: I am running the program as root, so it has all the authority needed.
From man 7 unix:
In the Linux implementation, sockets which are visible in the file system
honor the permissions of the directory they are in. Their owner,
group and their permissions can be changed. Creation of a new socket
will fail if the process does not have write and search (execute) permission on the directory the socket is created in. Connecting to the
socket object requires read/write permission. This behavior differs
from many BSD-derived systems which ignore permissions for UNIX domain
sockets. Portable programs should not rely on this feature for security.
So if you want to control permissions on a socket, in order to be portable, you should instead control the permissions of the directory containing the socket.
https://stackoverflow.com/a/42955529/1425297
"If you want your socket world-writeable, the easiest way would be for you app to call this before your socket is created and bound: umask(0);"

requirement of root privileges for libpcap functions

The pcap_lookupdev() fills in the errbuf variable when run as non-root user, while the same functions returns the value of the first available network interface when run as root.
Is this access disabled by the OS or the library. I think it is the OS. What is the right answer?
This is not a homework question
In general, when it comes to accessing files, devices and other services provided by the OS, access models in Unix (and, thus, Linux) are implemented in the OS.
Userspace programs are expected to just try whatever they want to do and gracefully handle any error condition by e.g. informing the user with a message.
This has several advantages:
Maintainability: Access policy enforcement remains with the OS and can be configured uniformly. The administrator that wants to restrict access to a resource does so once, rather than having to configure this library here, than that library there, then...
Configurability: The administrator can configure as simple or complex an access policy they need without being limited by each userspace implementation.
Security: Userspace programs should not in general be trusted with enforcing access policy. It would be like having a wolf guard the sheep.
EDIT:
In your case, pcap needs low-level access to the network interface. Due to the security implications (capturing network traffic, generating arbitrary network packets etc), such access is limited to privileged users only. On Linux, for example, pcap needs the CAP_NET_RAW capability to be available to the user.
Many of the pcap functions require root privileges in order to work correctly. Might this be the problem?
It mostly depends on OS. Not all pcap functions require root privilege on all OS.
Ref to Reference Manual Pages, all special privilege requirements are listed respectively.

Resources