Forebygging av kommando- og argumentinjisering
Sett anførselstegn rundt, valider og send upålitelig inndata som tabeller for å eliminere orddeling og eval-basert injisering.
Forebygging av kommando- og argumentinjisering er en gratis leksjon i DevOps-bootcamp på CoddyKit. Dette er leksjon 1 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i DevOps-bootcamp, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i DevOps-bootcamp inneholder totalt 4 leksjoner.
Hvorfor injeksjonsangrep oppstår i Bash
Bash er et kraftig limspråk — det sender tekst direkte til kjernen, andre programmer og underskall. Denne kraften blir en svakhet i det øyeblikket uklarert inndata når frem til en kommando uten validering eller sitering.
To grunnårsaker ligger bak nesten alle Bash-injeksjoner:
- Orddeling: Usiterte variabler deles ved mellomromstegn (
IFS), slik at én logisk verdi blir til flere skallsymboler. - Glob-ekspansjon: Tegn som
*,?og[utvides av skallet før kommandoen i det hele tatt kjøres.
En angriper som kontrollerer et filnavn, et brukernavn, en URL-parameter eller en miljøvariabel, kan utnytte begge deler til å kjøre vilkårlige kommandoer, lese filer eller eskalere privilegier.
Denne leksjonen viser nøyaktig hvordan disse sårbarhetene oppstår — og, enda viktigere, hvordan De eliminerer dem med korrekt sitering, validering av inndata og argumentoverføring basert på tabeller.
Orddeling: Den usynlige trusselen
Når Bash ser en usitert variabel, deler det verdien ved alle tegn som er oppført i $IFS (standard: mellomrom, tabulator, linjeskift). Det som ser ut som ett argument, blir til flere.
Kjør skriptet nedenfor og se hvordan et filnavn med et mellomrom blir til to separate argumenter til 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):"
lsSiter alltid: Den første regelen for defensiv Bash
Det enkleste og mest effektive forsvaret mot orddeling er å alltid sette doble anførselstegn rundt variabelutvidelser.
"$var"— utvides til nøyaktig ett symbol og bevarer mellomrom, tabulatorer og linjeskift.'literal'— enkle anførselstegn: ingen utvidelser i det hele tatt, nyttig for faste strenger.- Bruk aldri
$varusitert med mindre De uttrykkelig trenger orddeling og glob-ekspansjon.
Skriptet nedenfor viser den sikre versjonen av det forrige eksempelet.
#!/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):'
lsGlob-injeksjon: Når * blir et våpen
Usiterte variabler utsettes også for banenavnsutvidelse (glob-ekspansjon). Hvis brukerbestemte inndata inneholder * eller ?, utvider Bash dem mot filsystemet før kommandoen kjøres.
En klassisk angrepsvektor er et nettskjema som setter PATTERN=*, mens skriptet kjører cp $PATTERN /tmp/leak/ — og dermed kopierer alle filer i gjeldende mappe.
Løsningen er den samme: sett doble anførselstegn rundt variabelen. En sitert "$PATTERN" sendes bokstavelig; skallet utfører ingen glob-ekspansjon på den.
#!/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_dstArgumentinjeksjon via usiterte posisjonsparametere
Skript som mottar argumenter fra den som kaller dem, er attraktive mål for injeksjon. Hver posisjonsparameter ($1, $2, ...) må siteres overalt der den brukes.
Et spesielt farlig mønster er å sende $@ eller $* usitert til en annen kommando:
"$@"— utvider hver posisjonsparameter til et separat, individuelt sitert ord. Bruk alltid denne formen.$@eller$*usitert — utsettes for orddeling og glob-ekspansjon."$*"— slår sammen alle parametere til ett ord (sjelden det De ønsker).
#!/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"Kommandoinjeksjon via eval og uvaliderte inndata
eval tolker argumentet på nytt som skallkode. Uklarerte data som når frem til eval, kan kjøre vilkårlige kommandoer.
Vanlige farlige mønstre:
eval "$user_input"eval echo \$$var(indirekte variabeloppslag)- Å sende brukerdata gjennom
bash -c "$input"
Regel: Send aldri uklarerte inndata til eval eller bash -c. Bruk sikre Bash-alternativer:
- Indirekte utvidelse:
${!varname}i stedet foreval echo \$$varname - Assosiative tabeller for dynamiske oppslag av nøkkel og verdi
- Funksjoner i stedet for genererte kommandostrenger
#!/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
fiValidering av inndata: Tillatelseslister fremfor blokkeringslister
Det er sårbart å avvise kjente farlige tegn (en blokkeringsliste) — angripere finner kodinger eller tegn De har glemt. Bruk i stedet en tillatelsesliste: godta bare tegn De vet er sikre.
Strategier for tillatelseslister i Bash:
- Regex-samsvar:
[[ "$input" =~ ^[A-Za-z0-9_-]+$ ]] - Mønstergjenkjenning:
case "$input" in [A-Za-z0-9]*) ... ;; esac - Enum-sjekk: sammenlign med et fast sett av gyldige verdier
Valider ved grensen — så snart inndata kommer inn i skriptet — før den berører noen kommando.
#!/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' # REJECTEDBruk av tabeller for sikker argumentoverføring
Når De må bygge en kommando dynamisk — for eksempel ved å legge til flagg betinget eller gå gjennom inndata i en løkke — bør De bruke en Bash-tabell i stedet for å sette sammen strenger.
Strengsammenslåing fjerner all struktur; en Bash-tabell bevarer hvert argument som et separat element uten ny tolking av skallet.
- Deklarer:
args=() - Legg til:
args+=(--flag "$value") - Kjør:
command "${args[@]}"
"${args[@]}" utvider hvert element som et separat, individuelt sitert ord — nøyaktig som "$@".
#!/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[@]}"Separatoren --: Beskyttelse mot flagginjeksjon
Selv et korrekt sitert argument kan mistolkes som et alternativflagg hvis det begynner med -. Tenk på rm "$file" der file='-rf .': Siteringen beskytter mot orddeling, men rm tolker fortsatt -rf som flagg.
POSIX-konvensjonen -- signaliserer slutt på alternativer til de fleste GNU-/BSD-verktøy. Alt etter -- behandles som et posisjonsargument, aldri som et flagg.
#!/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_targetRensing av inndata for SQL og eksterne verktøy
Når Bash-skript kaller databaseklienter (psql, mysql), curl med brukerleverte URL-er eller lignende verktøy, gjelder to ekstra lag:
- Parametriserte spørringer: Sett aldri brukerdata direkte inn i SQL-strenger. Send verdier via
-vipsqleller--data-urlencodeicurl. - Skill data fra kode: Bruk
printfmed en bokstavelig formatstreng; la aldri brukerdata være formatstrengen.
Eksempelet nedenfor spør PostgreSQL på en sikker måte og holder den brukerleverte verdien helt ute av SQL-teksten.
#!/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"Sjekkliste for sikring: Sett alt sammen
Et Bash-skript med sikkerhet på produksjonsnivå kombinerer alle teknikkene fra denne leksjonen i et konsekvent, lagdelt forsvar. Her er en minimal, men komplett herdet mal:
set -euo pipefail— avslutt ved feil, behandle udefinerte variabler som feil, og viderefør feil i rør.- Valider ved innlesing — bruk en tillatelsesliste for alle eksterne inndata før de berører noen kommando.
- Siter alt —
"$var","$@","${array[@]}"— ingen unntak med mindre De trenger splitting. - Bruk tabeller til dynamisk bygging av kommandoer.
- Sett
--foran argumenter når De sender brukerleverte filnavn eller strenger. - Bruk aldri
evalmed uklarerte data; foretrekk${!var}for indirekte oppslag. - Begrens tillatelser — kjør skript med minimum nødvendige privilegier, og unngå
sudoi skript som mottar brukerdata.
#!/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[@]}"Kunnskapstest: Sitering og forebygging av injeksjon
Test forståelsen Deres av de viktigste begrepene i denne leksjonen.
Oppsummering av leksjonen: Forebygging av kommando- og argumentinjeksjon
De har gått gjennom et komplett defensivt verktøysett for sikker håndtering av inndata i Bash:
- Orddeling og glob-ekspansjon er de grunnleggende mekanismene som gjør usikre variabler til injeksjonsvektorer.
- Sett doble anførselstegn rundt alle variabler (
"$var","$@","${arr[@]}") for å undertrykke begge truslene. - Bruk
"$@"— aldri$@eller$*usitert — når De videresender argumenter. - Sett
--foran brukerleverte filnavn for å hindre flagginjeksjon. - Bruk en tillatelsesliste for alle eksterne inndata med en regex-vakt (
[[ $v =~ ^pattern$ ]]) før de når noen kommando. - Bygg dynamiske kommandoer med tabeller (
cmd+=()→"${cmd[@]}"), aldri med strengsammenslåing. - Fjern
evalogbash -c "$input"; bruk${!varname}for sikker indirekte utvidelse. - Start alltid skript med
set -euo pipefailogIFS=$'\n\t'som et herdet grunnlag.
Disse praksisene, brukt konsekvent fra første linje i hvert skript, reduserer Bash-angrepsflaten for injeksjonssårbarheter til nær null.
Lær deg DevOps-bootcamp med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 142
- Leksjoner
- 568
Ofte stilte spørsmål
Er leksjonen «Forebygging av kommando- og argumentinjisering» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien DevOps-bootcamp, inkludert «Forebygging av kommando- og argumentinjisering», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i DevOps-bootcamp inneholder totalt 4 leksjoner.
Hva lærer jeg i «Forebygging av kommando- og argumentinjisering»?
Sett anførselstegn rundt, valider og send upålitelig inndata som tabeller for å eliminere orddeling og eval-basert injisering. Du øver på DevOps-bootcamp med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med DevOps-bootcamp?
Ingen tidligere erfaring er nødvendig. DevOps-bootcamp på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 1 av 4.
Hvor lang tid tar leksjonen «Forebygging av kommando- og argumentinjisering»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne DevOps-bootcamp-leksjonen?
Ja. Alle DevOps-bootcamp-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Forebygging av kommando- og argumentinjisering
- Sikker håndtering av hemmeligheter og ryddige miljøer
- Kjøring med minste privilegium og sudo-disiplin
- Statisk analyse og revisjon med ShellCheck