How to disable socket creation for a Linux process, for sandboxing?

Asked
Active3 hr before
Viewed126 times

7 Answers

creationsocketdisable
90%

2 Similar Qs on sandboxing/jailing processes in Linux or Unix: * unix.stackexchange.com/q/6433/4319 * stackoverflow.com/q/3859710/94687 * stackoverflow.com/q/4249063/94687 * stackoverflow.com/q/1019707/94687 – imz -- Ivan Zakharyaschev Mar 13 '11 at 13:37 , 2 In my workload (running g++), sydbox was 50% slower than User-mode Linux, so I'm sticking to User-mode Linux now, because that gives me not only sandboxing, but limiting gross memory use. – pts Jan 6 '11 at 13:48 ,However, if P is assumed be to malicious rather than benign or if you're looking for strong assurance about how P will behave in the face of potentially malicious inputs, then you're probably out of luck: i.e., at best, with the tools available today, you can create an obstacle course for attackers. , By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

ptrace seems to be the most obvious tool but aside from that…

ptrace
load more v
88%

Try seccomp (see the prctl man page), it can confine your process to only accessing the sockets that were left open at the time the prctl call was made.,If you find copyright violations, you can contact us at info-generacodice.com to request the removal of the content.,   sockets  -  linux  -  sandbox ,(That being said, if an obstacle course works for you, then you might get some more good ideas by poking around over here at sandboxing.org or by sending your questions to the friendly folks on sandboxing-talk@lists.sandboxing.org.)

I'm considering several options for sandboxing a Linux process. Using clone() with CLONE_NEWNET (etc.) is one of the options. CLONE_NEWNET ensures that the the sandboxed process cannot make or accept real network connections. But I'd like to disable sockets entirely for that process, even bind()ing to any port on 0.0.0.0, and binding to a Unix doman socket (even anonymous). I'd like to do this to prevent the process from using too much kernel resources by binding to thousands of ports. How do I do that?

clone()

I'm considering several options for sandboxing a Linux process. Using clone() with CLONE_NEWNET (etc.) is one of the options. CLONE_NEWNET ensures that the the sandboxed process cannot make or accept real network connections. But I'd like to disable sockets entirely for that process, even bind()ing to any port on 0.0.0.0, and binding to a Unix doman socket (even anonymous). I'd like to do this to prevent the process from using too much kernel resources by binding to thousands of ports. How do I do that?

CLONE_NEWNET

I'm considering several options for sandboxing a Linux process. Using clone() with CLONE_NEWNET (etc.) is one of the options. CLONE_NEWNET ensures that the the sandboxed process cannot make or accept real network connections. But I'd like to disable sockets entirely for that process, even bind()ing to any port on 0.0.0.0, and binding to a Unix doman socket (even anonymous). I'd like to do this to prevent the process from using too much kernel resources by binding to thousands of ports. How do I do that?

CLONE_NEWNET

I'm considering several options for sandboxing a Linux process. Using clone() with CLONE_NEWNET (etc.) is one of the options. CLONE_NEWNET ensures that the the sandboxed process cannot make or accept real network connections. But I'd like to disable sockets entirely for that process, even bind()ing to any port on 0.0.0.0, and binding to a Unix doman socket (even anonymous). I'd like to do this to prevent the process from using too much kernel resources by binding to thousands of ports. How do I do that?

bind()

I'm considering several options for sandboxing a Linux process. Using clone() with CLONE_NEWNET (etc.) is one of the options. CLONE_NEWNET ensures that the the sandboxed process cannot make or accept real network connections. But I'd like to disable sockets entirely for that process, even bind()ing to any port on 0.0.0.0, and binding to a Unix doman socket (even anonymous). I'd like to do this to prevent the process from using too much kernel resources by binding to thousands of ports. How do I do that?

0.0 .0 .0
load more v
72%

Along with the other sugestions you might find this useful.,Note that the data is passed by writing out files and that can be slow if a lot is going on.,The Linux kernel also supports seccomp, a mode entered with prctl(PR_SET_SECCOMP, 1) which prevents the process (well, thread, really) from calling any syscalls other than read, write, exit, and sigreturn. It's a pretty effective sandbox but difficult to use with unmodified code.,I'm considering several options for sandboxing a Linux process. Using clone() with CLONE_NEWNET (etc.) is one of the options. CLONE_NEWNET ensures that the sandboxed process cannot make or accept real network connections. But I'd like to disable sockets entirely for that process, even bind()ing to any port on 0.0.0.0, and binding to a Unix doman socket (even anonymous). I'd like to do this to prevent the process from using too much kernel resources by binding to thousands of ports. How do I do that?

You first need to supply to finish a reference to the data structure that the child wants to return. In your case, you want to return a scalar $commandoutput[0] so do

$fork - > finish(0, $commandoutput[0]);

This reference is then found in the callback as the last, sixth, parameter. The one your code left out. So in the callback you need

my % ret_data;
# to store data from different child processes

$pm - > run_on_finish(
   sub {
      my($pid, $exit, $ident, $signal, $core, $dataref) = @_;
      $ret_data {
         $pid
      } = $dataref;
   }
);

Here $dataref is $commandoutput[0], which is stored in %ret_data as the value for the key which is the process id. So after the foreach completes you can find all data in %ret_data

foreach my $pid(keys % ret_data) {
   say "Data from $pid => ${$ret_data{$pid}}";
}

Here is a full example, where each child returns an array reference, by passing it tofinish, which is then retrieved in the callback. For a different example see this post.

use warnings;
use strict;
use feature 'say';

use Parallel::ForkManager;
my $pm = Parallel::ForkManager - > new(4);

my % ret_data;

$pm - > run_on_finish(sub {
   my($pid, $exit, $ident, $signal, $core, $dataref) = @_;
   $ret_data {
      $pid
   } = $dataref;
});

foreach my $i(1. .8) {
   $pm - > start and next;
   my $ref = run_job($i);
   $pm - > finish(0, $ref);
}
$pm - > wait_all_children;

foreach my $pid(keys % ret_data) {
   say "$pid returned: @{$ret_data{$pid}}";
}

sub run_job {
   my($i) = @_;
   return [1..$i];
   # make up
   return data: arrayref with list 1..$i
}

Prints

15037 returned: 1 2 3 4 5 6 7
15031 returned: 1 2
15033 returned: 1 2 3 4
15036 returned: 1 2 3 4 5 6
15035 returned: 1 2 3 4 5
15038 returned: 1 2 3 4 5 6 7 8
15032 returned: 1 2 3
15030 returned: 1
load more v
65%

Sandboxing tools available in Linux use this namespaces feature to isolate a process or create a new virtual environment. A much more secure tool will be that which uses maximum namespaces for isolation. Now, let’s talk about different methods of sandboxing, from soft to hard isolation.,This will create an isolated environment using the PID and user namespaces.,The unshare utility is used to create any namespace isolated environment and run a program or shell inside it.,Namespaces are features available in Linux to isolate processes in different system resource aspects. There are six types of namespaces available up to kernel 4.0. And more will be added in the future. These are:

Creation of new namespaces is done by the clone() system call, which is also used to start a process. The setns() system call adds a running process to the existing namespace. The unshare() call works on a process inside the namespace, and makes the caller a member of the namespace. Its main purpose is to isolate the namespace without having to create a new process or thread (as is done by clone()).You can directly use some services to get the features of these namespaces. CLONE_NEW* identifiers are used with these system calls to identify the type of namespace. These three system calls make use of the CLONE_NEW* as CLONE_NEWIPC, CLONE_NEWNS, CLONE_NEWNET, CLONE_NEWPID, CLONE_NEWUSER, and CLONE_NEWUTS. A process in a namespace can be different because of its unique inode number when it is created.

#ls -al /proc/<pid>/ns
   lrwxrwxrwx 1 root root 0 Feb 7 13:52 ipc -> ipc:[4026532253]
   lrwxrwxrwx 1 root root 0 Feb 7 15:39 mnt -> mnt:[4026532251]
   lrwxrwxrwx 1 root root 0 Feb 7 13:52 net -> net:[4026531957]
   lrwxrwxrwx 1 root root 0 Feb 7 13:52 pid -> pid:[4026532254]
   lrwxrwxrwx 1 root root 0 Feb 7 13:52 user -> user:[4026531837]
   lrwxrwxrwx 1 root root 0 Feb 7 15:39 uts -> uts:[4026532252]
load more v
75%

Then, starting a process without network access is as simple as:,You can use seccomp-bpf to block some system calls. For example might want to block the socket system call in order to prevent the process from creating sockets FD.,Is it possible to block the (outgoing) network access of a single process?,I wrote an example of this approcah which prevents the socket system call for working using libseccomp. The summary is (without error checking):

Then, starting a process without network access is as simple as:

unshare - n program...

This creates an empty network namespace for the process. That is, it is run with no network interfaces, including no loopback. In below example we add -r to run the program only after the current effective user and group IDs have been mapped to the superuser ones (avoid sudo):

$ unshare - r - n ping 127.0 .0 .1
connect: Network is unreachable

If your app needs a network interface you can set a new one up:

$ unshare - n--sh - c 'ip link set dev lo up; ping 127.0.0.1'
PING 127.0 .0 .1(127.0 .0 .1) 56(84) bytes of data.
64 bytes from 127.0 .0 .1: icmp_seq = 1 ttl = 32 time = 0.066 ms

The following example runs ping with network namespace that is used by PID 1 (it is specified through -t 1):

$ nsenter - n - t 1--ping - c4 example.com
PING example.com(93.184 .216 .119) 56(84) bytes of data.
64 bytes from 93.184 .216 .119: icmp_seq = 1 ttl = 50 time = 134 ms
64 bytes from 93.184 .216 .119: icmp_seq = 2 ttl = 50 time = 134 ms
64 bytes from 93.184 .216 .119: icmp_seq = 3 ttl = 50 time = 134 ms
64 bytes from 93.184 .216 .119: icmp_seq = 4 ttl = 50 time = 139 ms

   -- - example.com ping statistics-- -
   4 packets transmitted, 4 received, 0 % packet loss, time 3004 ms
rtt min / avg / max / mdev = 134.621 / 136.028 / 139.848 / 2.252 ms
load more v
40%

As root, enter the following command to create a new Linux user named newuser: ~]# useradd newuser, Make sure SELinux is running in permissive mode: ~]# setenforce 0~]$ getenforce Permissive , Enter the following command to view the file1 file created in step 3: ~]$ ls /test/ file1 , Enter the following command as root to create a group named CVS: [cvs-srv]# groupadd CVS This can by also done by using the system-config-users utility.

~] # getenforce
Enforcing
~] # setenforce 0
   ~] # getenforce
Permissive
~] # setenforce 1
   ~] # getenforce
Enforcing
~] # semanage permissive - a httpd_t
load more v
22%

Firejail is an easy to use SUID sandbox program that reduces the risk of security breaches by restricting the running environment of untrusted applications using Linux namespaces, seccomp-bpf and Linux capabilities. ,firejail --debug $Program > $PathToOutputFile Gives a detailed breakdown of the sandbox,firejail-handler-extra, like above but handles other protocols.,To manually map individual applications execute:

/etc/pacman.d / hooks / firejail.hook
load more v

Other "creation-socket" queries related to "How to disable socket creation for a Linux process, for sandboxing?"