Cron job'lar gözetimsiz ve düzenli komut çalıştırır; bu yüzden hem operasyonun omurgası hem de kalıcılık (persistence) ve yetki yükseltme hedefidir. Yanlış izinlenmiş tek script, crontab'a gömülü şifre veya denetlenmeyen bir satır tüm sunucuyu riske atar. Bu rehber en az yetki, erişim kontrolü, credential hijyeni, wildcard tuzağı ve düzenli denetimi somut komutlarla anlatır.
Tehditler yalnızca "dış saldırgan" değildir: paylaşımlı hosting'de komşu kullanıcı, ele geçirilmiş web uygulaması veya yazılabilir yedek dizini de yeterlidir. İzin hatalarını çözerken chmod 777 kullanmak güvenliği bilinçli olarak bozar. Ortam kaynaklı sessiz hatalar için çalışmıyor rehberine, izleme için log rehberine bakın.
Tehdit Haritası
| Tehdit | Risk | Etki | Önlem |
|---|---|---|---|
| Yazılabilir script root cron'da | Kritik | Tam yetki yükseltme | 1, 3 |
| Crontab'da açık şifre | Kritik | DB / API sızıntısı | 4 |
Wildcard injection (tar *) | Yüksek | Keyfi komut | 7 |
| Göreli yol / PATH oyunu | Yüksek | Sahte binary | 5 |
| Cron ile kalıcılık | Yüksek | T1053.003 | 12 |
| Korumasız web endpoint | Orta | Yetkisiz tetik / DoS | 10 |
En Az Yetki, cron.allow ve Dosya İzinleri
Kolaylık için her görevi root crontab'ına koymak en yaygın hatadır. Root'un çalıştırdığı script'in yazılabilir olduğu her nokta saldırı yüzeyidir.
# KÖTÜ
sudo crontab -e
0 2 * * * /opt/scripts/yedek.sh
# İYİ: kısıtlı servis kullanıcısı
sudo useradd -r -s /usr/sbin/nologin yedek_user
sudo -u yedek_user crontab -e
0 2 * * * /opt/scripts/yedek.sh
/opt/scripts/yedek.sh grup-yazılabilirse (ör. 664), gruptaki kullanıcı script'e komut ekler ve gece 02:00'de root (veya yedek kullanıcısı) olarak çalıştırır./etc/cron.allow varsa yalnızca listedekiler crontab kullanabilir; allow varken deny genelde yok sayılır. Üretimde beyaz liste tercih edin:
echo "deploy" | sudo tee /etc/cron.allow
echo "yedek_user" | sudo tee -a /etc/cron.allow
sudo chmod 644 /etc/cron.allow
sudo chown root:root /etc/cron.allow
chmod 700 /opt/scripts/yedek.sh
chown yedek_user:yedek_user /opt/scripts/yedek.sh
chmod 755 /opt/scripts
chown root:root /opt/scripts
chmod 600 /etc/crontab
ls -la /etc/cron.d/
Parola, PATH ve Girdi Doğrulama
Crontab satırındaki şifre ps, yedekler ve loglar üzerinden sızabilir.
# KÖTÜ
0 2 * * * mysqldump -u root -pSuperGizli123 uygulama_db > /yedek/db.sql
# İYİ: ~/.my.cnf (chmod 600)
# [client]
# user=backup_user
# password=...
0 2 * * * /usr/bin/mysqldump uygulama_db | /bin/gzip > /yedek/db-$(date +\%Y\%m\%d).sql.gz
API anahtarlarını script içine gömmeyin; 600 izinli .env veya secret manager kullanın. Yedekleme akışı için veritabanı yedekleme rehberine bakın.
# KÖTÜ: göreli komut
0 3 * * * backup.sh
# İYİ
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 3 * * * /opt/scripts/backup.sh
# Script içinde: /usr/bin/rsync -a /veri/ /yedek/
Dış girdiyi (dosya adı, API alanı) asla doğrudan shell'e birleştirmeyin:
# KÖTÜ
for f in $(cat /kuyruk/dosyalar.txt); do
convert $f /cikti/$f.png
done
# İYİ
while IFS= read -r f; do
[[ "$f" =~ ^[a-zA-Z0-9._-]+$ ]] || continue
/usr/bin/convert -- "$f" "/cikti/${f}.png"
done < /kuyruk/dosyalar.txt
Script başında set -euo pipefail hatalı durumda sessiz devamı keser.
Wildcard Injection, flock ve Loglama
Joker (*) shell tarafından dosya adlarına açılır; adlar komut seçeneğine dönüşebilir. Klasik örnek: root cron'da tar czf ... *.
# KÖTÜ
0 4 * * * cd /veri && tar czf /yedek/veri.tgz *
# Saldırgan /veri içinde oluşturur:
# --checkpoint=1
# --checkpoint-action=exec=sh saldiri.sh
# İYİ
0 4 * * * /usr/bin/tar czf /yedek/veri.tgz -C / veri
MAILTO=ops@sirket.com
0 2 * * * /opt/scripts/yedek.sh >> /var/log/yedek.log 2>&1
*/5 * * * * /usr/bin/flock -n /run/yedek_user/senkron.lock /opt/scripts/senkron.sh
/tmp ve tahmin edilebilir isimde tutmayın; symlink yarışına açık olur. Kullanıcıya özel /run/user/ veya root sahipli dizin tercih edin. Loglarda şifre/token yazmayın; rotasyon için log temizleme rehberine bakın.Web Endpoint, MAC ve Düzenli Denetim
URL ile tetiklenen görevler (ör. wp-cron.php, özel PHP uç noktası) korunmazsa herkes tarafından çağrılabilir.
- Token'ı özel header veya HTTP Basic Auth ile doğrulayın; kaynağa sabit kodlamayın, ortam değişkeninden okuyun.
- Mümkünse çağıran IP'leri kısıtlayın ve rate limit uygulayın.
- Hata yanıtlarında stack trace / yol sızdırmayın.
<?php
declare(strict_types=1);
$beklenen = getenv('CRON_SECRET') ?: '';
$token = $_SERVER['HTTP_X_CRON_TOKEN'] ?? '';
if ($beklenen === '' || !hash_equals($beklenen, $token)) {
http_response_code(403);
exit('forbidden');
}
// iş mantığı
http_response_code(200);
echo 'ok';
SELinux (RHEL ailesi) ve AppArmor (Ubuntu) ele geçirilmiş script'in erişimini sınırlar; kapatmak yerine politika düzeltin. Dağıtım notları: CentOS cron, Ubuntu cron. Sertifika yenileme betiklerini root cron'a koyarken özel anahtar dosyası izinlerini (genelde 600) ve post-hook reload sırasını cron ile SSL yenileme rehberindeki güvenlik adımlarıyla hizalayın; yenileme başarısız olsa bile özel anahtarın dünya okunabilir kalmamasına dikkat edin.
MITRE ATT&CK T1053.003: saldırganlar crontab ile kalıcılık kurar. Periyodik denetim:
for u in $(cut -f1 -d: /etc/passwd); do
echo "== $u =="; crontab -u "$u" -l 2>/dev/null
done
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ /var/spool/cron/
Alarm: tanımadığınız satırlar, curl ... | bash, wget -O- ... | sh, base64 -d | sh, /tmp veya /dev/shm altından çalışan script'ler.
Gerçek Senaryolar
Senaryo 1: Yazılabilir yedek script ile root
/etc/crontab içinde root olarak /home/app/backup.sh çağrılır; dizin uygulama kullanıcısına yazılabilirdir. Web zafiyetiyle script değiştirilir; bir sonraki cron tick'inde root shell komutları çalışır. Çözüm: script'i root sahipli /opt/scripts altına taşımak (700), görevi ayrı kullanıcıya almak.
Senaryo 2: Açık cron URL ile kaynak tüketimi
https://site.example/cron/heavy-report token'sız bırakılır; botlar dakikada onlarca istek atar, CPU ve DB kilitlenir. Çözüm: header token + rate limit; dış tetikleme için aşağıdaki HTTP servisi.
Sık Hatalar ve Çözümleri
| Hata / durum | Neden | Çözüm |
|---|---|---|
| Root cron + 777 script | Kolay izin "çözümü" | 700/750 + ayrı kullanıcı |
ps'te görünen şifre | -pSifre argümanı | ~/.my.cnf veya env dosyası 600 |
| Aniden eklenen crontab satırı | Kalıcılık | Allow listesi + düzenli crontab -l denetimi |
| tar sonrası şüpheli process | Wildcard injection | -C ile dizin; joker yok |
| Endpoint 200 herkese | Token yok | Header doğrulama + 403 |
| Çakışan iki yedek | Kilitsiz uzun iş | flock -n güvenli path'te |
Güvenlik Kontrol Listesi
- Görevler root yerine kısıtlı servis kullanıcılarıyla çalışıyor
/etc/cron.allowile beyaz liste uygulanıyor- Script ve dizin zinciri yalnızca sahibi tarafından yazılabilir (700/755)
- Şifreler crontab'da değil; 600 config veya secret manager
- Crontab'da güvenli PATH; komutlar mutlak yolla
- Dış girdiler doğrulanıyor; değişkenler çift tırnaklı
- Jokerli
tar *kaldırıldı - Çıktı loglanıyor; başarısızlıkta bildirim var
- Uzun işler
flockile tek kopya - Web endpoint token (+ mümkünse IP / rate limit)
- SELinux/AppArmor kapatılmadan yapılandırıldı
- Crontab ve cron dizinleri düzenli denetleniyor
cronjob.com.tr ile Tokenlı HTTP Alternatifi
Sunucuya SSH ile crontab yazmadan, yalnızca halka açık HTTPS uç noktanızı dışarıdan zamanlamak istiyorsanız uç noktayı yukarıdaki gibi token ile koruyup cronjob.com.tr panelinden çağırın. Servis ücretsizdir; kayıtta kredi kartı istenmez. En kısa aralık 1 dakikadır; hazır aralık veya 5 alanlı cron ifadesi, iş bazında saat dilimi (varsayılan Europe/Istanbul) desteklenir. GET/POST/PUT/PATCH/DELETE/HEAD/OPTIONS, özel header, gövde ve HTTP Basic Auth kullanılabilir. Başarı HTTP 200–399'dur; en fazla 5 yönlendirme izlenir; TLS doğrulanır. Localhost ve özel ağ (10.x, 192.168.x, 169.254.x vb.) hedeflerine istek gönderilmez. Timeout aralığa göre (1 dk → 55 sn, 5 dk+ / cron ifade → 290 sn). Ardışık hata eşiği (varsayılan 3, 1–20) aşılınca e-posta; düzelince kesinti süresiyle bildirim. Loglar: durum, süre, hata, yanıtın ilk ~64 KB'ı, 7 gün.
Sıkça Sorulan Sorular (SSS)
Cron job'ları root olarak çalıştırmak neden tehlikelidir?
Root crontab'ındaki bir script ele geçirilirse saldırgan tüm sisteme erişir. Yazılabilir script, yazılabilir dizin veya PATH manipülasyonu doğrudan root yetkisine çıkar. Her görevi yalnızca ihtiyacı kadar yetkili bir servis kullanıcısıyla çalıştırın.
Crontab'a şifre yazmak güvenli midir?
Hayır. Komut satırı argümanları ps çıktısında görünebilir; crontab yedekleri ve loglar da sızdırabilir. Şifreleri 600 izinli ~/.my.cnf veya .env dosyasında tutun ya da secret manager kullanın.
Sunucuma sızıldığını cron'dan nasıl anlarım?
Saldırganlar kalıcılık için crontab'a gizli satır ekler (MITRE ATT&CK T1053.003). crontab -l, /etc/cron.d/, /etc/cron.daily/ ve /var/spool/cron/ dizinlerini denetleyin; tanımadığınız satırlar, base64|sh veya curl|bash kalıpları alarm sebebidir.
Web cron endpoint'ini nasıl korurum?
Sabit URL'yi herkese açık bırakmayın. Uzun rastgele token'ı özel HTTP header veya Basic Auth ile doğrulayın; mümkünse IP kısıtı ve rate limit uygulayın. Hata yanıtlarında stack trace sızdırmayın.
tar * wildcard saldırısı nasıl engellenir?
Yazılabilir dizinde * ile tar çalıştırmayın; dosya adları --checkpoint gibi seçeneklere dönüşebilir. Dizini -C ile açıkça verin veya -- ile seçenek işlemeyi sonlandırın; root cron'da joker kullanmayın.
Cron Job'larınızı Güvenle Yönetin
cronjob.com.tr ile SSH vermeden, header/Basic Auth korumalı URL işleri zamanlayın. Ücretsiz; kayıtta kart istenmez.
Ücretsiz Başla →