· Alex · security  · 30 min read

Linux for Hackers 101

Learn a bit about Linux, its filesystem, basic and advanced commands every hacker should know

Learn a bit about Linux, its filesystem, basic and advanced commands every hacker should know

In this article I’m going to explain a few basic things about Linux, its filesystem and the commands all beginner hackers should know. Let’s dive in!

Basic Linux Commands for Hackers

Let’s start with a few basic commands:

  • pwd tells us where are we are on the filesystem. It stands for print working directory.

Every process on Linux has a working directory. A directory is a collection of files, but on Linux, a directory is fundamentally a special type of file. When a process is started, it inherits the working directory from its parent process.

Note: On Linux, everything is a file. Settings, interfaces, devices, processes, etc. Everything is represented as a file.

Example: suppose you’re in a terminal in the /home/user folder and you launch your script which is stored in /home/user/apps/script.sh. The working directory of script.sh will be /home/user, not /home/user/apps/script.sh as one might assume. Why? Because the terminal is actually a process. It might be bash, sh, zsh, etc. Its working directory is /home/user (because that’s where we are) and it’s the parent process of the script.

  • cd stands for change directory and it’s used to change the working directory. You can use it to navigate the filesystem. Running cd .. will move you up one folder. And you can just as well use cd ../.. to go up 2 directories and so on. You can repeatedly use cd .. until you reach the root / of the filesystem, which is like the parent folder of everything.

Tip: consider the command: cd ../../../../../../../../../../../../. There are 12 pairs of ... Where would this put us on the filesystem? Well, we’ll still be in the root /:

$ pwd              
/usr/local/bin

$ cd ../../../../../../../../../../../../
$ pwd
/

No matter how many you add, the highest you can go is still /. This approach can be used when exploiting a directory traversal vulnerability. Say you attempt to exploit such a vulnerability and you want to reach /etc/passwd (which stores system user names, among other things). And you cannot provide an exact path when exploiting the vulnerability. You can use a similar path with a big number of .. to get you into the root and then add /etc/passwd at the end (../../../../../../../../../../../../etc/passwd will be transformed to/etc/passwd, as long as there are less folders in the current path than the number of ../). So just make sure the number is big enough to traverse all folders.

  • ls simply lists what’s in the current directory. Lots of Linux beginners use cd before using the ls command. You can just as well list content in any folder from whatever your current directory is. Example: pwd tells you you’re in /home/user/, but you can use ls /usr/bin to list files there without switching to the directory.

Two important arguments you should remember:

  • -a which shows hidden files. On Linux hidden files/folders start with a dot (.).
  • -l prints content in long format. This way, it prints file mode (permissions), number of links, owner name, group name, number of bytes in the file, a timestamp when the file was last modified and the name:
ls -l /usr/bin
total 1038284
lrwxrwxrwx 1 root root            31 Dec  7 19:55  1password2john -> ../share/john/1password2john.py
-rwxr-xr-x 1 root root            96 Aug  1  2022  2to3-2.7
-rwxr-xr-x 1 root root            39 Aug 15  2020  7z
lrwxrwxrwx 1 root root            24 Dec  7 19:55  7z2john -> ../share/john/7z2john.pl
-rwxr-xr-x 1 root root            40 Aug 15  2020  7za
-rwxr-xr-x 1 root root            40 Aug 15  2020  7zr
..

Tip: Anytime you’re unsure about an argument or command, use the man command to see its manual page (man ls) with the complete list of arguments it supports. Some commands support an -h or --help argument that present syntax.

Note that you don’t have to specify all the dashes if, for example you use 3 arguments. You can just do ls -laR (R lists folders recursively).

  • clear just clears out the terminal. Like clearing a chalkboard. Some prefer having a clear and uncluttered terminal as it’s easier to see what you’re working on.

The Linux Filesystem Explained

Now that we know some basic commands, let’s familiarize ourselves with what’s on the Linux filesystem.

If we run an ls -l / we can see what’s in the root.

lrwxrwxrwx   1 root root     7 May 12  2023 bin -> usr/bin
drwxr-xr-x   3 root root  4096 Dec 16 12:01 boot
drwxr-xr-x  17 root root  3440 Jan 11 13:04 dev
drwxr-xr-x 195 root root 12288 Mar  3 08:30 etc
drwxr-xr-x   3 root root  4096 May 12  2023 home
lrwxrwxrwx   1 root root    33 Dec 16 11:58 initrd.img -> boot/initrd.img-6.5.0-kali3-amd64
lrwxrwxrwx   1 root root    33 May 12  2023 initrd.img.old -> boot/initrd.img-6.1.0-kali5-amd64
lrwxrwxrwx   1 root root     7 May 12  2023 lib -> usr/lib
lrwxrwxrwx   1 root root     9 May 12  2023 lib32 -> usr/lib32
lrwxrwxrwx   1 root root     9 May 12  2023 lib64 -> usr/lib64
drwx------   2 root root 16384 May 12  2023 lost+found
drwxr-xr-x   3 root root  4096 May 12  2023 media
drwxr-xr-x   3 root root  4096 Jan 16 01:05 mnt
drwxr-xr-x   3 root root  4096 May 12  2023 opt
dr-xr-xr-x 331 root root     0 Jan 11 11:06 proc
drwx------   5 root root  4096 Jan 16 00:23 root
drwxr-xr-x  38 root root  1000 Feb 27 15:58 run
lrwxrwxrwx   1 root root     8 May 12  2023 sbin -> usr/sbin
drwxr-xr-x   3 root root  4096 May 12  2023 srv
dr-xr-xr-x  13 root root     0 Jan 11 11:06 sys
drwxrwxrwt  29 root root 12288 Mar  8 21:39 tmp
drwxr-xr-x  15 root root  4096 Dec 16 11:50 usr
drwxr-xr-x  12 root root  4096 Dec 16 12:24 var
lrwxrwxrwx   1 root root    30 Dec 16 11:58 vmlinuz -> boot/vmlinuz-6.5.0-kali3-amd64
lrwxrwxrwx   1 root root    30 May 12  2023 vmlinuz.old -> boot/vmlinuz-6.1.0-kali5-amd64

First we have bin which stands for binaries. Let’s see what’s inside: cd /bin ls

2to3-2.7                             expect_multixterm                     lion2john
...  

Whoaaa, tons of files in here. These are all commands you can run on your Linux machine and you’ll end up using many of them, including the ls command. To confirm this is the case, you can use ls -l ls which will only give you a listing with the ls file:

-rwxr-xr-x 1 root root 151344 Sep 20  2022 ls

Now you might have noticed there’s another type of bin called sbin. This one contains super (hence the s) binaries meant to be used with administrator (root) privileges.

Looking at the directory listing, you might have noticed both the bin and sbin directories have a -> next to their names. This means they’re actually symlinks (similar to shortcuts from the Windows world). And what’s after the arrow, is what they point to. We see they both point to folders with the same names from the /usr directory.

Let’s look it up:

$ cd /usr/bin
$ pwd
/usr/bin
$ ls -l ls       
-rwxr-xr-x 1 root root 151344 Sep 20  2022 ls

So when you run ls which one does it actually execute? A common (bad) way to look that up is by using the which command. However, without going into details, which makes some assumptions that are not always correct. Let’s see what it returns on my Kali machine:

$ which ls
ls: aliased to ls --color=auto

This shows that I have an alias created for this command that colorizes the output. So it doesn’t really help us to achieve what we wanted. An alias is just what the name says. You can create different names/aliases to run commands for convenience.

The correct way to do it, is to use the type command (or where on some distributions), which is a POSIX compliant command and should work on all Linux distributions. Furthermore, using the -a argument will show us the entire chain:

$ type -a ls
ls is an alias for ls --color=auto
ls is /usr/bin/ls
ls is /bin/ls

$ where ls  
ls: aliased to ls --color=auto
/usr/bin/ls
/bin/ls

We see that both type and where commands give similar results on Kali. ls is aliased to ls --color=auto, /usr/bin/ls is the real location of the file and /bin/ls is a symbolic link to it.

Let’s move on to the rest of the folders in root filesystem.

  • boot contains a few files critical to the operating system start-up.
-rw-r--r-- 1 root root   258844 Feb 23  2023 config-6.1.0-kali5-amd64
-rw-r--r-- 1 root root   265572 Oct  9 18:30 config-6.5.0-kali3-amd64
drwxr-xr-x 6 root root     4096 Dec 16 11:58 grub
-rw-r--r-- 1 root root 75812606 Nov 23 19:41 initrd.img-6.1.0-kali5-amd64
-rw-r--r-- 1 root root 77195749 Dec 16 12:01 initrd.img-6.5.0-kali3-amd64
-rw-r--r-- 1 root root       83 Feb 23  2023 System.map-6.1.0-kali5-amd64
-rw-r--r-- 1 root root       83 Oct  9 18:30 System.map-6.5.0-kali3-amd64
-rw-r--r-- 1 root root  8519296 Feb 23  2023 vmlinuz-6.1.0-kali5-amd64
-rw-r--r-- 1 root root  9155776 Oct  9 18:30 vmlinuz-6.5.0-kali3-amd64

Most important files here:

  • vmlinuz is the bootable Linux kernel image. The name stands for “Virtual Memory LINUx GZip,” indicating that it’s a gzip-compressed Linux kernel. You might have multiple versions of this file as you upgrade your OS over time.

  • initrd is the “Initial RAM Disk”. It’s a temporary filesystem used in the boot process and it’s loaded by the bootloader along with the kernel image. It’s purpose is to act as a temporary filesystem until the actual root filesystem is mounted.

Let’s move on to other folders. dev stands for devices. Remember I said that everything on Linux is file? This includes devices. For example, you can find your storage disks here (sda/vda files):

ls -la sda*                                                   
brw-rw---- 1 root disk 8, 0 Mar 17 19:56 sda
brw-rw---- 1 root disk 8, 1 Mar 17 19:56 sda1
brw-rw---- 1 root disk 8, 2 Mar 17 19:56 sda2
brw-rw---- 1 root disk 8, 5 Mar 17 19:56 sda5

The etc folder contains configuration files. From the package manager settings to your network configuration, you’ll find just about everything here. For example, in /etc/apt you can configure the apt package manager:

$ cd /etc/apt
$ ls -la
total 48
drwxr-xr-x   8 root root  4096 Dec 16 11:43 .
drwxr-xr-x 195 root root 12288 Mar 17 19:56 ..
drwxr-xr-x   2 root root  4096 Dec 16 11:59 apt.conf.d
drwxr-xr-x   2 root root  4096 Feb  8  2023 auth.conf.d
drwxr-xr-x   2 root root  4096 Feb  8  2023 keyrings
drwxr-xr-x   2 root root  4096 Feb  8  2023 preferences.d
-rw-r--r--   1 root root   293 May 12  2023 sources.list
-rw-r--r--   1 root root     0 May 12  2023 sources.list~
drwxr-xr-x   2 root root  4096 Feb  4 11:35 sources.list.d
-rw-r--r--   1 root root  3494 Dec 16 11:41 trusted.gpg
drwxr-xr-x   2 root root  4096 Dec 16 11:50 trusted.gpg.d

home is where the users live. This usually contains a folder for each user, other than root. So you might be wondering where is root? Well, since it’s the super user, it has it’s own living space in /root

Moving on, we have a series of lib folders: lib -> usr/lib lib32 -> usr/lib32 lib64 -> usr/lib64 These contain libraries (.so files, similar to DLLs on Windows) that Linux and its applications need to run properly.

Next we have media and mnt. These 2 directories will contain pluggable drives, shares, etc. media will have things that the system automatically adds (or mounts in Linux terms) for you. This will be your USB sticks and such. And mnt is where you will manually mount things like network shares or disk images, ISOs, etc.

proc is a virtual filesystem created when the system boots. And it contains information about processes, system configuration, hardware, and more, while being grouped as, you guessed it, files. If you ls this folder, you’ll see (among other things) a bunch of numbered directories. These numbers are process identification numbers or PIDs. They’re the same numbers you’ll see if you run the ps tool (more on this later). You’ll be using the PID when you want to shutdown or kill a certain process.

run is where some early boot Linux processes store run-time information.

sys is another virtual directory like proc and dev and also contains information from devices connected to your computer.

tmp just holds temporary files and it’s usually a place where every user can write (tip: drop files here; caveat being that some sysadmins mark it as non-executable). It also tends to be cleaned-out when restarting the OS.

We’ve already talked a bit about the usr directory. This is where Unix (the precursor of Linux) used to store user home directories (now home). Besides commands, this one contains a variety of things like libraries, documentation, media files, etc.

var stands for variable. Originally, its contents was considered variable, as in it changed frequently. Today, that doesn’t necessarily apply because there are many other directories that also contain data that changes frequently, especially the virtual directories we saw previously.

Next, let’s talk about some more Linux commands you should know about.

Top Linux Commands Every Hacker Should Know

How to use the cat command to view files?

cat stands for ‘concatenation’ and it’s a very versatile command.

  • The most frequent use is to view the contents of a file:
cat file

Or multiple files:

cat file1 file2
  • But you can also use it to create a new file:
cat >file.txt

After entering the command you can start writing the contents of the file. When you’re done, press CTRL+D to exit and save the file.

  • Instead of viewing files, you can concatenate files by redirecting output (stdout - more on this later):
cat file1 file2 > file3

The above command will concatenate the contents of file1 and file2 and save it into a new file called file3. This will overwrite file3, if it exists. To append to an existing file, use >> instead of >. And this works with any Linux command:

cat file1 file2 >> file3
  • If the contents of the file is very big, you can pipe (this is the pipe character: |) the output of cat to another command such as more or less:
cat bigfile | more

The more and less commands allow you to paginate output and navigate easier through content. Make sure to check out their man pages to learn how to use them.

How to use the cp command to copy things around the filesystem?

cp stands for copy and you can use it to copy files or directories on the filesystem.

  • Copy the source file to target file:
cp source target
  • You can also copy entire directories, together with its content using the -r (recursive) argument:
cp -r source target

If you don’t specify -r, and your attempt to copy a non-empty folder, it will ignore the directory, giving an error output like cp: -r not specified; omitting directory X.

How to use the rm command to delete files and folders?

rm stands for remove and well, you can use it to delete files and folders.

  • Delete a file or multiple files:
rm file 
rm file1 file2
  • You can also use it to remove a directory:
rm -d directory
  • Attempting to remove a non-empty directory will give an error (rm: cannot remove 'X': Directory not empty). You can use -r to remove the folder along with its contents:
rm -r directory
  • If the directory contains read-only files, it will prompt you to confirm deletion for each one. To override this behavior, use the -f (force) argument. Always be careful with it as you can mess up your system if you delete the wrong thing (google “rm -rf / accident”):
rm -rf directory

How to use the whoami and id commands to see who we are?

whoami tells you what user you are on the system. It gives the same output as id -un:

$ whoami
user
$ id -un
user

id is a more complex command as it print real and effective user and group IDs (which groups the current user belongs to, and thus what privileges it has).

How to use the ps, pstree and top commands to investigate running processes?

These are all commands used to list information about running processes.

  • ps has lots of arguments, but the ones I use the most are -ef:
$ ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 Mar17 ?        00:00:01 /sbin/init splash
root           2       0  0 Mar17 ?        00:00:00 [kthreadd]
root           3       2  0 Mar17 ?        00:00:00 [rcu_gp]
...

The -e will display all running processes (from all users). The -f stands for full format listing, so it will give us:

  • the user under which the process runs (UID)

  • the process ID (PID), parent process ID (PPID)

  • CPU utilization (C)

  • start time (STIME)

  • the name of the controlling terminal for the process (TTY)

  • the sum of CPU time used by the process (TIME)

  • and the name of the command used to start the process (CMD).

  • Another useful argument for ps is --forest which will print a tree so you can clearly see which process was run by other processes:

$ ps -ef --forest
...
root        1194     793  0 Mar17 ?        00:00:00  \_ lightdm --session-child 13 24
user        1244    1194  0 Mar17 ?        00:00:00      \_ xfce4-session
user        1308    1244  0 Mar17 ?        00:00:00          \_ /usr/bin/ssh-agent x-session-manager
...

The pstree command gives a similar output to --forest:

$ pstree
systemd─┬─ModemManager───3*[{ModemManager}]
        ├─NetworkManager───3*[{NetworkManager}]
        ├─accounts-daemon───3*[{accounts-daemon}]
        ├─agetty
        ├─colord───3*[{colord}]
        ├─containerd───7*[{containerd}]
        ├─cron
        ├─dbus-daemon
        ├─dockerd───7*[{dockerd}]
        ├─haveged
        ├─lightdm─┬─Xorg───{Xorg}
         ├─lightdm─┬─xfce4-session─┬─Thunar───3*[{Thunar}]
               ├─agent───3*[{agent}]

The top command shows the current running processes along with CPU, memory consumption and other statistics:

top - 19:43:43 up 23:47,  1 user,  load average: 0.00, 0.03, 0.00
Tasks: 250 total,   1 running, 249 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.2 us,  0.7 sy,  0.0 ni, 99.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st 
MiB Mem :   7939.1 total,   5314.4 free,   1269.9 used,   1660.4 buff/cache     
MiB Swap:    975.0 total,    975.0 free,      0.0 used.   6669.2 avail Mem 

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+COMMAND                                                             
829 root      20   0  645092 376676  58468 S   0.7   4.6   2:05.22Xorg                                                                
814 root      20   0 1795020  46296  30208 S   0.3   0.6   1:09.56containerd                                                          
...

Foreground and background processes

Let’s assume you’ve run the above top command. Our terminal is now only showing the command output and we can’t run any other terminal commands. This is called a foreground process. But what if you want to run other commands while the first one is running?

First, we can use CONTROL+Z to suspend the process and get back to our shell:

zsh: suspended (signal)  top

The top command is currently freezed. We can see this with the jobs command:

$ jobs
[1]  + suspended (signal)  top

Now we have two options:

  • we can use the fg 1 command (1 being the [1] from the jobs output; if you omit the argument, it will select the last suspended process) to return to our process, unsuspend it and make it a foreground process again (while blocking our ability to enter commands in terminal). If you want to exit and stop the process, just press CONTROL+C and you’ll be back to the command line.
  • or we can use the bg 1 command (same things apply regarding arguments) to unsuspend the process but let it continue in the background, hence allowing us to write further commands in the terminal.

If fg 1 doesn’t work in your terminal, use fg %1 and you should be good (this is what works in Kali). So try it out for yourself.

You can make a program run in the background from the start by appending & at the end:

ping 127.0.0.2&
[1] 707944

PING 127.0.0.2 (127.0.0.2) 56(84) bytes of data.
64 bytes from 127.0.0.2: icmp_seq=1 ttl=64 time=0.023 ms
┌──(user@kali)-[~]
└─$ 64 bytes from 127.0.0.2: icmp_seq=2 ttl=64 time=0.029 ms
64 bytes from 127.0.0.2: icmp_seq=3 ttl=64 time=0.026 ms
64 bytes from 127.0.0.2: icmp_seq=4 ttl=64 time=0.026 ms
64 bytes from 127.0.0.2: icmp_seq=5 ttl=64 time=0.025 ms
64 bytes from 127.0.0.2: icmp_seq=6 ttl=64 time=0.026 ms

Notice the program keeps printing results but we can still enter commands.

To foreground the process and exit, enter fg and hit enter (might be hard to see because of the ping output, but it will work):

64 bytes from 127.0.0.2: icmp_seq=15 ttl=64 time=0.029 ms
64 bytes from 127.0.0.2: icmp_seq=16 ttl=64 time=0.021 ms
fg 
[1]  + running    ping 127.0.0.2
64 bytes from 127.0.0.2: icmp_seq=17 ttl=64 time=0.026 ms

Now we can hit CONTROL+C to finally close ping:

^C
--- 127.0.0.2 ping statistics ---
19 packets transmitted, 19 received, 0% packet loss, time 18432ms
rtt min/avg/max/mdev = 0.021/0.025/0.029/0.002 ms

How to stop or shutdown processes using the kill command?

  • To cleanly exit a process, you can just use:
kill PID

To obtain the PID of the process, use any of the process specific commands listed above. Or you can use the pidof command:

$ pidof firefox
1556 44433

If you have multiple instances of the same process, pidof will show all PIDs. Then just use the PID with kill:

kill 1556

kill can send a variety of signals to the process. kill with no arguments sends the 15 signal which is SIGTERM. You can view all the signals that can be used with:

kill -l

Two frequently used signals are SIGHUP (1) and SIGKILL (9). SIGHUP is used to reload a process, while SIGKILL terminates a process (like pulling the cord when something is unresponsive):

kill -9 1556

How to see what users exist on the system?

It’s really simple:

$ cat /etc/passwd
root:x:0:0:root:/root:/usr/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
mysql:x:100:107:MySQL Server,,,:/nonexistent:/bin/false
tss:x:101:108:TPM software stack,,,:/var/lib/tpm:/bin/false
strongswan:x:102:65534::/var/lib/strongswan:/usr/sbin/nologin
systemd-timesync:x:997:997:systemd Time Synchronization:/:/usr/sbin/nologin
redsocks:x:103:109::/var/run/redsocks:/usr/sbin/nologin
rwhod:x:104:65534::/var/spool/rwho:/usr/sbin/nologin
iodine:x:105:65534::/run/iodine:/usr/sbin/nologin
messagebus:x:106:111::/nonexistent:/usr/sbin/nologin
miredo:x:107:65534::/var/run/miredo:/usr/sbin/nologin
redis:x:108:114::/var/lib/redis:/usr/sbin/nologin
usbmux:x:109:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
mosquitto:x:110:116::/var/lib/mosquitto:/usr/sbin/nologin
tcpdump:x:111:118::/nonexistent:/usr/sbin/nologin
sshd:x:112:65534::/run/sshd:/usr/sbin/nologin
_rpc:x:113:65534::/run/rpcbind:/usr/sbin/nologin
dnsmasq:x:114:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
statd:x:115:65534::/var/lib/nfs:/usr/sbin/nologin
avahi:x:116:122:Avahi mDNS daemon,,,:/run/avahi-daemon:/usr/sbin/nologin
stunnel4:x:996:996:stunnel service system account:/var/run/stunnel4:/usr/sbin/nologin
Debian-snmp:x:117:123::/var/lib/snmp:/bin/false
_gvm:x:118:124::/var/lib/openvas:/usr/sbin/nologin
speech-dispatcher:x:119:29:Speech Dispatcher,,,:/run/speech-dispatcher:/bin/false
sslh:x:120:125::/nonexistent:/usr/sbin/nologin
postgres:x:121:126:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
pulse:x:122:127:PulseAudio daemon,,,:/run/pulse:/usr/sbin/nologin
saned:x:123:130::/var/lib/saned:/usr/sbin/nologin
inetsim:x:124:131::/var/lib/inetsim:/usr/sbin/nologin
lightdm:x:125:132:Light Display Manager:/var/lib/lightdm:/bin/false
geoclue:x:126:133::/var/lib/geoclue:/usr/sbin/nologin
polkitd:x:994:994:polkit:/nonexistent:/usr/sbin/nologin
nm-openvpn:x:128:135:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
rtkit:x:129:136:RealtimeKit,,,:/proc:/usr/sbin/nologin
colord:x:130:137:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
nm-openconnect:x:131:138:NetworkManager OpenConnect plugin,,,:/var/lib/NetworkManager:/usr/sbin/nologin
user:x:1000:1000:user,,,:/home/user:/usr/bin/zsh

You might recognize the first one (root) and the last one, which is probably your username (user in this case). But what are all the others? Well, these are users that certain services or applications use for separation of duties or privileges (a well known security principle).

And don’t worry, you can’t login with most of them. You can tell from the last part of each line which shows what shell the user is assigned at login. So in this case, only root, postgres and user have valid shells assigned (bash & zsh).

Lets consider the last line:

user:x:1000:1000:user,,,:/home/user:/usr/bin/zsh
  • The x is where the password used to be in older Linux/Unix versions. Now it’s stored someplace else (/etc/shadow). You can also cat the shadow file with root privileges/sudo, but you’ll only see a hash of your password.

  • The first number group (1000) is the user id (UID) and the second one is the group id (GID).

  • The next field is the user’s name (user in this case). And the next few fields are informational and don’t matter that much, until:

  • /home/user is the user’s home directory.

  • last, but not least, we have the user shell used at login which we already talked about.

How to add a new user in Linux?

There are two commands: adduser and useradd. Not all Linux distributions come with the first one, but it’s the easier option.

  • To add a user, you need to run the command with sudo rights:
$ sudo adduser tmpp
info: Adding user `tmpp' ...
info: Selecting UID/GID from range 1000 to 59999 ...
info: Adding new group `tmpp' (1001) ...
info: Adding new user `tmpp' (1001) with group `tmpp (1001)' ...
info: Creating home directory `/home/tmpp' ...
info: Copying files from `/etc/skel' ...
New password: 
Retype new password: 
passwd: password updated successfully
Changing the user information for tmpp
Enter the new value, or press ENTER for the default
        Full Name []: 
        Room Number []: 
        Work Phone []: 
        Home Phone []: 
        Other []: 
Is the information correct? [Y/n] 
info: Adding new user `tmpp' to supplemental / extra groups `users' ...
info: Adding user `tmpp' to group `users' ...

You just pass it what user you want to add. It will then ask you for the password and some informational data, which you can ignore if you’d like (by pressing ENTER). It will also automatically create the home folder for you.

Now looking in /etc/passwd, we have our new user complete with its group and login shell:

tmpp:x:1001:1001:,,,:/home/tmpp:/bin/bash

The useradd command does only the first part of this process, as in adding it to /etc/passwd, but it won’t ask you to set a password, set group info, etc.

If you want this user to have root/sudo privileges, you can use the usermod command to add it to the sudo group. Note that this depends on the Linux distribution you’re using as some use the wheel group instead of sudo. Make sure you really need this as it can create a security gap:

sudo usermod -aG sudo user

The -aG parameters tells usermod to add user user to the sudo group. You can use the usermod command to change other user and group information (as alway, check out its man page).

How to remove a Linux user using the userdel command?

Easy, just set the user you want to remove as the argument to userdel:

sudo userdel tmpp

If you’ll run cat /etc/passwd again, you’ll see the user is no longer there. Note that this doesn’t delete the user folder so you should do that yourself (using rm -rf /home/user after you made sure you copy over any files you might need).

$ sudo ls -la /home/tmpp
drwx------ 5 1001 1001  4096 Mar 18 15:50 .
drwxr-xr-x 4 root root  4096 Mar 18 15:50 ..
-rw-r--r-- 1 1001 1001   220 Mar 18 15:50 .bash_logout
-rw-r--r-- 1 1001 1001  5551 Mar 18 15:50 .bashrc
-rw-r--r-- 1 1001 1001  3526 Mar 18 15:50 .bashrc.original
drwxr-xr-x 6 1001 1001  4096 Mar 18 15:50 .config

How to change the password for a Linux user using passwd?

To set the password of any user, enter the following command:

sudo passwd user

You’ll be prompted to enter a new password. Note that we’re running with sudo privileges so we can affect any user. If you want to change your own password, just omit sudo and the user:

passwd

What does the sudo commmand do?

We’ve used this command a bunch of times already, but what does it actually do? Well, it stand for ‘super user do’ and it lets you run commands as the super user, without actually logging in as root. You basically borrow super user privileges for the command it preppends.

How to switch users using the su command?

What if you want to run commands as other user? This is where the su command comes into play:

$ su postgres
Password: 

If you know the password, enter it and that’s it. But what if you don’t know the user password, but you have sudo rights? Say you want to switch to the ‘postgres` user. You can:

$ sudo su postgres             
[sudo] password for user: 
postgres@kali:/home/user$ 

You can use the sudo command and su to switch to any user as long as you have sudo rights and know the password of the logged in user (in pentesting, you might get access to a user using a reverse shell, but you won’t know its password).

What if you want to log in as the root user?

sudo su -

And that’s it. You’re root (test with whoami).

How to install packages on Linux?

Every once in a while, you’ll need to install software on your Linux box. The two most common package managers are apt and dpkg. apt is the easy way so we’re going to use that. A major advantage of apt is that is installs dependencies for you. With dpkg you have to do it manually and it becomes a real pain.

Before installing anything with apt, it’s recommended to use apt update first. This command updates apt’s repositories (the place where the software is stored and from which apt downloads it) so it knows the latest versions, dependencies and from where to download your software.

sudo apt update

Now, we can install whatever we want (say binwalk in this case, which is a cool forensics tool):

sudo apt install binwalk
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
  base58 cython3 dnsmap ettercap-common ettercap-graphical faraday-agent-dispatcher
...
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  python3-binwalk python3-zombie-imp
The following NEW packages will be installed:
  python3-zombie-imp
The following packages will be upgraded:
  binwalk python3-binwalk
2 upgraded, 1 newly installed, 0 to remove and 1624 not upgraded.

Need to get 116 kB of archives.
After this operation, 58.4 kB of additional disk space will be used.
Do you want to continue? [Y/n] 

I already have binwalk installed so apt will just upgrade it to the latest version if I confirm with Y. It also tells me that I have a bunch of dependencies that were installed automatically, but are no longer in use (probably because the software that caused their installation is no longer present on the system). We can remove these with:

sudo apt autoremove

apt can also fix incomplete installs for you using the --fix-broken argument. This happens if you interupt apt during an installation or have manually installed a package using dpkg.

What are Repositories?

We’ve briefly mentioned earlier that apt updates updates repository information. So where can you see these repositories?

sudo apt edit-sources   
[sudo] password for user: 

Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.basic
  3. /usr/bin/vim.tiny

Choose 1-3 [1]: 

I’ll hit ENTER for 1 and I have this on my Kali machine:

# See https://www.kali.org/docs/general-use/kali-linux-sources-list-repositories/
deb https://http.kali.org/kali kali-rolling main contrib non-free non-free-firmware

Some distributions might not have the repositories defined here, but you’ll usually get a comment redirecting you to the proper place. You can open that URL in your browser and just look at the structure.

Some applications might not be in the official distribution repository. So you might need to add 3rd party repositories to the source file to actually download that software.

After changing the source file, you must run apt update so it refreshes that informationn.

How to see what packages are installed on Linux?

Just use sudo apt list --installed:

$ sudo apt list --installed
Listing... Done
0ad-data-common/kali-rolling,kali-rolling 0.0.26-1 all
0ad-data/kali-rolling,kali-rolling 0.0.26-1 all
...

You’ll probably get a huge list of packages there, but you get the point. You can pipe | those results to something like grep to filter out results.

How to remove a package on Linux?

That’s easy:

sudo apt remove binwalk

How to upgrade your Linux OS?

The following command will update all your applications to the latest versions available in the apt repositories:

apt update
apt upgrade

You can also do full-upgrade instead of upgrade to remove old versions of files that are no longer needed. There’s also a dist-upgrade. They are similar, but not the same. From the man page: full-upgrade removes installed packages when necessary, while dist-upgrade “intelligently handles changing dependencies with new versions of packages”. Kernel upgrades might only happen with dist-upgrade.

How to find files on Linux?

How to use the locate command?

A first method to try is using the locate command. This is a fast command that relies on disk indexing. Indexing is performed using the sudo updatedb. If you create a file and immediately try to use the locate command, it probably won’t find it until you run the indexing command.

Example:

locate mount
/etc/apparmor.d/abstractions/apparmor_api/find_mountpoint
/etc/init.d/cgroupfs-mount
/etc/initramfs-tools/scripts/init-premount
...

Let’s create a new file and try to find it:

$ touch abdef12345
$ locate abdef12345

locate can’t find the file. Let’s try after updatedb:

$ sudo updatedb
$ locate abdef12345
/home/user/abdef12345

Yey, now it does find it!

How to use the find command?

updatedb requires sudo privileges. Another way to look for files and directories is the find command.

$ find / -name abdef12345
...
find: ‘/sys/kernel/debug’: Permission denied
find: ‘/sys/fs/pstore’: Permission denied
find: ‘/sys/fs/bpf’: Permission denied
find: ‘/sys/fs/fuse/connections/35’: Permission denied
/home/user/abdef12345
...

The above command will start in the root filesystem (/) and look for files named abdef12345. Make sure to read the man page as the find command is very versatile (like the exec feature that you can use to run a command for each item it found).

You’ll see a lot of ‘Permission denied’ lines. This is because we don’t have sudo privileges and thus we can’t access those files. This output makes it hard to see our result. To exclude it, we can redirect standard error (stderr) to /dev/null so it will hide the errors from us:

$ find / -name abdef12345 2>/dev/null
/home/user/abdef12345

What are stdin, stdout & stderr?

When a command is executed, there are 3 streams being created: stdin, stdout, and stderr. A stream has a source and a sink. You can redirect or pipe these to the terminal, another command or file.

  • stdin is the input stream and it’s represented by the 0 file descriptor in each process.
  • The output of the command is delivered to the stdout (standard out) stream noted by the 1 file descriptor.
  • Finally, error messages are sent through the stderr (standard error) stream and it’s described by the 2 file descriptor.

So in the 2>/dev/null part of the above command, we’re redirecting stderr noted by the 2 file descriptor to /dev/null which is like redirecting to nothing. You can do the same with the normal output (stdout or 1) like 1>/dev/null.

Or you can redirect a file to the input of a command. Let’s create a text file (input_file) which contains the text ‘please subscribe’. Then we listen on the 9001 port on localhost with the help of netcat:

$ nc -lvp 9001

From another terminal, we launch this command from the folder we created the file:

nc 127.0.0.1 9001 < input_file

This will use netcat to connect to port 9001 on localhost while redirecting the contents of input-file to the stdin of the command (note the <). And we receive the contents of our file in the first terminal:

nc -lvp 9001
listening on [any] 9001 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 60672
please subscribe

Cool, right?

Hacker Tips & Tricks

When doing CTFs or pentesting, there are certain things that will make your life easier. Let’s see a few of them.

Setup an impromptu webserver

You probably have python installed on your Linux machine. You can spin up a basic webserver with a single command:

python3 -m http.server 9090

Use it to transfer files, exfiltrate cookies via XSS or whatever you need. Adjust 9090 with the port you wish to use.

Tips for the cd command

  • cd without arguments will take you to the user home directory. Same as cd ~.
  • cd - will take you back to the previous directory you were.

Searching for text using grep

grep is an extreamly useful tool.

  • You can use it to look for ‘searchtext’ in a file:
cat file | grep searchtext
  • You can search all files in the current directory for the same text using -r (recursive):
grep -r searchtext
  • Use -i to ignore case and -v to exclude the search text.

  • Use -A number or -B number to show number amount of lines after (-A) or before (-B) the matched text.

See in real time what is appended to a file using tail -f:

tail -f /var/log/dpkg.log
...

Proxy application traffic using the “HTTP_PROXY” and “HTTPS_PROXY” environment variables

Use these variables when you want to redirect the traffic of an application to an HTTP proxy like Burp Suite and you can’t set a system wide proxy. You can set a per process variable by preppending it on the command line:

HTTP_PROXY=http://127.0.0.1:8080 nc 127.0.0.1 9001

Re-use commands you entered from the history file

Typing the same command over and over wastes a lot of time. Fortunately, you can look for previously executed commands by hitting CONTROL+R and then entering a few characters:

cat /etc/group        
bck-i-search: etc_

If you have more matches in your history, you can hit CONTROL+R multiple times to go through all of them.

Show network interfaces

Use ifconfig to display current network interfaces:

$ ifconfig  
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.1  netmask 255.255.255.0  broadcast 192.168.200.255
        ether 00:00:00:00:00:00  txqueuelen 1000  (Ethernet)
        RX packets 93074  bytes 139816188 (133.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7481  bytes 507392 (495.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 120  bytes 9698 (9.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 120  bytes 9698 (9.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Display current listening ports:

netstat -l

Shortcuts

  • CONTROL+A - go to the start of a line
  • CONTROL+E - go to the end of a line
  • !! - reissues last command

Create a TTY shell

Sometimes you have a reverse shell, but without a functional TTY terminal.

  • Create one using python:
python -c 'import pty;pty.spawn("/bin/sh")'
  • Perl:
exec "/bin/sh";
perl —e 'exec "/bin/sh";'
  • Ruby:
exec "/bin/sh"
  • From vi editor:
:!bash

Conclusion

And that’s it for this article! Hope you enjoyed reading this article and learned a bit about Linux!

About the Author:

Alex

Application Security Engineer and Red-Teamer. Over 15 years of experience in Application Security, Software Engineering and Offensive Security. OSCE3 & OSCP Certified. CTF nerd.

Back to Blog

Related Posts

View All Posts »