Configuring IP Dynamic Port Ranges

As you are probably aware, IP port numbers are 16 bit unsigned integers in the range 0 to 65535. IANA (Internet Assigned Numbers Authority) manages these port numbers. See the IANA Service Name and Transport Protocol Port Number Registry for more information.

IANA specifies the range 49152 to 65535 be used for dynamic (AKA private) ports. From the above referenced document:

   Port numbers are assigned in various ways, based on three ranges: System
   Ports (0-1023), User Ports (1024-49151), and the Dynamic and/or Private
   Ports (49152-65535); the difference uses of these ranges is described in  
   RFC6335. 

   System Ports are assigned by IETF process for standards-track protocols, 
   as per RFC6335.  User Ports are assigned by IANA using the "IETF Review" 
   process, the "IESG Approval" process, or the "Expert Review" process, as per
   RFC6335.  Dynamic Ports are not assigned.

Contrary to the IANA, Linux kernels typically use the range 32768 to 61000. In 2007, the Linux kernel maintainers decided to use that range following a short discussion on the Linux kernel mailing list (See lkml.org).

Two kernel settings control the IP dynamic port ranges on a system, i.e. ip_local_port_range and ip_local_reserved_ports.

# pwd
/proc/sys/net/ipv4

# ls | grep port
ip_local_port_range
ip_local_reserved_ports

# cat ip_local_port_range 
32768	61000
# cat ip_local_reserved_ports 

#

The range specified in ip_local_port_range determines the port assigned to an application by default when the application itself does not specify a TCP or UDP port to use for an outgoing connection. The upper range value (port number) was reduced to 61000 because ports above that number are used for masquerading ports when masquerading is enabled. The lower range value was selected because it was felt that more ports were needed than suggested by IANA.

From the kernel documentation:

ip_local_port_range - 2 INTEGERS
     Defines the local port range that is used by TCP and UDP to
     choose the local port. The first number is the first, the
     second the last local port number. The default values are
     32768 and 61000 respectively.

The ip_local_port_range enables you to add exceptions to the range of ports listed in ip_local_port_range.

From the kernel documentation:

ip_local_reserved_ports - list of comma separated ranges
     Specify the ports which are reserved for known third-party
     applications. These ports will not be used by automatic port
     assignments (e.g. when calling connect() or bind() with port
     number 0). Explicit port allocation behavior is unchanged.

     The format used for both input and output is a comma separated
     list of ranges (e.g. "1,2-4,10-10" for ports 1, 2, 3, 4 and
     10). Writing to the file will clear all previously reserved
     ports and update the current list with the one given in the
     input.

     Note that ip_local_port_range and ip_local_reserved_ports
     settings are independent and both are considered by the kernel
     when determining which ports are available for automatic port
     assignments.

     You can reserve ports which are not in the current
     ip_local_port_range, e.g.:

         $ cat /proc/sys/net/ipv4/ip_local_port_range
          32000  61000
         $ cat /proc/sys/net/ipv4/ip_local_reserved_ports
          8080,9148
	
      although this is redundant. However such a setting is useful
      if later the port range is changed to a value that will
      include the reserved ports.

      Default: Empty

Access A VMware Virtual Disk from Linux

Recently I needed to recover some data off a VMware Workstation virtual disk using Linux. As you probably know, VMware Workstation (and VMware vSphere) represents a physical disk by a virtual disk whose backing store is one or more VMDK files.

VMDK (Virtual Machine Disk) is a documented file format, which uses the file extension .vmdk. It describes containers for virtual hard disk drives to be used in virtual machines like VMware Workstation or VirtualBox. Initially developed by VMware for its virtual appliance products, nowadays VMDK is an open format.

Fortunately, VMware provides a simple utility, vmware-mount, for mounting a VMware virtual disk on a Linux system. The utility depends on Fuse (File system in USEr Space) which is a loadable kernel module. Fuse allows regular (non-root) users to create and access their own file systems. The file system code runs in user space, while the Fuse module provides a bridge to the actual kernel mount interfaces. Fuse was merged into mainstream Linux in kernel version 2.6.14.

# lsmod | grep fuse
fuse    91371  7 

# modinfo --filename fuse
/lib/modules/3.17.8-300.fc21.x86_64/kernel/fs/fuse/fuse.ko.xz


Note that you may have to create loop devices (/dev/loopX) for Fuse to work correctly. Fedora 20 and 21, for example, do not have loop devices installed by default.

You can mount the VMDK as a loop device:

# ls -l
-rw-r--r--. 1 fpm fpm 7706112 Jan 28 09:14 UEFI-disk1.vmdk

# vmware-mount -p ./UEFI-disk1.vmdk 
Nr      Start       Size Type Id Sytem                   
-- ---------- ---------- ---- -- ------------------------
 1       2048    2095104 BIOS  B Win95 FAT32

# vmware-mount ./UEFI-disk1.vmdk /mnt
# df
Filesystem     1K-blocks      Used Available Use% Mounted on
....
/dev/loop0       1045488     28304   1017184   3% /mnt
# 

# cd /mnt
# ls -l
total 8
drwxr-xr-x. 6 root root 4096 Dec  1 05:04 efi
-rwxr-xr-x. 1 root root   10 Nov 29 19:24 startup.nsh

# find efi/tools
efi/tools
efi/tools/ftp.efi
efi/tools/hostname.efi
efi/tools/hexdump.efi
efi/tools/which.efi
efi/tools/python.efi
# 

# vmware-mount -d /mnt 
#

or you can mount a flat-file representation of the entire virtual disk:

# vmware-mount -f ./UEFI-disk1.vmdk /mnt 

# df
Filesystem     1K-blocks      Used Available Use% Mounted on
/dev/sda4      479468544  17989652 460335532   4% /
devtmpfs         8153896         0   8153896   0% /dev
tmpfs            8164292       260   8164032   1% /dev/shm
tmpfs            8164292      1004   8163288   1% /run
tmpfs            8164292         0   8164292   0% /sys/fs/cgroup
tmpfs            8164292       256   8164036   1% /tmp
/dev/sda4      479468544  17989652 460335532   4% /home
/dev/sdb1      480589524 383220116  72933748  85% /home/fpm
/dev/sda2         487652    131166    326790  29% /boot
/dev/sda1         204580    105944     98636  52% /boot/efi
tmpfs            1632860        20   1632840   1% /run/user/1000
/dev/sdc1         978692     35016    943676   4% /run/media/fpm/CENTON USB

# cd /mnt
# ls -al
total 1048576
-rw-r--r--. 1 fpm fpm 1073741824 Jan 30 21:47 flat

# vmware-mount -L
Disks with mounted partitions:
	/home/fpm/tmp/UEFI-disk1.vmdk	/mnt/flat

# fdisk -lu /mnt/flat

Disk /mnt/flat: 1 GiB, 1073741824 bytes, 2097152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00067806

Device     Boot Start     End Sectors  Size Id Type
/mnt/flat1       2048 2097151 2095104 1023M  b W95 FAT32

# dd if=/mnt/flat bs=512 skip=2048 count=1 | xxd
0000000: eb58 906d 6b64 6f73 6673 0000 0208 2000  .X.mkdosfs.... .
0000010: 0200 0000 00f8 0000 3f00 ff00 0000 0000  ........?.......
0000020: 00f8 1f00 0008 0000 0000 0000 0200 0000  ................
0000030: 0100 0600 0000 0000 0000 0000 0000 0000  ................
0000040: 0000 2967 c83b 9120 2020 2020 2020 2020  ..)g.;.         
0000050: 2020 4641 5433 3220 2020 0e1f be77 7cac    FAT32   ...w|.
0000060: 22c0 740b 56b4 0ebb 0700 cd10 5eeb f032  ".t.V.......^..2
0000070: e4cd 16cd 19eb fe54 6869 7320 6973 206e  .......This is n
0000080: 6f74 2061 2062 6f6f 7461 626c 6520 6469  ot a bootable di
0000090: 736b 2e20 2050 6c65 6173 6520 696e 7365  sk.  Please inse
00000a0: 7274 2061 2062 6f6f 7461 626c 6520 666c  rt a bootable fl
00000b0: 6f70 7079 2061 6e64 0d0a 7072 6573 7320  oppy and..press 
00000c0: 616e 7920 6b65 7920 746f 2074 7279 2061  any key to try a
00000d0: 6761 696e 202e 2e2e 200d 0a00 0000 0000  gain ... .......
00000e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000100: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000110: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000120: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000140: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000150: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000160: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000170: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000180: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000190: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00001a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00001b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00001c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00001d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.


Recognize what sector this is? Look at the 55 AA signature at the end of the sector. This designates an Master Boot Record (MBR). An MBR is located in the first sector of an MBR-partitioned disk.

Note that with VMware Workstation 10 you may get the error message VixDiskLib: Invalid configuration file parameter. Failed to read configuration file. You can safely ignore that message.

Best practice is to make a backup copy of your virtual disk before mounting it using the vmware-mount utility.

Shell String Concatenation

Many people are unaware that string concatenation using the += syntax is fully supported in modern versions of both the Bash and Korn shells

Here is a simple example which demonstrates the syntax:

str="Hello"
$ str+=" "
$ str+="World"
$ echo $str
Hello World
$ 

If you use this syntax with “numbers”, you end up with a string that looks like a number but is not a number.

$ a=2
$ a+=4
$ echo $a
$ 24

Shell Script to List ACPI tables

ACPI (Advanced Configuration and Power Interface) defines platform-independent interfaces for hardware discovery, configuration, power management and monitoring, and these tables contain lots of useful information for low-level programmers such as myself.

Here is a short shell script which I clobbered together a few days ago to list out the ACPI tables on a system together with a short description of each table where possible.

#!/bin/bash
#
#   Author:  Finnbarr P. Murphy 
#     Date:  January 2015
#  Purpose:  List ACPI tables 
#  License:  BSD
#

TMP1=$(mktemp -u -p /var/tmp/ acpiXXXXXX)
TMP2=$(mktemp -u -p /var/tmp/ acpiXXXXXX)
TMP3=$(mktemp -u -p /var/tmp/ acpiXXXXXX)

cat << EOF | sed -e 's/^[ \t]*//' > $TMP1 
    APIC, Multiple APIC Description
    BERT, Boot Error Record
    BGRT, Boot Graphics Resource
    BOOT, Simple Boot Flag
    CPEP, Corrected Platform Error Polling
    CRST, Core System Resources
    DBG2, Micosoft Debug Port2 
    DSDT, Differentiated System Description
    ECDT, Embedded Controller Boot Resources
    EINJ, Error Injection
    ERST, Error Record Serialization
    FACP, Fixed ACPI Description
    FACS, Firmware ACPI Control Structure
    FADT, Fixed ACPI Description
    GTDT, Generic Timer Description
    HEST, Hardware Error Source
    HPET, High Precision Event Timer
    MADT, Multiple APIC Description
    MCFG, Memory Configuration
    MSCT, Maximum System Characteristics
    MSDM, Microsoft Data Management
    PMTT, Platform Memory Topology 
    PSDT, Persistent System Description
    RASF, RAS Feature
    RSDP, Root System Description Pointer
    RSDT, Root System Description
    SBST, Smart Battery
    SLIC, Software Licensing Description
    SLIT, System Locality Distance Information
    SPCR, Serial Port Console Redirection
    SRAT, System Resource Affinity
    SSDT, Secondary System Descriptor
    XSDT, Extended System Description
EOF

# get the list of ACPI tables that Linux knows about
ls -1 /sys/firmware/acpi/tables | sed '/dynamic/d' > $TMP2
ls -1 /sys/firmware/acpi/tables/dynamic >> $TMP2
sort $TMP2 > $TMP3 

# output each table with a description where possible
awk -F, 'NR == FNR { a[$1] = $2; next }
         { 
             desc = a[substr($1,1,4)] 
             if (desc == "") {
                 desc = " Unknown ACPI Table"
             }
             printf "%s\t-%s Table\n", $1, desc
         }' $TMP1 $TMP3 

rm -f $TMP1 $TMP2 $TMP3 

exit 0


The above code should be self-explanatory to most experienced Linux administrators who are familiar with bash and awk.

Here is the output for my current system:

$ ./listapci
APIC	- Multiple APIC Description Table
BGRT	- Boot Graphics Resource Table
DSDT	- Differentiated System Description Table
FACP	- Fixed ACPI Description Table
FACS	- Firmware ACPI Control Structure Table
HPET	- High Precision Event Timer Table
MCFG	- Memory Configuration Table
SSDT1	- Secondary System Descriptor Table
SSDT2	- Secondary System Descriptor Table
SSDT3	- Secondary System Descriptor Table
SSDT4	- Secondary System Descriptor Table
SSDT5	- Secondary System Descriptor Table
SSDT6	- Secondary System Descriptor Table
$


The list of ACPI tables included with the script contains the most common ACPI tables up to revision 5 of the ACPI specification. It does not include some of the more uncommon tables. You can easily add those yourself if you are so inclined.

Address Space Layout Randomization in Linux

Address Space Layout Randomization (ASLR) was first implemented in Linux in 2001 and formally included in Linux kernel 2.6.12 in 2005. Microsoft followed soon afterwards and implemented ASLR in Vista in 2007.

ASLR randomizes process memory address space in order to prevent an attacker from finding the addresses of functions or ROP (Return Oriented Programming) gadgets required to successfully complete an exploit. The effectiveness of ASLR is limited by the amount of available entropy which varies from platform to platform depending on the implementation.

For ASLR to be useful, all segments of a processes memory space must be randomized. If even a single area of process memory is not randomized, ASLR can be defeated because an attacker could use that single area to discover useful ROP gadgets with which to build a successful exploit.

Address space randomization is used to hinder some types of attacks by making it more difficult for an attacker to predict target addresses. For example, attackers trying to execute return-to-libc or ROP gadget attacks must first locate the code to be executed, whereas attackers trying to execute shellcode injected on the stack must first find the appropriate SP and IP. Even NOP sleds have limitations!

Window binaries have to be specifically built with ALSR enabled, and all required DLLs must also have been built with ALSR enabled, for ALSR to be effective on a Windows platform. In many cases people build applications with ASLR enabled but include pre-built DLLs which are not ASLR-enabled. This totally defeats the purpose of ASLR.

By default, Linux binaries and shared objects are build with ASLR enabled except for the .text segment, i.e. the program code. The .text segment is only randomized if the program is build as a Position Independent Executable (PIC).

ASLR can be configured via /proc/sys/kernel/randomize_va_space. From the kernel documentation:

randomize_va_space:

    This option can be used to select the type of process address
    space randomization that is used in the system, for architectures
    that support this feature.

    0 - Turn the process address space randomization off.  This is the
        default for architectures that do not support this feature anyways,
        and kernels that are booted with the "norandmaps" parameter.

    1 - Make the addresses of mmap base, stack and VDSO page randomized.
        This, among other things, implies that shared libraries will be
        loaded to random addresses.  Also for PIE-linked binaries, the
        location of code start is randomized.  This is the default if the
        CONFIG_COMPAT_BRK option is enabled.

    2 - Additionally enable heap randomization.  This is the default if
        CONFIG_COMPAT_BRK is disabled.

    There are a few legacy applications out there (such as some ancient
    versions of libc.so.5 from 1996) that assume that brk area starts
    just after the end of the code+bss.  These applications break when
    start of the brk area is randomized.  There are however no known
    non-legacy applications that would be broken this way, so for most
    systems it is safe to choose full randomization.

    Systems with ancient and/or broken binaries should be configured
    with CONFIG_COMPAT_BRK enabled, which excludes the heap from process
    address space randomization.


To change the value permanently, add the setting to /etc/sysctl.conf.

Note that ASLR can slow program execution slightly and put some additional pressure on memory caches. When debugging code, and especially when trying to track down memory access bugs, ASLR is an impediment because it makes bugs non deterministic. By turning ASLR off, you can typically more easily reliably reproduce the bug.

You can disable ASLR for a specific program and its child processes by using the following command:

$ setarch `uname -m` -R program [args ...]


Wny build with ASLR enabled if a user can simply bypass it? I have to wonder if setarch should be one of the utilities that should be removed if hardening a Linux system.

Finally, ASLR is just one of a number of techniques that can be used to thwart an attacker. Other useful techniques include stack canaries, NX and W^R (non-executable stack) and RELRO (RELocation Read-Only).