En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini
Ayrıcalıkları düşürün, sudo kurallarının kapsamını sıkı tutun ve riskli işlemlerden önce etkin UID değerini doğrulayın.
En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini, CoddyKit'te ücretsiz bir Linux Command Line & Bash Scripting Mastery dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Linux Command Line & Bash Scripting Mastery öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Linux Command Line & Bash Scripting Mastery kursu toplamda 4 dersten oluşur.
Kabuk Betiklerinde En Az Ayrıcalık Neden Önemlidir
Otomasyondaki güvenlik ihlallerinin çoğu karmaşık açıklardan değil, betiklerin gerektiğinden daha fazla ayrıcalıkla çalışmasından kaynaklanır. Yalnızca bir günlük dosyasını döndürmesi gereken root olarak çalışan bir cron işi, gerçekleşmesi beklenen bir kazadır.
En az ayrıcalık ilkesi şunu belirtir: her işlem, işini yapmak için gereken izinleri ve yalnızca bunları kullanarak çalışmalıdır. Bash betiklerinde bu şu anlama gelir:
- Mümkün olduğunda ayrıcalıksız bir kullanıcı olarak çalıştırmak
- root yetkisine yalnızca bunu gerektiren belirli komutlar için yükselmek
- Yükseltilmiş işlem tamamlanır tamamlanmaz ayrıcalıkları bırakmak
- Kimlik bilgilerini kapsamlarının ötesinde asla saklamamak veya devralmamak
Bu derste somut teknikler ele alınır: sudo kapsamlandırması, su ile ayrıcalık bırakma, UID doğrulama korumaları ve sudoers güçlendirmesi; böylece üretim betikleri için disiplinli bir ayrıcalık modeli oluşturulur.
Riskli İşlemlerden Önce Etkin UID'yi Denetleme
Gerçekten root gerektiren herhangi bir kod bloğundan önce betiğiniz, beklenen etkin UID ile çalıştığını doğrulamalıdır. Varsaymayın; her zaman doğrulayın.
$EUID, geçerli işlemin etkin kullanıcı kimliğini tutan özel bir Bash değişkenidir. Root'un EUID değeri her zaman 0'dır. Betiğin başında veya ayrıcalıklı bir bloğun çevresinde bunu denetlemek, yanlış kimlikle yanlışlıkla çalıştırılmayı önler.
Şu koruma kalıbını kullanın:
#!/usr/bin/env bash
set -euo pipefail
# Guard: this script must NOT run as root.
if [[ "$EUID" -eq 0 ]]; then
echo "ERROR: Do not run this script as root. Use a normal user account." >&2
exit 1
fi
echo "Running as UID $EUID — proceeding safely."Yalnızca Gerektiğinde Root Olduğunu Doğrulama
Bazı betiklerin gerçekten root yetkisine ihtiyacı vardır. Bu durumda koruma tersine çevrilir: betiğin ayrıcalıklı bir sistem çağrısına ulaşıp çalışma sırasında kafa karıştırıcı bir izin hatası üretmesini beklemek yerine, root yoksa erkenden başarısız olun.
Erken çıkışı yararlı bir kullanım mesajıyla birleştirmek, betiklerin kendi belgelerini içermesini sağlar:
#!/usr/bin/env bash
set -euo pipefail
require_root() {
if [[ "$EUID" -ne 0 ]]; then
echo "ERROR: $(basename "$0") must be run as root." >&2
echo " Try: sudo $(basename "$0") $*" >&2
exit 1
fi
}
require_root "$@"
echo "Root confirmed (EUID=0). Starting privileged work..."sudo'yu Tek Komutla Sınırlandırma
En yaygın hata, bir betiğin en üstüne sudo koyup ardından her şeyi root olarak çalıştırmaktır. Bunun yerine sudo'yu yalnızca ona ihtiyaç duyan tam komuta uygulayın; diğer her şey normal kullanıcınız olarak çalışır.
Bu, saldırının etkisini sınırlar: Bir saldırgan betiğinize kod enjekte ederse root izinleriyle yalnızca önünde sudo bulunan bölümleri çalıştırabilir.
Aşağıdaki iki kalıbı karşılaştırın. İkincisi çok daha güvenlidir:
#!/usr/bin/env bash
set -euo pipefail
# BAD: escalate early, do everything as root (avoid this)
# sudo bash -c '
# cp config.conf /etc/app/config.conf
# chown app:app /etc/app/config.conf
# systemctl restart app
# '
# GOOD: escalate only for the commands that require it
LOCAL_CONF="./config.conf"
DEST="/etc/app/config.conf"
# Unprivileged: validate the config before touching anything as root
if ! grep -q '^[[:space:]]*\[main\]' "$LOCAL_CONF"; then
echo "ERROR: config.conf is missing [main] section" >&2
exit 1
fi
# Privileged: only these three commands run under sudo
sudo cp "$LOCAL_CONF" "$DEST"
sudo chown app:app "$DEST"
sudo systemctl restart app
echo "Config deployed and service restarted."Sıkı sudoers Kuralları Yazma
Bir betikte sudo somecommand çağrısı, yalnızca sudoers dosyası tam olarak o komuta ve başka hiçbir şeye izin verecek şekilde yapılandırılmışsa güvenli çalışır. Hizmet hesapları için ALL=(ALL) NOPASSWD: ALL gibi kurallardan kaçının.
Bunun yerine, visudo için güvenli sözdizimini kullanarak kuralları belirli bağımsız değişkenlere sahip belirli komutlarla sınırlandırın. Bir sudoers kuralındaki temel alanlar:
- Kullanıcı — sudo'yu kimin çağırabileceği
- Makine — hangi makinede (taşınabilirlik için
ALLkullanın) - RunAs — hangi kimliğin üstlenileceği (neredeyse her zaman
root) - Komut — isteğe bağlı olarak gerçek bağımsız değişkenlerle birlikte tam mutlak yol
Bir dağıtım hizmet hesabı (deployer) için sıkı kural örnekleri:
# /etc/sudoers.d/deployer (edit with: sudo visudo -f /etc/sudoers.d/deployer)
#
# Allow 'deployer' to restart exactly one service — nothing else
deployer ALL=(root) NOPASSWD: /usr/bin/systemctl restart app
# Allow copying a config file to a fixed destination only
deployer ALL=(root) NOPASSWD: /usr/bin/cp /home/deployer/staging/config.conf /etc/app/config.conf
# Allow chown of that specific file only
deployer ALL=(root) NOPASSWD: /usr/bin/chown app\:app /etc/app/config.conf
# NEVER do this — gives full root shell:
# deployer ALL=(ALL) NOPASSWD: ALLsu ve runuser ile Ayrıcalıkları Bırakma
Bir betik root olarak başladığında (örneğin root olarak çalışan bir sistem başlatıcısı veya cron tarafından başlatıldığında), ancak işlerin çoğunun ayrıcalıksız bir kullanıcı olarak yapılması gerektiğinde, tüm betiği root olarak çalıştırmak yerine ayrıcalıkları açıkça bırakın.
Bunun için iki araç vardır:
su -s /bin/bash -c 'command' username— username olarak bir kabuk başlatır ve komutu çalıştırırrunuser -u username -- command args— root sahipli betiklerde geçiş yapmak için Linux'ta tercih edilir;su'dan daha temizdir
Aşağıdaki kalıp, gerçek uygulama mantığı için app kullanıcısına geçen root sahipli bir dağıtım sarmalayıcısını gösterir:
#!/usr/bin/env bash
# This script is called by systemd as root during pre-deployment
set -euo pipefail
APP_USER="app"
DEPLOY_DIR="/opt/myapp"
# Step 1: privileged — fix ownership of deploy directory
chown -R "${APP_USER}:${APP_USER}" "$DEPLOY_DIR"
# Step 2: drop to app user for the actual migration/startup logic
# runuser is available on most modern Linux systems
runuser -u "$APP_USER" -- bash -c "
cd $DEPLOY_DIR
./bin/migrate.sh
./bin/start.sh
"
echo "Deploy complete. Privileged wrapper exiting."Tek Bir Komutu Başka Bir Kullanıcı Olarak Çalıştırmak için sudo -u Kullanma
Her zaman tam bir kabuk oturumuna geçmeniz gerekmez. sudo -u username command, tek bir komutu belirtilen kullanıcı olarak çalıştırır ve ardından çağıran kimliğe döner. Bu, bir hizmet hesabına etkileşimli erişim izni vermeden o hesaba ait dosyalara dokunmak için kullanışlıdır.
Bunu, tam olarak o kullanıcı ve komut birleşimine izin veren bir sudoers kuralıyla birlikte kullanın:
#!/usr/bin/env bash
set -euo pipefail
# Scenario: deploy script runs as 'deployer'; DB migrations must run as 'postgres'
# sudoers entry needed:
# deployer ALL=(postgres) NOPASSWD: /opt/app/bin/run_migrations.sh
DB_MIGRATION_SCRIPT="/opt/app/bin/run_migrations.sh"
if [[ ! -x "$DB_MIGRATION_SCRIPT" ]]; then
echo "ERROR: migration script not found or not executable: $DB_MIGRATION_SCRIPT" >&2
exit 1
fi
echo "Running DB migrations as postgres user..."
sudo -u postgres "$DB_MIGRATION_SCRIPT"
echo "Migrations done. Returning to deployer context (EUID=$EUID)."Ortam Değişkenleri Yoluyla Ayrıcalık Yükseltmeyi Önleme
İnce bir saldırı yüzeyi: sudo oturumu tarafından devralınan ortam değişkenleri. Varsayılan olarak sudo ortamı sıfırlar; ancak yanlış yapılandırılmış env_keep veya env_reset geçersiz kılmaları, saldırganın denetimindeki LD_PRELOAD, PATH veya PYTHONPATH gibi değişkenleri ayrıcalıklı komutlara aktarabilir.
En iyi uygulamalar:
sudoaltında çalışan betiklerde her zaman mutlak yollar kullanın —$PATH'e asla güvenmeyin- Yalnızca açıkça ihtiyaç duyduğunuz değişkenleri aktarın:
sudo env VAR=value /path/to/cmd - sudoers içinde
env_keep += PATHveyaenv_keep += LD_*kullanmaktan kaçının - Çağıran ortamı tamamen denetlediğinizden ve ona güvendiğinizden emin olmadıkça
sudo -Ekullanmayın
#!/usr/bin/env bash
set -euo pipefail
# BAD: relies on $PATH — attacker who controls PATH can hijack 'cp'
# sudo cp config.conf /etc/app/
# GOOD: absolute paths for every command called under elevated context
SUDO_BIN="/usr/bin/sudo"
CP_BIN="/usr/bin/cp"
CHOWN_BIN="/usr/bin/chown"
SYSTEMCTL_BIN="/usr/bin/systemctl"
"$SUDO_BIN" "$CP_BIN" ./config.conf /etc/app/config.conf
"$SUDO_BIN" "$CHOWN_BIN" app:app /etc/app/config.conf
"$SUDO_BIN" "$SYSTEMCTL_BIN" restart app
echo "Deployed with hardened absolute-path invocations."Komut Bağımsız Değişkeni Doğrulamasıyla sudo'yu Sıkılaştırma
Bir sudoers kuralı belirli bir betiğe izin verse bile, kural bunları da sınırlandırmıyorsa betiğe rastgele bağımsız değişkenler aktarılabilir. Yaygın bir tuzak:
deployer ALL=(root) NOPASSWD: /opt/scripts/manage.shBu, sudo /opt/scripts/manage.sh restart komutuna izin verir — ancak sudo /opt/scripts/manage.sh --arbitrary-flag komutuna da izin verir. manage.sh bağımsız değişkenleri ayrıcalıklı alt komutlara sorgulamadan aktarıyorsa bir sorun yaşarsınız.
Derinlemesine savunun: bağımsız değişkenleri sudoers'ta olduğu gibi ayrıcalıklı betiğin içinde de doğrulayın:
#!/usr/bin/env bash
# /opt/scripts/manage.sh — called via sudo; must validate its own args
set -euo pipefail
# Allowlist of valid actions
declare -A ALLOWED_ACTIONS=(
[restart]=1
[status]=1
[reload]=1
)
ACTION="${1:-}"
if [[ -z "$ACTION" ]]; then
echo "Usage: $(basename "$0") <restart|status|reload>" >&2
exit 1
fi
if [[ -z "${ALLOWED_ACTIONS[$ACTION]:-}" ]]; then
echo "ERROR: Unknown action '${ACTION}'. Allowed: ${!ALLOWED_ACTIONS[*]}" >&2
exit 2
fi
/usr/bin/systemctl "$ACTION" app
echo "Action '$ACTION' executed successfully."Temizleme Tuzağıyla Geçici Yetki Yükseltme
Bir betiğin ayrıcalıklı bir dosyaya, kimlik bilgisine veya kaynağa kısa süreliğine sahip olması gerektiğinde, hata ya da sinyal durumunda bile temizleme işleminin gerçekleşmesini sağlamak için Bash'in trap özelliğini kullanın. Bu, örneğin betik çökerse geride kalan geçici bir setuid ikili dosyasının veya root sahipliğindeki bir soketin neden olabileceği yetki sızıntısını önler.
Aşağıdaki kalıp root olarak geçici bir dosya oluşturur, dosyayı kullanır ve ardından siler; bu işlem EXIT üzerindeki bir trap tarafından garanti edilir:
#!/usr/bin/env bash
set -euo pipefail
# Must run as root for this demo
if [[ "$EUID" -ne 0 ]]; then
echo "Run as root" >&2; exit 1
fi
TMP_SECRET=""
cleanup() {
local exit_code=$?
if [[ -n "$TMP_SECRET" && -f "$TMP_SECRET" ]]; then
# Overwrite before deletion to reduce forensic recovery risk
shred -u "$TMP_SECRET" 2>/dev/null || rm -f "$TMP_SECRET"
echo "[cleanup] Removed privileged temp file." >&2
fi
exit "$exit_code"
}
trap cleanup EXIT INT TERM
# Create a root-owned temp file for a short-lived secret
TMP_SECRET="$(mktemp /tmp/deploy_secret.XXXXXXXX)"
chmod 600 "$TMP_SECRET"
# Simulate fetching a secret into the temp file
echo "super-secret-token" > "$TMP_SECRET"
# Use the secret (e.g., pass to a sub-command via file descriptor)
/usr/bin/some-privileged-tool --key-file "$TMP_SECRET"
echo "Privileged operation complete."Ayrıcalıklı İşlemleri Denetleme ve Günlüğe Kaydetme
Her yetki yükseltme olayı bağlamıyla birlikte günlüğe kaydedildiğinde en az ayrıcalık ilkesini uygulamak daha kolaydır: işlemi kim, ne zaman ve neden çalıştırdı? İki katmanı birleştirin:
- sudo'nun kendisi —
/var/log/auth.log(Debian/Ubuntu) veya/var/log/secure(RHEL), her sudo çağrısını otomatik olarak kaydeder - Betiğe ait denetim günlüğü — amacın sistem günlüğüyle birlikte kaydedilmesi için her ayrıcalıklı işlevin başlangıcında yapılandırılmış bir kayıt yazın
Basit bir yapılandırılmış günlük işlevi kullanmak, denetim izlerini tutarlı ve grep ile aranabilir durumda tutar:
#!/usr/bin/env bash
set -euo pipefail
AUDIT_LOG="/var/log/app_deploy_audit.log"
log_privileged_action() {
local action="$1"
local reason="${2:-unspecified}"
local ts
ts="$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
printf '{"ts":"%s","user":"%s","euid":%d,"action":"%s","reason":"%s"}\n' \
"$ts" "${SUDO_USER:-$USER}" "$EUID" "$action" "$reason" \
| sudo tee -a "$AUDIT_LOG" > /dev/null
}
# Each privileged step is logged before execution
log_privileged_action "cp_config" "deploy release v2.4.1"
sudo /usr/bin/cp ./config.conf /etc/app/config.conf
log_privileged_action "chown_config" "ensure app user owns config"
sudo /usr/bin/chown app:app /etc/app/config.conf
log_privileged_action "restart_service" "activate new config"
sudo /usr/bin/systemctl restart app
echo "Deployment complete. Audit entries written to $AUDIT_LOG"Bilgi Yoklaması: sudo Kapsamı
Bash betiklerinde en az ayrıcalıkla yürütme konusundaki anlayışınızı sınayın.
Özet: En Az Ayrıcalıkla Yürütme ve sudo Disiplini
Bu derste, Bash betiklerini her adımda gereken en düşük ayrıcalıkla çalıştırma tekniklerinde ustalaştınız. Temel ilkelerin kısa bir özeti aşağıdadır:
$EUIDile koruma ekleyin — betik, root olmayı reddetmek veya root olmayı gerektirmek gibi durumlarda yanlış kimlikle çalışıyorsa hemen başarısız olunsudokapsamını tek tek komutlarla sınırlayın — hiçbir zaman betiğin tamamının yetkisini yükseltmeyin;sudoyu yalnızca gerçekten ihtiyaç duyan satırlara uygulayın- Sıkı sudoers kuralları yazın — tam mutlak yolları ve değişmez bağımsız değişkenleri belirtin; joker karakterlerden ve
ALL'dan kaçının runuserveyasudo -uile ayrıcalıkları bırakın — root olarak başlayan bir betiğin ayrıcalıksız bir kullanıcıya devretmesi gerektiğinde, her şeyi root olarak çalıştırmak yerine doğru aracı kullanın- Mutlak yollar kullanın — ayrıcalıklı kod içinde hiçbir zaman
$PATH'e güvenmeyin; ele geçirmeyi önlemek için ikili dosya yollarını doğrudan yazın - Ayrıcalıklı betiklerin içindeki bağımsız değişkenleri doğrulayın — sudoers kuralları ilk savunma hattıdır, tek savunma hattı değildir; izin verilenler listelerini kullanın
- Yakalama ve temizleme yapın — hata durumunda bile geçici ayrıcalıklı kaynakların yok edilmesini garanti etmek için
trap cleanup EXITkullanın - Her yetki yükseltmesini günlüğe kaydedin — yapılandırılmış denetim kayıtları ile yerleşik sudo syslog'unu birleştirerek her ayrıcalıklı işlem için izlenebilirlik sağlayın
Tutarlı biçimde uygulandığında bu uygulamalar, otomasyonunuzun saldırı yüzeyini her zaman root olmaktan yalnızca kanıtlanabilir biçimde gerekli olduğunda root olmaya indirger; bu, güçlendirilmiş ve üretim kalitesinde Bash'in ayırt edici özelliğidir.
Sıkça Sorulan Sorular
“En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini” dersi ücretsiz mi?
Evet — “En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Linux Command Line & Bash Scripting Mastery kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Linux Command Line & Bash Scripting Mastery kursu toplamda 4 dersten oluşur.
“En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini” dersinde ne öğreneceğim?
Ayrıcalıkları düşürün, sudo kurallarının kapsamını sıkı tutun ve riskli işlemlerden önce etkin UID değerini doğrulayın. Linux Command Line & Bash Scripting Mastery ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Linux Command Line & Bash Scripting Mastery öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Linux Command Line & Bash Scripting Mastery, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Linux Command Line & Bash Scripting Mastery dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Linux Command Line & Bash Scripting Mastery dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Komut ve Bağımsız Değişken Enjeksiyonunu Önleme
- Güvenli Gizli Bilgi Yönetimi ve Ortam Hijyeni
- En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini
- ShellCheck ile Statik Analiz ve Denetim