· Alex · security · 30 min read
Linux for Hackers 101
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 forprint 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 forchange directory
and it’s used to change the working directory. You can use it to navigate the filesystem. Runningcd ..
will move you up one folder. And you can just as well usecd ../..
to go up 2 directories and so on. You can repeatedly usecd ..
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
simplylists
what’s in the current directory. Lots of Linux beginners usecd
before using thels
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 usels /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 asmore
orless
:
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 thejobs
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 the1
file descriptor. - Finally, error messages are sent through the
stderr
(standard error) stream and it’s described by the2
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 ascd ~
.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 shownumber
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:
Application Security Engineer and Red-Teamer. Over 15 years of experience in Application Security, Software Engineering and Offensive Security. OSCE3 & OSCP Certified. CTF nerd.