Linux enumeration with read access only
05 Mar 2018Table of contents
Introduction
The proc filesystem
Default paths of configuration files
Introduction
I moved this article to my new blog. Click here to read it there.
If attackers exploit a vulnerability that gives them the ability to read arbitrary files from a remote system, they must count on default locations of configuration files to enumerate the system. They can’t execute commands or list the files inside the directories and their permissions.
An example of such attack is XML External Entity (XXE) vulnerability, which could lead to disclosure of local files. The example below shows XXE exploit to read /etc/passwd file.
But attackers can enumerate much more than just files, when they have file read access. By utilizing the /proc filesystem it’s possible to list running processes, mounted filesystems, network connections, listening ports, ARP cache and other things without the ability to execute commands.
Below is an example of XXE exploit to list running processes without the need of command execution.
Defenders should be aware that even with such restricted access it’s possible to disclose valuable information about the machine, which attackers can use to their advantage and further compromise the machine.
The proc filesystem
The man pages explain the proc filesystem well enough: “The proc filesystem is a pseudo-filesystem which provides an interface to kernel data structures. It is commonly mounted at /proc. […] Most of the files in the proc filesystem are read-only, but some files are writable, allowing kernel variables to be changed.”.
So the pseudo-files inside /proc represent data stored in and used by the kernel in real time. Some programs make use of the data available in /proc, make it more user-friendly and show the information to the user. One such program, which everyone knows, is top. You can easily verify this with strace:
root@kali:~# strace top
execve("/usr/bin/top", ["top"], 0x7ffd2d20a6e0 /* 44 vars */) = 0
[...snip...]
stat("/proc/9", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
open("/proc/9/stat", O_RDONLY) = 6
read(6, "9 (rcu_bh) S 2 0 0 0 -1 2129984 "..., 1024) = 148
close(6) = 0
open("/proc/9/statm", O_RDONLY) = 6
read(6, "0 0 0 0 0 0 0\n", 1024) = 14
close(6) = 0
open("/proc/9/status", O_RDONLY) = 6
[...snip...]
Below are the files that would be useful to an attacker.
/proc/net/arp - contains the ARP cache. Could be used to enumerate machines on the LAN.
root@kali:~# cat /proc/net/arp
IP address HW type Flags HW address Mask Device
192.168.0.1 0x1 0x2 64:70:02:cd:47:3a * wlan0
/proc/net/dev - contains network device status information and basic statistics. It’s used by the ifconfig program. Could be used to enumerate network interfaces.
root@kali:~# cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
wlan0: 21574215 26111 0 0 0 0 0 0 2779687 19557 0 0 0 0 0 0
eth0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
lo: 3576918 2567 0 0 0 0 0 0 3576918 2567 0 0 0 0 0 0
/proc/net/route - contains the routing table. The IP addresses are in HEX format.
root@kali:~# cat /proc/net/route
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
wlan0 00000000 0100A8C0 0003 0 0 600 00000000 0 0 0
wlan0 0000A8C0 00000000 0001 0 0 600 00FFFFFF 0 0 0
/proc/net/tcp - contains the TCP socket table. Can be used to enumerate network connections and listening ports. The uid field holds the effective UID of the creator of the socket. IP addresses and ports are shown in HEX format. If “rem_address” is null, “local_address” represents listening socket. In this case the machine listens on 0100007F:0FA0 (equal to 127.0.0.1:4000). Addresses are in little endian.
root@kali:~# cat /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 0100007F:0FA0 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 39786 1 ffff8add4e388000 100 0 0 10 0
1: 6400A8C0:DAAE 40706597:01BB 01 00000000:00000000 02:0000030C 00000000 0 0 84209 2 ffff8adcea1d8800 26 4 12 10 -1
/proc/net/tcp6 - same as /proc/net/tcp, but for IPv6.
/proc/net/udp - contains the UDP socket table.
/proc/net/udp6 - contains the UDP socket table for IPv6.
/proc/net/wireless - contains wireless device information and basic statistics.
root@kali:~# cat /proc/net/wireless
Inter-| sta-| Quality | Discarded packets | Missed | WE
face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
wlan0: 0000 68. -42. -256 0 0 0 0 208 0
/proc/[pid]/cmdline - holds the complete command line for the process with the given PID. The arguments are separated by a null byte, that’s why when printed they appear concatenated.
root@kali:~# python -m SimpleHTTPServer 8080 &
[2] 2837
root@kali:~# Serving HTTP on 0.0.0.0 port 8080 ...
root@kali:~# cat /proc/2837/cmdline
python-mSimpleHTTPServer8080
It’s possible to write a script to enumerate the processes on the system by reading /proc/[pid]/cmdline for a range of PIDs (for example from 1 to 30000 or more). Here’s an example of such script, which enumerates processes through tftp:
#!/bin/bash
for i in {1..30000}
do
tftp 192.168.0.1 2>&1 >/dev/null 2>/dev/null << EOF
get /proc/$i/cmdline
quit
EOF
if ! [ -z "$(cat cmdline)" ]; then
cat cmdline && echo
fi
done
And the result is:
/sbin/init
/lib/systemd/systemd-journald
vmware-vmblock-fuse/run/vmblock-fuse-orw,subtype=vmware-vmblock,default_permissions,allow_other,dev,suid
[...snip...]
/usr/sbin/vsftpd/etc/vsftpd.conf
/usr/sbin/cron-f
/usr/sbin/rsyslogd-n
/usr/sbin/sshd-D
/usr/sbin/squid-YC-f/etc/squid/squid.conf
(squid-1)-YC-f/etc/squid/squid.conf
(logfile-daemon)/var/log/squid/access.log
/usr/sbin/apache2-kstart
/usr/sbin/apache2-kstart
[...snip...]
/proc/[pid]/status - holds information about the process name, state, PPID, UID, GID and supplementary group list.
root@kali:~# cat /proc/2837/status
Name: python
Umask: 0022
State: S (sleeping)
Tgid: 2837
Ngid: 0
Pid: 2837
PPid: 2473
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 256
Groups:
[...snip...]
/proc/[pid]/loginuid - The loginuid value is used to track what account a user gained system access with. All system entry point programs should set this value right before changing to the uid of the user granted access so that audit events are properly attributed to the that user.
root@kali:~# ssh test_user@localhost
test_user@localhost's password:
$ cat /proc/self/loginuid
1000
$ cat /proc/2837/loginuid
0
/proc/[pid]/comm - the command name associated with the process. Typically the process name. Different threads in the same process may have different comm values, accessible via /proc/[pid]/task/[tid]/comm.
root@kali:~# cat /proc/2837/comm
python
/proc/[pid]/attr/current - contains the SELinux security context of a process.
root@kali:~# cat /proc/2837/attr/current
unconfined
/proc/[pid]/environ - contains the initial environment variables which were set when the currently executing program was started.
In all previous examples, “self” can be used instead of [pid], to use the current process PID.
root@kali:~# cat /proc/self/comm
cat
/proc/partitions - enumerate the available partitions.
root@kali:~# cat /proc/partitions
major minor #blocks name
8 0 625131864 sda
8 1 512000 sda1
8 2 101888000 sda2
8 3 215529472 sda3
8 4 1 sda4
8 5 233792442 sda5
8 6 41942016 sda6
8 7 1999872 sda7
8 8 29464576 sda8
11 0 1048575 sr0
/proc/modules - list the loaded kernel modules.
root@kali:~# cat /proc/modules
fuse 98304 5 - Live 0xffffffffc0c2c000
ctr 16384 4 - Live 0xffffffffc072d000
ccm 20480 6 - Live 0xffffffffc06f6000
pci_stub 16384 1 - Live 0xffffffffc06f1000
vboxpci 24576 0 - Live 0xffffffffc06e6000 (O)
[...snip...]
/proc/mounts - holds the mounted filesystems.
root@kali:~# cat /proc/mounts
sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
[...snip...]
/dev/sda2 /mnt fuseblk rw,relatime,user_id=0,group_id=0,allow_other,blksize=4096 0 0
/proc/sched_debug - Could be used to list the running processes on every CPU
root@kali:~# cat /proc/sched_debug
[...snip...]
runnable tasks:
task PID tree-key switches prio wait-time sum-exec sum-sleep
----------------------------------------------------------------------------------------------------------
mm_percpu_wq 6 55.852300 2 100 0.000000 0.002146 0.000000 0 0 /
ksoftirqd/0 7 1236364.953796 8587 120 0.000000 208.716001 0.000000 0 0 /
rcu_bh 9 59.855652 2 120 0.000000 0.001254 0.000000 0 0 /
migration/0 10 0.000000 124 0 0.000000 7.941575 0.000000 0 0 /
watchdog/0 11 0.000000 2565 0 0.000000 33.640540 0.000000 0 0 /
[...snip...]
rsyslogd 544 1152885.712609 46 120 0.000000 15.026057 0.000000 0 0 /
rs:main Q:Reg 568 1147101.764004 4543 120 0.000000 178.167006 0.000000 0 0 /
NetworkManager 573 1235783.020177 2888 120 0.000000 3033.867445 0.000000 0 0 /
gdbus 625 1229055.325319 3619 120 0.000000 429.441316 0.000000 0 0 /
iprt-VBoxTscThr 647 1225259.884033 170 120 0.000000 6.366787 0.000000 0 0 /
gmain 657 3200.951729 7 120 0.000000 0.119794 0.000000 0 0 /
gdbus 658 1104709.985140 190 120 0.000000 30.162614 0.000000 0 0 /
wpa_supplicant 684 1235805.678182 1472 120 0.000000 1027.728392 0.000000 0 0 /
radeon_cs:0 707 7005.506352 11 120 0.000000 1.386411 0.000000 0 0 /
dhclient 708 4410.439050 29 120 0.000000 9.122386 0.000000 0 0 /
[...snip...]
python 2837 188838.661437 5266 120 0.000000 699.150197 0.000000 0 0 /user.slice/
[...snip...]
/proc/version - holds information about the kernel version
root@kali:~# cat /proc/version
Linux version 4.13.0-kali1-amd64 (devel@kali.org) (gcc version 6.4.0 20171026 (Debian 6.4.0-9)) #1 SMP Debian 4.13.13-1kali1 (2017-11-17)
/proc/bus/input/devices - could be used to enumerate input devices connected to the machine (keyboard, mouse, camera, touchpad…).
root@kali:~# cat /proc/bus/input/devices
I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/devices/platform/i8042/serio0/input/input0
U: Uniq=
H: Handlers=sysrq kbd leds event0
B: PROP=0
B: EV=120013
B: KEY=402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=7
I: Bus=0003 Vendor=0458 Product=003a Version=0111
N: Name="Genius Optical Mouse"
[...snip...]
I: Bus=0011 Vendor=0002 Product=0007 Version=01b1
N: Name="SynPS/2 Synaptics TouchPad"
[...snip...]
/proc/bus/pci/devices - enumerate PCI connected devices. Go to the right end.
0100 10026742 1d b000000c 0 c2000004 0 4001 0 c0002 10000000 0 20000 0 100 0 20000 radeon
0101 1002aa90 1e c2020004 0 0 0 0 0 0 4000 0 0 0 0 0 0 snd_hda_intel
0800 10ec8723 11 3001 0 c3000004 0 0 0 0 100 0 4000 0 0 0 0 rtl8723ae
0900 10ec8136 18 2001 0 c000400c 0 c000000c 0 0 100 0 1000 0 4000 0 0 r8169
/proc/uptime - the uptime of the machine.
root@kali:~# cat /proc/uptime
11069.37 41314.72
/proc/loadavg - the average load of the machine. Similar to what top shows.
root@kali:~# cat /proc/loadavg
0.23 0.23 0.32 1/616 3225
/proc/meminfo - holds information about RAM.
/proc/cpuinfo - contains information about the CPU.
/proc/sys - a directory which holds system configuration variables. For example if /proc/sys/net/ipv4/ip_forward is set to 1, that means the system can forward ipv4 packets (act as a router). The variables are too many to be listed in this post. You could explore on your own.
Default paths of configuration files
For completeness I’ll list the default paths to some configuration files and other files valuable to an attacker.
/root/.bashrc - executed every time an interactive shell (terminal) is opened.
/root/.profile - executed every time a user logs in.
/root/.bash_profile - executed every time the user logs in.
/root/.bash_history - history of the executed bash commands in terminal.
/root/.ssh/id_rsa - private rsa key of the root user.
/root/.ssh/authorized_keys - public keys of machines allowed to login via ssh as the root user.
/root/.ssh/known_hosts - hosts to which the root user connected via ssh.
/home/[username]/.bashrc - executed every time an interactive shell (terminal) is opened.
/home/[username]/.profile - executed every time a user logs in.
/home/[username]/.bash_profile - executed every time the user logs in.
/home/[username]/.bash_history - history of the executed bash commands in terminal.
/home/[username]/.ssh/id_rsa - private rsa key of the user.
/home/[username]/.ssh/authorized_keys - public keys of machines allowed to login via ssh as the user.
/home/[username]/.ssh/known_hosts - hosts to which the user connected via ssh.
/etc/ssh/sshd_config - ssh server configuration
/etc/ssh/ssh_host_rsa_key - private rsa key of the ssh server
/etc/ssh/ssh_host_rsa_key.pub - public rsa key of the ssh server
/etc/fstab - filesystems which the system mounts
/etc/passwd - could be used to enumerate users and services
/etc/shadow - contains the hashed passwords of the users
/etc/group - holds the existings groups and group memberships on the system
/etc/hosts - static DNS table lookup for hostnames
/etc/hostname - the hostname of the machine
/etc/issue - linux distribution
/etc/lsb-release - linux distribution and version information
/etc/resolv.conf - configured DNS nameservers
/etc/network/interfaces - static network interfaces configuration
/etc/crontab - the system crontab
/var/spool/cron/crontabs/[username] - the user crontab
/var/log/apt/history.log - log of installed/removed apt packages. Could be used to enumerate installed programs.
/etc/apache2/apache2.conf - apache2 configuration
/etc/apache2/ports.conf - configuration of listening ports used by apache2
/etc/apache2/sites-enabled/000-default.conf - virtual host configuration
/etc/apache2/sites-available/000-default.conf - virtual host configuration
/usr/local/apache2/ - if apache is installed from source, the default configuration files are found under this directory.
/var/www/html/ - usually the default directory for the webpage source code and files. Should look for index.php or other well known files.
/etc/squid/squid.conf - squid proxy configuration file
/etc/nginx/nginx.conf - nginx configuration
/etc/nginx/sites-available/default - virtual host configuration
/etc/nginx/sites-enabled/default - virtual host configuration
/etc/php/[version]/cli/php.ini - php configuration file