Linux Namespaces

November 23rd, 2014

Starting from kernel 2.6.24, there are 6 different types of Linux namespaces. Namespaces are useful in isolating processes from the rest of the system, without needing to use full low level virtualization technology.

  • CLONE_NEWIPC: IPC Namespaces: SystemV IPC and POSIX Message Queues can be isolated.
  • CLONE_NEWPID: PID Namespaces: PIDs are isolated, meaning that a PID inside of the namespace can conflict with a PID outside of the namespace. PIDs inside the namespace will be mapped to other PIDs outside of the namespace. The first PID inside the namespace will be ‘1’ which outside of the namespace is assigned to init
  • CLONE_NEWNET: Network Namespaces: Networking (/proc/net, IPs, interfaces and routes) are isolated. Services can be run on the same ports within namespaces, and “duplicate” virtual interfaces can be created.
  • CLONE_NEWNS: Mount Namespaces. We have the ability to isolate mount points as they appear to processes. Using mount namespaces, we can achieve similar functionality to chroot() however with improved security.
  • CLONE_NEWUTS: UTS Namespaces. This namespaces primary purpose is to isolate the hostname and NIS name.
  • CLONE_NEWUSER: User Namespaces. Here, user and group IDs are different inside and outside of namespaces and can be duplicated.

Let’s look first at the structure of a C program, required to demonstrate process namespaces. The following has been tested on Debian 6 and 7.

First, we need to allocate a page of memory on the stack, and set a pointer to the end of that memory page. We use alloca to allocate stack memory rather than malloc which would allocate memory on the heap.

void *mem = alloca(sysconf(_SC_PAGESIZE)) + sysconf(_SC_PAGESIZE);

Next, we use clone to create a child process, passing the location of our child stack ‘mem’, as well as the required flags to specify a new namespace. We specify ‘callee’ as the function to execute within the child space:

mypid = clone(callee, mem, SIGCHLD | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | CLONE_FILES, NULL);

After calling clone we then wait for the child process to finish, before terminating the parent. If not, the parent execution flow will continue and terminate immediately after, clearing up the child with it:

while (waitpid(mypid, &r, 0) < 0 && errno == EINTR)
{
	continue;
}

Lastly, we’ll return to the shell with the exit code of the child:

if (WIFEXITED(r))
{
	return WEXITSTATUS(r);
}
return EXIT_FAILURE;

Now, let’s look at the callee function:

static int callee()
{
	int ret;
	mount("proc", "/proc", "proc", 0, "");
	setgid(u);
	setgroups(0, NULL);
	setuid(u);
	ret = execl("/bin/bash", "/bin/bash", NULL);
	return ret;
}

Here, we mount a /proc filesystem, and then set the uid (User ID) and gid (Group ID) to the value of ‘u’ before spawning the /bin/bash shell.
Read the rest of this entry »

Linux iproute2 multiple default gateways

October 5th, 2014

This article describes a Linux server set up with 2 interfaces (eth0) and (eth1). Each interface has a separate ISP, network details and default gateway. eth0 has two sets of network details on the same interface and so a virtual interface (eth0:0) must be created to handle the second IP.

By default, Linux only allows for one default gateway. Let’s see what happens if we try to use multiple uplinks with 1 default gateway. Assume eth0 is assigned 192.168.1.2/24 and eth1 is assigned 172.16.1.5/16. Let’s say our default gateway is 192.168.1.1 (which of course is found through eth0) but there’s also a 172.16.0.1 gateway on eth1 which we can’t enter as Linux only allows for the one.

Our routing table now looks like this:

root@www1:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
172.16.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth1

If a packet comes in to us, routed through the 172.16.0.1 gateway from say 8.8.8.8, our machine will receive it. When it tries to reply to 8.8.8.8 however, it runs down the routing table and sees that it’s not local to eth0 or eth1 and therefore will get routed out through the default gateway (192.168.1.1) – the problem is, this is the wrong gateway and so the target machine will ignore our response due to it being out of sequence and from the wrong IP.

Using iproute2, Linux can track multiple routing tables and therefore multiple default gateways. If the packet comes in through one interface and to one IP, it will go out via a specific default gateway. The script to achieve this is as follows:

Read the rest of this entry »

Simple Ready to Roll Linux Backup Script

September 12th, 2014

I’d built a Linux backup BASH shell script a while ago that I’ve been using, and wanted to share it today. This is a simple and easy to configure script, useful for backing up and scheduling multiple hosts, as well as handling file and MySQL backups, and flexibly allowing multiple days or copies to be retained.

The full source is available here

The global configuration is performed at the top of the script:

#config
MAIN_DIR="/home/sysbackups"
BACKUP_DIR="${MAIN_DIR}/backups"
LOG_DIR="${MAIN_DIR}/logs"

RSYNC="time nice -19 rsync"
SSH=ssh
MYSQLDUMP="time nice -19 mysqldump"
GZIP=gzip
SCP=scp
CAT=cat
RM=rm
CP=cp
RSYNC_ARGS="-arplogu --delete --stats"
TODAY=`date +%Y%m%d`
LOG="${LOG_DIR}/log_error_${TODAY}.log"

The utilities that you see listed are all required to be installed: rsync gzip scp time nice cat mysqldump.

The directory structure for backups is a master directory, which in this case is /home/sysbackups, a directory for the actual backups to be placed, in this case /home/sysbackups/backups and a directory for log files, in this case /home/sysbackups/logs. These directories should exist prior to running the script.

The usage of ‘nice’ is to ensure the backups are as resource friendly as possible, and ‘time’ allows for timing data to be provided within the log files created.

Each backup set is defined lower down in the ‘startEntry’ function. Taking the first as an example:

10 )
 STARTED=1
 START="Local: vm1"
 HOST="192.168.1.50"
 B_RSYNC_USER=root
 B_RSYNC=1
 B_RSYNC_LIMIT=4096
 B_RSYNC_DIR=( "/var/www" "/var/spool/cron" "/etc" "/home" )
 B_MYSQLDUMP=1
 B_MULTIPLEDAYS_DB=3
 B_MYSQLDUMP_USER="root"
 B_MYSQLDUMP_MYSQLUSER="root"
 B_MYSQLDUMP_PASS="password"
 B_MYSQLDUMP_HOST="127.0.0.1"
 B_MYSQLDUMP_TMP="/tmp/mysqldump-backup.sql"
 B_MYSQLDUMP_GZIPAFTER=1
 B_MYSQLDUMP_DATABASES=( "all-databases" )
 ;;

The ‘START’ variable defines the “friendly name” of the machine for log purposes, and the ‘HOST’ variable defines it’s IP or hostname.

Setting ‘B_RSYNC’ to 1 instructs the script to execute the rsync routines for file backup. Setting ‘B_MYSQLDUMP’ to 1 allows us to back up MySQL databases from on the host.

Rsync options

B_RSYNC_USER defines the SSH user to connect to the host as
B_RSYNC_LIMIT defines the limit in kbps for the transferB_RSYNC_DIR is an array of directories to back up

Mysqldump options

B_MYSQLDUMP_USER defines the SSH user to connect to the host as
B_MYSQLDUMP_MYSQLUSER and B_MYSQLDUMP_PASS define the MySQL username and password to connect with
B_MYSQLDUMP_HOST defines the MySQL host to connect to, relative to the HOST variable.
B_MYSQLDUMP_TMP defines a temporary location for the mysql backup on the host
B_MYSQLDUMP_GZIPAFTER defines whether the MySQL backups should be GZipped before being transferred
B_MYSQLDUMP_DATABASES is an array of database names to be backed up, with “all-databases” being hopefully self explanatory

B_MULTIPLEDAYS_DB defines the number of database copies to keep and B_MULTIPLEDAYS defines the number of file sets to keep.

As we have defined this backup set as case ’10’ in the script, to execute it, we simply run: /path/to/backup.script.sh 10

This can be cronned to run on a daily basis.

Lastly, as connections to hosts are made via SSH, either a password will need to be entered on each run manually, or SSH keys can be set up.

Feel free to reply with changes or comments.

Exim, DKIM and Debian Configuration

July 11th, 2014

DKIM is a system for cryptographically signing messages and confirming they were sent from a sending server authorized at domain level. A private and public key pair is generated. The private key is used to sign the messages, and the public key is published as a DNS TXT record for the domain name. This allows recipients to electronically verify that mail claiming to be from domain was actually sent by a server authorized to send mail on behalf of that domain. Implementing DKIM into a mail system increases trust and deliverability.

Setting up Exim to sign outgoing mail under DKIM (Domain Keys Identified Mail) is a reasonably quick and simple task. Assuming you’re using an up to date version of Debian with Exim4, the process is even easier.
Read the rest of this entry »

BASH One liner – Disassemble shellcode

April 30th, 2013

Here’s a BASH one liner that I just discovered that will allow you to disassemble shellcode on the command line:

echo -n $'\x41\x41\x41\x41' | ndisasm -u -

00000000  41                inc ecx
00000001  41                inc ecx
00000002  41                inc ecx
00000003  41                inc ecx

Enjoy!

Converting binary to shellcode

April 8th, 2013

Here is my ‘bin2sc.sh’. This is a short bash script that will convert binary to shellcode on the Linux console using objdump:

#!/bin/bash
code=$(objdump -d $1|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|tr -s ' '|tr '\t' '!'|cut -d \! -f 2|sed s/^/\ /g|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g')
len=$(echo $code|grep -o \\\\|wc -l)
echo $code
echo "len: " $len

This was originally taken from the SecurityTube SLAE video series however it was improved to face a shortcoming where it didn’t work in all cases if a certain set of instructions was too long. This new version should work in all cases

EDIT
Here’s a far better version from commandlinefu:

for i in $(objdump -d binary -M intel |grep "^ " |cut -f2); do echo -n '\x'$i; done;echo