Penguasaan Baris Perintah Linux & Penskripan Bash · Pelajaran

Pelaksanaan dengan Keistimewaan Minimum dan Disiplin sudo

Kurangkan keistimewaan, hadkan skop peraturan sudo dengan ketat dan sahkan UID berkesan sebelum operasi berisiko

Pelajaran 3 daripada 413 langkah

Pelaksanaan dengan Keistimewaan Minimum dan Disiplin sudo ialah pelajaran Penguasaan Baris Perintah Linux & Penskripan Bash percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Penguasaan Baris Perintah Linux & Penskripan Bash, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Penguasaan Baris Perintah Linux & Penskripan Bash merangkumi sejumlah 4 pelajaran.

Mengapa Keistimewaan Minimum Penting dalam Skrip Shell

Kebanyakan pelanggaran keselamatan dalam automasi berlaku bukan kerana eksploitasi eksotik, tetapi kerana skrip berjalan dengan lebih banyak keistimewaan daripada yang diperlukan. Tugas cron yang berjalan sebagai root sedangkan hanya perlu memutar fail log ialah kemalangan yang sedang menunggu untuk berlaku.

Prinsip keistimewaan minimum menyatakan: setiap proses harus beroperasi hanya menggunakan kebenaran yang diperlukan untuk menjalankan tugasnya — dan tidak lebih. Dalam penskripan Bash, ini bermaksud:

  • Berjalan sebagai pengguna tanpa keistimewaan apabila boleh
  • Menaik taraf kepada root hanya untuk perintah tertentu yang memerlukannya
  • Menurunkan keistimewaan sebaik sahaja kerja berkeistimewaan selesai
  • Jangan sekali-kali menyimpan atau mewarisi kelayakan di luar skopnya

Pelajaran ini menerangkan teknik konkrit: penskopan sudo, penurunan su, pengawal pengesahan UID dan pengukuhan sudoers — untuk membina model keistimewaan yang berdisiplin bagi skrip produksi.

Menyemak UID Berkesan Sebelum Operasi Berisiko

Sebelum sebarang blok kod yang benar-benar memerlukan root, skrip Anda harus mengesahkan bahawa ia berjalan dengan UID berkesan yang dijangka. Jangan menganggap; sentiasa tegaskan.

$EUID ialah pemboleh ubah khas Bash yang menyimpan ID pengguna berkesan bagi proses semasa. Root sentiasa mempunyai EUID 0. Menyemaknya di bahagian atas skrip — atau di sekitar blok berkeistimewaan — mencegah pelaksanaan tidak sengaja dengan identiti yang salah.

Gunakan pola pengawal ini:

#!/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."

Menegaskan Root Hanya Apabila Diperlukan

Sesetengah skrip sememangnya memerlukan root. Dalam keadaan itu, pengawal diterbalikkan: gagal lebih awal jika root tiada, bukannya membiarkan skrip mencapai panggilan sistem berkeistimewaan lalu menghasilkan ralat kebenaran yang mengelirukan di tengah-tengah pelaksanaan.

Menggabungkan keluar awal dengan mesej penggunaan yang membantu menjadikan skrip boleh menerangkan dirinya sendiri:

#!/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..."

Mengehadkan sudo kepada Perintah Tunggal

Kesilapan yang paling biasa ialah meletakkan sudo di bahagian atas skrip dan kemudian menjalankan semuanya sebagai root. Sebaliknya, gunakan sudo hanya pada perintah tepat yang memerlukannya — perkara lain berjalan sebagai pengguna biasa Anda.

Ini mengehadkan kesan serangan: jika penyerang menyuntik kod ke dalam skrip Anda, mereka hanya boleh melaksanakan bahagian yang tidak mempunyai sudo di hadapannya dengan kebenaran root.

Bandingkan dua pola di bawah. Pola kedua jauh lebih selamat:

#!/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."

Menulis Peraturan sudoers yang Ketat

Memanggil sudo somecommand dalam skrip hanya selamat jika fail sudoers dikonfigurasikan untuk membenarkan tepat perintah tersebut — dan tiada yang lain. Elakkan peraturan seperti ALL=(ALL) NOPASSWD: ALL untuk akaun perkhidmatan.

Sebaliknya, hadkan peraturan kepada perintah khusus dengan argumen khusus menggunakan sintaks yang selamat untuk visudo. Medan utama dalam peraturan sudoers:

  • Pengguna — siapa yang boleh menggunakan sudo
  • Hos — pada mesin mana (gunakan ALL untuk kemudahalihan)
  • RunAs — identiti yang hendak diambil (hampir selalu root)
  • Perintah — laluan mutlak penuh, secara pilihan dengan argumen literal

Contoh peraturan ketat untuk akaun perkhidmatan penerapan (deployer):

# /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: ALL

Menurunkan Keistimewaan dengan su dan runuser

Apabila skrip bermula sebagai root (contohnya, dilancarkan oleh init sistem atau cron yang berjalan sebagai root) tetapi kebanyakan kerja sepatutnya berlaku sebagai pengguna tanpa keistimewaan, turunkan keistimewaan secara jelas dan bukannya menjalankan keseluruhan skrip sebagai root.

Dua alat untuk tujuan ini:

  • su -s /bin/bash -c 'command' username — melancarkan shell sebagai username dan menjalankan perintah
  • runuser -u username -- command args — lebih disukai pada Linux untuk pertukaran dalam skrip milik root; lebih bersih daripada su

Pola di bawah menunjukkan pembungkus penerapan milik root yang menurunkan keistimewaan kepada pengguna app untuk logik aplikasi sebenar:

#!/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."

Menggunakan sudo -u untuk Menjalankan Satu Perintah sebagai Pengguna Lain

Anda tidak semestinya perlu beralih kepada sesi shell penuh. sudo -u username command menjalankan satu perintah sebagai pengguna yang ditentukan, kemudian kembali kepada identiti pemanggil. Ini berguna untuk mengubah suai fail milik akaun perkhidmatan tanpa memberikan akaun tersebut sebarang akses interaktif.

Gabungkan ini dengan peraturan sudoers yang membenarkan tepat gabungan pengguna/perintah tersebut:

#!/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)."

Mengelakkan Peningkatan Keistimewaan melalui Pemboleh Ubah Persekitaran

Satu permukaan serangan yang halus ialah pemboleh ubah persekitaran yang diwarisi oleh sesi sudo. Secara lalai, sudo menetapkan semula persekitaran, tetapi penggantian env_keep atau env_reset yang tersalah konfigurasi boleh menghantar pemboleh ubah yang dikawal penyerang seperti LD_PRELOAD, PATH atau PYTHONPATH ke dalam perintah berkeistimewaan.

Amalan terbaik:

  • Sentiasa gunakan laluan mutlak dalam skrip yang berjalan di bawah sudo — jangan sekali-kali bergantung pada $PATH
  • Hantar hanya pemboleh ubah yang diperlukan secara jelas: sudo env VAR=value /path/to/cmd
  • Dalam sudoers, elakkan env_keep += PATH atau env_keep += LD_*
  • Gunakan sudo -E hanya apabila Anda mengawal sepenuhnya dan mempercayai persekitaran pemanggil
#!/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."

Mengunci sudo dengan Pengesahan Argumen Perintah

Walaupun peraturan sudoers membenarkan skrip tertentu, argumen sewenang-wenangnya masih boleh dihantar kepada skrip itu melainkan peraturan tersebut turut mengehadkannya. Perangkap yang biasa berlaku:

deployer ALL=(root) NOPASSWD: /opt/scripts/manage.sh

Ini membenarkan sudo /opt/scripts/manage.sh restart — tetapi juga sudo /opt/scripts/manage.sh --arbitrary-flag. Jika manage.sh menghantar argumen secara membuta tuli kepada subperintah berkeistimewaan, Anda menghadapi masalah.

Gunakan pertahanan berlapis: sahkan argumen di dalam skrip berkeistimewaan serta dalam sudoers:

#!/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."

Peningkatan Keistimewaan Sementara dengan Perangkap Pembersihan

Apabila skrip perlu memegang fail, kelayakan atau sumber berkeistimewaan buat sementara waktu, gunakan trap Bash untuk memastikan pembersihan berlaku walaupun berlaku ralat atau isyarat. Ini menghalang kebocoran keistimewaan — contohnya perduaan setuid sementara atau soket milik root yang tertinggal jika skrip ranap.

Corak di bawah mencipta fail sementara sebagai root, menggunakannya, kemudian memadamkannya — dijamin oleh perangkap pada EXIT:

#!/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."

Mengaudit dan Merekod Tindakan Berkeistimewaan

Keistimewaan minimum lebih mudah dikuatkuasakan apabila setiap peristiwa peningkatan direkodkan berserta konteks: siapa menjalankan perkara apa, bila dan mengapa. Gabungkan dua lapisan:

  1. sudo itu sendiri — /var/log/auth.log (Debian/Ubuntu) atau /var/log/secure (RHEL) merekodkan setiap penggunaan sudo secara automatik
  2. log audit peringkat skrip — tulis entri berstruktur pada permulaan setiap fungsi berkeistimewaan supaya niat direkodkan bersama log sistem

Menggunakan fungsi log berstruktur yang ringkas memastikan jejak audit konsisten dan mudah dicari dengan grep:

#!/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"

Semakan Pengetahuan: Penskopan sudo

Uji pemahaman anda tentang pelaksanaan dengan keistimewaan minimum dalam skrip Bash.

Imbas Kembali: Pelaksanaan dengan Keistimewaan Minimum dan Disiplin sudo

Dalam pelajaran ini, anda telah menguasai teknik untuk menjalankan skrip Bash dengan keistimewaan minimum yang diperlukan pada setiap langkah. Berikut ialah ringkasan padat prinsip utama:

  • Lindungi dengan $EUID — hentikan dengan segera jika skrip berjalan menggunakan identiti yang salah, sama ada dengan menolak root atau mewajibkannya
  • Hadkan skop sudo kepada arahan individu — jangan sekali-kali meningkatkan keistimewaan seluruh skrip; gunakan sudo hanya pada baris yang benar-benar memerlukannya
  • Tulis peraturan sudoers yang ketat — nyatakan laluan mutlak penuh dan argumen literal; elakkan aksara bebas dan ALL
  • Lepaskan keistimewaan dengan runuser atau sudo -u — apabila skrip yang dimulakan sebagai root perlu menyerahkan tugas kepada pengguna tanpa keistimewaan, gunakan alat yang betul dan bukannya menjalankan semuanya sebagai root
  • Gunakan laluan mutlak — jangan sekali-kali bergantung pada $PATH dalam kod berkeistimewaan; tetapkan laluan perduaan secara terus untuk menghalang rampasan
  • Sahkan argumen dalam skrip berkeistimewaan — peraturan sudoers ialah barisan pertahanan pertama, bukan satu-satunya; gunakan senarai benarkan
  • Gunakan perangkap dan lakukan pembersihan — gunakan trap cleanup EXIT untuk menjamin sumber berkeistimewaan sementara dimusnahkan walaupun berlaku ralat
  • Rekodkan setiap peningkatan — entri audit berstruktur yang digabungkan dengan syslog sudo terbina dalam memberikan kebolehkesanan bagi setiap tindakan berkeistimewaan

Jika diamalkan secara konsisten, amalan ini mengurangkan permukaan serangan automasi anda daripada root-sepanjang-masa kepada root-hanya-apabila-benar-benar-diperlukan — ciri utama Bash yang diperkukuh untuk persekitaran produksi.

Percuma untuk bermula

Pelajari Bash dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
22
Pelajaran
88

Soalan Lazim

Adakah pelajaran “Pelaksanaan dengan Keistimewaan Minimum dan Disiplin sudo” percuma?

Ya — teks penuh “Pelaksanaan dengan Keistimewaan Minimum dan Disiplin sudo” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Penguasaan Baris Perintah Linux &amp; Penskripan Bash, tingkat taraf kepada CoddyKit PRO. Kursus Penguasaan Baris Perintah Linux &amp; Penskripan Bash merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Pelaksanaan dengan Keistimewaan Minimum dan Disiplin sudo”?

Kurangkan keistimewaan, hadkan skop peraturan sudo dengan ketat dan sahkan UID berkesan sebelum operasi berisiko Anda berlatih Penguasaan Baris Perintah Linux &amp; Penskripan Bash menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Penguasaan Baris Perintah Linux &amp; Penskripan Bash?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Penguasaan Baris Perintah Linux &amp; Penskripan Bash di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Pelaksanaan dengan Keistimewaan Minimum dan Disiplin sudo” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Penguasaan Baris Perintah Linux &amp; Penskripan Bash ini?

Ya. Setiap pelajaran Penguasaan Baris Perintah Linux &amp; Penskripan Bash menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Mencegah Suntikan Perintah dan Argumen
  2. Pengendalian Rahsia yang Selamat dan Kebersihan Persekitaran
  3. Pelaksanaan dengan Keistimewaan Minimum dan Disiplin sudo
  4. Analisis Statik dan Pengauditan dengan ShellCheck
← Kembali ke Penguasaan Baris Perintah Linux &amp; Penskripan Bash