Mencegah Suntikan Perintah dan Argumen
Petik, sahkan dan hantar input tidak dipercayai melalui tatasusunan untuk menghapuskan pemisahan perkataan dan suntikan berasaskan eval
Mencegah Suntikan Perintah dan Argumen ialah pelajaran Penguasaan Baris Perintah Linux & Penskripan Bash percuma di CoddyKit. Ini ialah pelajaran 1 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 Serangan Suntikan Berlaku dalam Bash
Bash ialah bahasa penghubung yang berkuasa — ia menghantar teks terus kepada kernel, program lain dan subcangkerang. Kuasa ini menjadi liabiliti sebaik sahaja masukan tidak dipercayai sampai kepada perintah tanpa pengesahan atau pemetikkan.
Dua punca utama mendorong hampir semua suntikan Bash:
- Pemisahan perkataan: Pemboleh ubah yang tidak dipetik dipisahkan pada ruang kosong (
IFS), lalu menukar satu nilai logik menjadi banyak token cangkerang. - Pengembangan glob: Aksara seperti
*,?dan[dikembangkan oleh cangkerang sebelum perintah dijalankan.
Penyerang yang mengawal nama fail, nama pengguna, parameter URL atau pemboleh ubah persekitaran boleh mengeksploitasi kedua-duanya untuk menjalankan perintah sewenang-wenangnya, membaca fail atau meningkatkan keistimewaan.
Pelajaran ini menunjukkan dengan tepat bagaimana kerentanan ini muncul dan — yang lebih penting — cara menghapuskannya dengan pemetikkan yang betul, pengesahan masukan dan penghantaran argumen berasaskan tatasusunan.
Pemisahan Perkataan: Ancaman Senyap
Apabila Bash menemui pemboleh ubah yang tidak dipetik, ia memisahkan nilainya pada mana-mana aksara yang disenaraikan dalam $IFS (lalai: ruang, tab, baris baharu). Perkara yang kelihatan seperti satu argumen menjadi banyak argumen.
Jalankan skrip di bawah dan perhatikan bagaimana nama fail yang mengandungi ruang menjadi dua argumen berasingan kepada rm.
#!/usr/bin/env bash
# Dangerous: unquoted variable
FILE='important file.txt'
# Create the file so the demo is self-contained
touch "$FILE"
echo "Files before:"
ls
# BUG: rm sees TWO arguments: 'important' and 'file.txt'
# If 'important' does not exist, rm prints an error but continues.
rm $FILE # <-- unquoted, word-split happens here
echo "Files after (unquoted rm):"
lsSentiasa Gunakan Pemetikkan: Peraturan Pertama Bash Defensif
Pertahanan paling mudah dan berkesan terhadap pemisahan perkataan ialah sentiasa menggunakan tanda petik berganda pada pengembangan pemboleh ubah.
"$var"— dikembangkan menjadi tepat satu token, sambil mengekalkan ruang, tab dan baris baharu.'literal'— tanda petik tunggal: tiada pengembangan langsung, berguna untuk rentetan tetap.- Jangan gunakan
$vartanpa petik melainkan anda memang memerlukan pemisahan perkataan dan pengembangan glob.
Skrip di bawah menunjukkan versi selamat bagi contoh sebelumnya.
#!/usr/bin/env bash
set -euo pipefail
FILE='important file.txt'
touch "$FILE"
echo 'Files before:'
ls
# SAFE: double-quotes keep the filename as one token
rm "$FILE"
echo 'Files after (quoted rm):'
lsSuntikan Glob: Apabila * Menjadi Senjata
Pemboleh ubah yang tidak dipetik juga tertakluk kepada pengembangan nama laluan (glob). Jika masukan yang dikawal pengguna mengandungi * atau ?, Bash mengembangkannya berdasarkan sistem fail sebelum perintah dijalankan.
Vektor serangan klasik: borang web yang menetapkan PATTERN=* dan skrip menjalankan cp $PATTERN /tmp/leak/ — menyalin setiap fail dalam direktori semasa.
Penyelesaiannya sama: gunakan tanda petik berganda pada pemboleh ubah. "$PATTERN" yang dipetik dihantar secara literal; cangkerang tidak melakukan pengembangan glob terhadapnya.
#!/usr/bin/env bash
set -euo pipefail
# Simulate attacker-supplied input
PATTERN='*'
mkdir -p /tmp/safe_demo_src /tmp/safe_demo_dst
touch /tmp/safe_demo_src/secret1.txt /tmp/safe_demo_src/secret2.txt
cd /tmp/safe_demo_src
# UNSAFE: glob expands, copies every file
# cp $PATTERN /tmp/safe_demo_dst/
# SAFE: pattern is treated as a literal filename
cp "$PATTERN" /tmp/safe_demo_dst/ 2>&1 || echo 'No file named literally "*" — attack neutralised'
rm -rf /tmp/safe_demo_src /tmp/safe_demo_dstSuntikan Argumen melalui Parameter Kedudukan yang Tidak Dipetik
Skrip yang menerima argumen daripada pemanggil ialah sasaran utama suntikan. Setiap parameter kedudukan ($1, $2, ...) mestilah dipetik di mana-mana sahaja ia digunakan.
Pola yang amat berbahaya ialah menghantar $@ atau $* tanpa petik kepada perintah lain:
"$@"— mengembangkan setiap parameter kedudukan sebagai perkataan berasingan dan dipetik secara individu. Sentiasa gunakan bentuk ini.$@atau$*tanpa petik — tertakluk kepada pemisahan perkataan dan pengembangan glob."$*"— menggabungkan semua parameter menjadi satu perkataan (jarang sekali itulah yang anda mahukan).
#!/usr/bin/env bash
set -euo pipefail
# Safe wrapper: forward all arguments quoted
grep_wrapper() {
local pattern="$1"
shift
# "$@" preserves each file argument as one token
grep -rn "$pattern" "$@"
}
# Usage: ./script 'error msg' /var/log/syslog '/path with spaces/app.log'
echo 'Searching current script for "safe":'
grep_wrapper 'safe' "$0"Suntikan Perintah melalui eval dan Masukan yang Tidak Disahkan
eval menghuraikan semula argumennya sebagai kod cangkerang. Apa-apa data yang tidak dipercayai dan sampai kepada eval boleh menjalankan perintah sewenang-wenangnya.
Pola berbahaya yang biasa:
eval "$user_input"eval echo \$$var(carian pemboleh ubah tidak langsung)- Menghantar data pengguna melalui
bash -c "$input"
Peraturan: jangan sesekali menghantar masukan tidak dipercayai kepada eval atau bash -c. Gunakan alternatif Bash yang selamat:
- Pengembangan tidak langsung:
${!varname}dan bukannyaeval echo \$$varname - Tatasusunan bersekutu untuk carian nilai-kunci dinamik
- Fungsi dan bukannya rentetan perintah yang dijana
#!/usr/bin/env bash
set -euo pipefail
# Simulated attacker-supplied variable name
VARNAME='PATH; echo INJECTED'
# UNSAFE: eval lets attacker run 'echo INJECTED'
# eval "echo \$$VARNAME"
# SAFE: indirect expansion only resolves valid variable names
# First validate that VARNAME is a legal identifier
if [[ "$VARNAME" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then
echo "Value: ${!VARNAME}"
else
echo "ERROR: invalid variable name: '$VARNAME'" >&2
exit 1
fiPengesahan Masukan: Senarai Benarkan Mengatasi Senarai Tolak
Menolak aksara yang diketahui buruk (sebuah senarai tolak) adalah rapuh — penyerang boleh mencari pengekodan atau aksara yang anda terlupa. Sebaliknya, gunakan senarai benarkan: terima hanya aksara yang anda tahu selamat.
Strategi senarai benarkan dalam Bash:
- Padanan ungkapan nalar:
[[ "$input" =~ ^[A-Za-z0-9_-]+$ ]] - Padanan pola:
case "$input" in [A-Za-z0-9]*) ... ;; esac - Semakan enum: bandingkan dengan set nilai sah yang tetap
Sahkan pada sempadan — sebaik sahaja masukan memasuki skrip — sebelum masukan menyentuh mana-mana perintah.
#!/usr/bin/env bash
set -euo pipefail
validate_username() {
local name="$1"
# Allowlist: only lowercase letters, digits, underscore, hyphen; 1-32 chars
if [[ ! "$name" =~ ^[a-z0-9_-]{1,32}$ ]]; then
echo "ERROR: invalid username '${name}'" >&2
return 1
fi
echo "Username accepted: $name"
}
validate_username 'alice' # OK
validate_username 'bob_smith-2' # OK
validate_username 'root; rm -rf /' # REJECTED
validate_username '../etc/passwd' # REJECTEDMenggunakan Tatasusunan untuk Menghantar Argumen dengan Selamat
Apabila anda perlu membina perintah secara dinamik — menambah bendera secara bersyarat atau menggelung melalui masukan — gunakan tatasusunan Bash dan bukannya menggabungkan rentetan.
Penggabungan rentetan meruntuhkan semua struktur; tatasusunan Bash mengekalkan setiap argumen sebagai unsur diskret tanpa penghuraian semula oleh cangkerang.
- Isytihar:
args=() - Tambah:
args+=(--flag "$value") - Laksanakan:
command "${args[@]}"
"${args[@]}" mengembangkan setiap unsur sebagai perkataan berasingan yang dipetik secara individu — tepat seperti "$@".
#!/usr/bin/env bash
set -euo pipefail
# Build a find command safely with an array
BASEDIR='/tmp'
USER_PATTERN='*.log' # could come from user input (validate first!)
MAX_DAYS=7
cmd=(find "$BASEDIR" -type f -name "$USER_PATTERN" -mtime "+${MAX_DAYS}")
# Optionally add -delete only when requested
DELETE=false
if [[ "$DELETE" == 'true' ]]; then
cmd+=(-delete)
fi
echo "Running: ${cmd[*]}"
"${cmd[@]}"Pemisah --: Melindungi daripada Suntikan Bendera
Argumen yang dipetik dengan betul pun boleh disalah tafsir sebagai bendera pilihan jika bermula dengan -. Pertimbangkan rm "$file" apabila file='-rf .': pemetikkan melindungi daripada pemisahan perkataan, tetapi rm masih mentafsir -rf sebagai bendera.
Konvensyen POSIX -- menandakan akhir pilihan kepada kebanyakan utiliti GNU/BSD. Segala-galanya selepas -- dianggap sebagai argumen kedudukan, bukan bendera.
#!/usr/bin/env bash
set -euo pipefail
# Simulate a dangerous filename supplied by the user
FILENAME='-rf /tmp/safe_demo_target'
mkdir -p /tmp/safe_demo_target
touch /tmp/safe_demo_target/keep_me.txt
echo 'Files before:'
ls /tmp/safe_demo_target/
# UNSAFE (flag injection — do NOT uncomment in real systems):
# rm "$FILENAME"
# SAFE: -- ends option processing; filename is treated literally
rm -- "$FILENAME" 2>&1 || echo "No such file (attack neutralised): $FILENAME"
echo 'Files after:'
ls /tmp/safe_demo_target/
rm -rf /tmp/safe_demo_targetMenyanitasi Masukan untuk SQL dan Alat Luaran
Apabila skrip Bash memanggil CLI pangkalan data (psql, mysql), curl dengan URL yang dibekalkan pengguna atau alat yang serupa, dua lapisan tambahan terpakai:
- Kuiri berparameter: Jangan sesekali menyisipkan data pengguna ke dalam rentetan SQL. Hantar nilai melalui
-vdalampsqlatau--data-urlencodedalamcurl. - Asingkan data daripada kod: Gunakan
printfdengan rentetan format literal; jangan sesekali membenarkan masukan pengguna menjadi rentetan format.
Contoh di bawah menyoal PostgreSQL dengan selamat sambil memastikan nilai yang dibekalkan pengguna tidak masuk langsung ke dalam teks SQL.
#!/usr/bin/env bash
set -euo pipefail
# Validate first: only allow alphanumeric usernames
USERNAME="${1:-alice}"
if [[ ! "$USERNAME" =~ ^[a-z0-9_]{1,32}$ ]]; then
echo 'ERROR: invalid username' >&2
exit 1
fi
# UNSAFE:
# psql -c "SELECT * FROM users WHERE name = '$USERNAME';"
# SAFE: pass value as a psql variable, never inside the SQL text
# psql -v username="$USERNAME" -c 'SELECT * FROM users WHERE name = :username;'
# Demonstrate the principle with printf (safe format string usage)
printf 'Query would use username: %s\n' "$USERNAME"Senarai Semak Pengerasan: Menggabungkan Kesemuanya
Skrip Bash selamat bertaraf produksi menggabungkan setiap teknik daripada pelajaran ini menjadi pertahanan berlapis yang konsisten. Berikut ialah templat yang diperkukuh, minimum tetapi lengkap:
set -euo pipefail— keluar apabila berlaku ralat, anggap pemboleh ubah yang tidak ditetapkan sebagai ralat, dan sebarkan kegagalan paip.- Sahkan semasa masuk — gunakan senarai benarkan untuk setiap masukan luaran sebelum masukan menyentuh mana-mana perintah.
- Petik semuanya —
"$var","$@","${array[@]}"— tiada pengecualian kecuali anda memerlukan pemisahan. - Gunakan tatasusunan untuk pembinaan perintah dinamik.
- Awali argumen dengan
--apabila menghantar nama fail atau rentetan yang dibekalkan pengguna. - Jangan sesekali gunakan
evaldengan data yang tidak dipercayai; utamakan${!var}untuk carian tidak langsung. - Hadkan keizinan — jalankan skrip dengan keistimewaan minimum yang diperlukan; elakkan
sudodalam skrip yang menerima masukan pengguna.
#!/usr/bin/env bash
# Hardened template — safe argument injection prevention
set -euo pipefail
IFS=$'\n\t'
#--- 1. Validate inputs at the boundary ---
SEARCH_DIR="${1:-}"
PATTERN="${2:-}"
[[ -z "$SEARCH_DIR" || -z "$PATTERN" ]] && { echo 'Usage: script <dir> <pattern>' >&2; exit 1; }
[[ ! "$SEARCH_DIR" =~ ^[A-Za-z0-9/_.-]+$ ]] && { echo 'ERROR: unsafe directory path' >&2; exit 1; }
[[ ! "$PATTERN" =~ ^[A-Za-z0-9._-]+$ ]] && { echo 'ERROR: unsafe pattern' >&2; exit 1; }
#--- 2. Build command with an array ---
cmd=(find -- "$SEARCH_DIR" -type f -name "$PATTERN")
#--- 3. Execute — no string interpolation, no eval ---
echo "Executing: ${cmd[*]}"
"${cmd[@]}"Semakan Pengetahuan: Pemetikkan dan Pencegahan Suntikan
Uji pemahaman anda tentang konsep utama dalam pelajaran ini.
Ringkasan Pelajaran: Mencegah Suntikan Perintah dan Argumen
Anda telah mempelajari set alat pertahanan lengkap untuk mengendalikan masukan Bash dengan selamat:
- Pemisahan perkataan dan pengembangan glob ialah mekanisme asas yang menukar pemboleh ubah tidak selamat menjadi vektor suntikan.
- Gunakan tanda petik berganda pada setiap pemboleh ubah (
"$var","$@","${arr[@]}") untuk menyekat kedua-dua ancaman. - Gunakan
"$@"— jangan sesekali gunakan$@atau$*tanpa petik — apabila meneruskan argumen. - Awali nama fail yang dibekalkan pengguna dengan
--untuk mencegah suntikan bendera. - Gunakan senarai benarkan untuk semua masukan luaran dengan pengawal ungkapan nalar (
[[ $v =~ ^pattern$ ]]) sebelum masukan sampai kepada mana-mana perintah. - Bina perintah dinamik dengan tatasusunan (
cmd+=()→"${cmd[@]}"), bukan dengan penggabungan rentetan. - Hapuskan
evaldanbash -c "$input"; gunakan${!varname}untuk pengembangan tidak langsung yang selamat. - Sentiasa mulakan skrip dengan
set -euo pipefaildanIFS=$'\n\t'sebagai garis dasar yang diperkukuh.
Amalan ini, jika diterapkan secara konsisten dari baris pertama setiap skrip, mengurangkan permukaan serangan Bash kepada hampir sifar bagi kerentanan kelas suntikan.
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 “Mencegah Suntikan Perintah dan Argumen” percuma?
Ya — teks penuh “Mencegah Suntikan Perintah dan Argumen” 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 & Penskripan Bash, tingkat taraf kepada CoddyKit PRO. Kursus Penguasaan Baris Perintah Linux & Penskripan Bash merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Mencegah Suntikan Perintah dan Argumen”?
Petik, sahkan dan hantar input tidak dipercayai melalui tatasusunan untuk menghapuskan pemisahan perkataan dan suntikan berasaskan eval Anda berlatih Penguasaan Baris Perintah Linux & 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 & Penskripan Bash?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Penguasaan Baris Perintah Linux & 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 1 daripada 4.
Berapa lamakah pelajaran “Mencegah Suntikan Perintah dan Argumen” 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 & Penskripan Bash ini?
Ya. Setiap pelajaran Penguasaan Baris Perintah Linux & 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
- Mencegah Suntikan Perintah dan Argumen
- Pengendalian Rahsia yang Selamat dan Kebersihan Persekitaran
- Pelaksanaan dengan Keistimewaan Minimum dan Disiplin sudo
- Analisis Statik dan Pengauditan dengan ShellCheck