Förhindra kommando- och argumentinjektion
Använd citattecken, validering och arrayer för att skicka opålitlig indata och eliminera orddelning och eval-baserad injektion.
Förhindra kommando- och argumentinjektion är en gratis lektion i Bemästra Linux-kommandoraden och Bash-skriptning på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Bemästra Linux-kommandoraden och Bash-skriptning, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Bemästra Linux-kommandoraden och Bash-skriptning innehåller totalt 4 lektioner.
Varför injektionsattacker uppstår i Bash
Bash är ett kraftfullt limspråk — det skickar text direkt till kärnan, andra program och underskal.
Denna kraft blir en risk så snart otillförlitlig indata når ett kommando utan validering eller citering.
Två grundorsaker ligger bakom nästan alla Bash-injektioner:
- Orddelning: Okvoterade variabler delas upp vid blanktecken (
IFS), så att ett logiskt värde blir flera skalargument. - Glob-expansion: Tecken som
*,?och[expanderas av skalet innan kommandot ens körs.
En angripare som styr ett filnamn, användarnamn, en URL-parameter eller en miljövariabel kan utnyttja båda för att köra godtyckliga kommandon, läsa filer eller höja sina behörigheter.
I den här lektionen visas exakt hur dessa sårbarheter uppstår och — ännu viktigare — hur Ni eliminerar dem med korrekt citering, indatavalidering och argumentöverföring med arrayer.
Orddelning: det tysta hotet
När Bash ser en okvoterad variabel delar det upp dess värde vid alla tecken som anges i $IFS (standard: blanksteg, tabb, nyrad). Det som ser ut som ett argument blir flera.
Kör skriptet nedan och se hur ett filnamn med ett blanksteg blir två separata argument till 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):"
lsCitera alltid: den första regeln för defensiv Bash
Det enklaste och mest effektiva skyddet mot orddelning är att alltid använda dubbla citattecken kring variabelexpansioner.
"$var"— expanderas till exakt ett token och bevarar blanksteg, tabbar och nyrader.'literal'— enkla citattecken: inga expansioner alls, användbart för fasta strängar.- Använd aldrig
$varokvoterat om Ni inte uttryckligen behöver orddelning och glob-expansion.
Skriptet nedan visar den säkra versionen av det föregående exemplet.
#!/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-injektion: när * blir ett vapen
Okvoterade variabler påverkas även av sökvägsexpansion (glob-expansion). Om användarstyrd indata innehåller * eller ? expanderar Bash den mot filsystemet innan kommandot körs.
En klassisk attackvektor är ett webbformulär som anger PATTERN=* och ett skript som kör cp $PATTERN /tmp/leak/ — då kopieras alla filer i den aktuella katalogen.
Lösningen är densamma: använd dubbla citattecken kring variabeln. En citerad "$PATTERN" skickas ordagrant; skalet utför ingen glob-expansion 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_dstArgumentinjektion via okvoterade positionsparametrar
Skript som tar emot argument från den som anropar dem är särskilt utsatta för injektioner. Varje positionsparameter ($1, $2, ...) måste citeras överallt där den används.
Ett särskilt farligt mönster är att skicka $@ eller $* okvoterat till ett annat kommando:
"$@"— expanderar varje positionsparameter till ett separat, individuellt citerat ord. Använd alltid denna form.$@eller$*okvoterat — påverkas av orddelning och glob-expansion."$*"— sammanfogar alla parametrar till ett ord (vilket sällan är vad Ni vill).
#!/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"Kommandoinjektion via eval och ovaliderad indata
eval tolkar om sitt argument som skalkod. Otillförlitliga data som når eval kan köra godtyckliga kommandon.
Vanliga farliga mönster:
eval "$user_input"eval echo \$$var(indirekt variabeluppslagning)- Att skicka användardata via
bash -c "$input"
Regel: skicka aldrig otillförlitlig indata till eval eller bash -c. Använd säkra Bash-alternativ:
- Indirekt expansion:
${!varname}i stället föreval echo \$$varname - Associativa arrayer för dynamiska nyckel-värde-uppslagningar
- Funktioner i stället för genererade kommandosträngar
#!/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
fiIndatavalidering: tillåtelselistor framför spärrlistor
Att avvisa kända farliga tecken (en spärrlista) är bräckligt — angripare hittar kodningar eller tecken som Ni har glömt. Använd i stället en tillåtelselista: acceptera endast tecken som Ni vet är säkra.
Strategier för tillåtelselistor i Bash:
- Reguljärt uttryck:
[[ "$input" =~ ^[A-Za-z0-9_-]+$ ]] - Mönstermatchning:
case "$input" in [A-Za-z0-9]*) ... ;; esac - Uppräkning: jämför med en fast uppsättning giltiga värden
Validera vid gränsen — så snart indata kommer in i skriptet — innan den når något 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' # REJECTEDAnvänd arrayer för att skicka argument säkert
När Ni behöver bygga ett kommando dynamiskt — till exempel lägga till flaggor villkorligt eller iterera över indata — ska Ni använda en Bash-array i stället för att sammanfoga strängar.
Strängsammanfogning suddar ut all struktur; en Bash-array bevarar varje argument som ett separat element utan att skalet tolkar om det.
- Deklarera:
args=() - Lägg till:
args+=(--flag "$value") - Kör:
command "${args[@]}"
"${args[@]}" expanderar varje element som ett separat, individuellt citerat ord — precis 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[@]}"Avgränsaren --: skydd mot flagginjektion
Även ett korrekt citerat argument kan misstolkas som en flagga om det börjar med -. Tänk på rm "$file" där file='-rf .': citeringen skyddar mot orddelning, men rm tolkar fortfarande -rf som flaggor.
POSIX-konventionen -- signalerar slut på flaggor till de flesta GNU-/BSD-verktyg. Allt efter -- behandlas som ett positionsargument, aldrig som en flagga.
#!/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_targetSanera indata för SQL och externa verktyg
När Bash-skript anropar databas-CLI:er (psql, mysql), curl med användarstyrda URL:er eller liknande verktyg gäller ytterligare två lager:
- Parametriserade frågor: interpolera aldrig användardata i SQL-strängar. Skicka värden via
-vipsqleller--data-urlencodeicurl. - Separera data från kod: använd
printfmed en bokstavlig formatsträng; låt aldrig användarinmatning vara formatsträngen.
Exemplet nedan frågar PostgreSQL på ett säkert sätt och håller det användarstyrda värdet helt utanför SQL-texten.
#!/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"Checklista för härdning: sätt ihop allt
Ett produktionsklart säkert Bash-skript kombinerar alla tekniker från den här lektionen till ett konsekvent skydd i flera lager. Här är en minimal men komplett härdad mall:
set -euo pipefail— avsluta vid fel, behandla odefinierade variabler som fel och vidarebefordra fel i rör.- Validera vid inmatningen — använd en tillåtelselista för all extern indata innan den når något kommando.
- Citera allt —
"$var","$@","${array[@]}"— inga undantag om Ni inte behöver orddelning. - Använd arrayer för dynamisk kommandokonstruktion.
- Inled argument med
--när Ni skickar användarstyrda filnamn eller strängar. - Använd aldrig
evalmed otillförlitliga data; föredra${!var}för indirekta uppslagningar. - Begränsa behörigheter — kör skript med minsta nödvändiga behörighet och undvik
sudoi skript som tar emot användarindata.
#!/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[@]}"Kunskapskontroll: citering och förebyggande av injektioner
Testa Er förståelse av de viktigaste begreppen i den här lektionen.
Lektionssammanfattning: förebyggande av kommando- och argumentinjektioner
Ni har gått igenom hela verktygslådan för säker hantering av indata i Bash:
- Orddelning och glob-expansion är de grundläggande mekanismer som gör osäkra variabler till injektionsvektorer.
- Använd dubbla citattecken kring varje variabel (
"$var","$@","${arr[@]}") för att stoppa båda hoten. - Använd
"$@"— aldrig$@eller$*okvoterat — när Ni vidarebefordrar argument. - Inled användarstyrda filnamn med
--för att förhindra flagginjektion. - Använd en tillåtelselista för all extern indata med ett reguljärt uttryck (
[[ $v =~ ^pattern$ ]]) innan den når något kommando. - Bygg dynamiska kommandon med arrayer (
cmd+=()→"${cmd[@]}"), aldrig genom strängsammanfogning. - Eliminera
evalochbash -c "$input"; använd${!varname}för säker indirekt expansion. - Inled alltid skript med
set -euo pipefailochIFS=$'\n\t'som en härdad grundnivå.
Om dessa metoder tillämpas konsekvent från första raden i varje skript minskar de Bash-ytan för sårbarheter i injektionsklassen till nästan noll.
Lär dig Bash med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 22
- Lektioner
- 88
Vanliga frågor
Är lektionen ”Förhindra kommando- och argumentinjektion” gratis?
Ja – hela texten till ”Förhindra kommando- och argumentinjektion” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Bemästra Linux-kommandoraden och Bash-skriptning, kan Ni uppgradera till CoddyKit PRO. Kursen i Bemästra Linux-kommandoraden och Bash-skriptning innehåller totalt 4 lektioner.
Vad lär jag mig i ”Förhindra kommando- och argumentinjektion”?
Använd citattecken, validering och arrayer för att skicka opålitlig indata och eliminera orddelning och eval-baserad injektion. Ni övar på Bemästra Linux-kommandoraden och Bash-skriptning med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Bemästra Linux-kommandoraden och Bash-skriptning?
Du behöver inga förkunskaper. Utbildningen i Bemästra Linux-kommandoraden och Bash-skriptning på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Förhindra kommando- och argumentinjektion”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Bemästra Linux-kommandoraden och Bash-skriptning-lektionen?
Ja. Varje Bemästra Linux-kommandoraden och Bash-skriptning-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Förhindra kommando- och argumentinjektion
- Säker hantering av hemligheter och ren miljö
- Körning med minsta möjliga behörighet och disciplin kring sudo
- Statisk analys och granskning med ShellCheck