Implicazioni sulla sicurezza dell'utilizzo di dati non autorizzati nella valutazione aritmetica di Shell


17

In un commento a una recente domanda , Stéphane Chazelas afferma che esistono implicazioni di sicurezza nell'aritmetica delle doppie parentesi come:

x=$((1-$x))

sulla maggior parte delle conchiglie.

Le mie competenze su Google sembrano essere arrugginite e non riesco a trovare nulla. Quali sono le implicazioni di sicurezza dell'aritmetica tra doppie parentesi?

Risposte:


22

Il problema si verifica nei casi in cui il contenuto di $xnon è stato disinfettato e contiene dati che potrebbero essere potenzialmente sotto il controllo di un utente malintenzionato nel caso in cui il codice shell possa finire per essere utilizzato in un contesto di escalation di privilegi (ad esempio uno script invocato da un setuid applicazione, uno script sudoers o utilizzato per elaborare dati fuori rete (CGI, hook DHCP ...) direttamente o indirettamente).

Se:

x='(PATH=2)'

Poi:

x=$((1-$x)))

ha l'effetto collaterale dell'impostazione PATHsu 2(un percorso relativo che potrebbe benissimo essere sotto il controllo dell'attaccante). Puoi sostituirlo PATHcon LD_LIBRARY_PATHo IFS... Lo stesso succede con x=$((1-x))bash, zsh o ksh (non trattino né yash che accettano solo costanti numeriche nelle variabili lì).

Nota che:

x=$((1-$x))

non funzionerà correttamente per valori negativi $xin alcune shell che implementano l' --operatore ( opzionale secondo POSIX) (decremento) (come con x=-1, ciò significa chiedere alla shell di valutare l' 1--1espressione aritmetica). "$((1-x))"non ha il problema poiché xviene espanso come parte della valutazione aritmetica (non prima).

In bash, zshe ksh(no dasho yash), se xè:

x='a[0$(uname>&2)]'

Quindi l'espansione $((1-$x))o $((1-x))causa l' unameesecuzione di quel comando (per zsh, adeve essere una variabile array, ma si può usare psvarper esempio per quello).

In sintesi, non si dovrebbe usare non inizializzate o non sterilizzate dati esterni in espressioni aritmetiche in gusci (si noti che la valutazione aritmetica può essere fatto da $((...))(aka $[...]in basho zsh), ma anche a seconda della shell in let, [/ test, declare/typeset/export..., return, break, continue, exit, printf, printbuiltin, indici di array ((..))e [[...]]costrutti per citarne alcuni).

Per verificare che una variabile contenga un numero intero decimale letterale, è possibile utilizzare POSIXly:

case $var in
  ("" | - | *[!0123456789-]* | ?*-*) echo >&2 not a valid number; exit 1;;
esac

Attenzione che [0-9]in alcune versioni locali più di 0123456789. [[:digit:]]dovrebbe essere OK ma non ci scommetterei.

Ricorda inoltre che i numeri con zeri iniziali sono trattati come ottali in alcuni contesti (a 010volte 10, a volte 8) e fai attenzione che il controllo sopra consentirà di passare attraverso numeri potenzialmente più grandi dell'intero massimo supportato dal tuo sistema (o qualunque applicazione tu voglia usa quel numero intero in; bash ad esempio considera 18446744073709551616 come 0 dato che è 2 64 ). Quindi potresti voler aggiungere ulteriori controlli nell'affermazione del caso sopra come:

(0?* | -0?*)
  echo >&2 'Only decimal numbers without leading 0 accepted'; exit 1;;
(-??????????* | [!-]?????????*)
  echo >&2 'Only numbers from -999999999 to 999999999 supported'; exit 1;;

Esempi:

$ export 'x=psvar[0$(uname>&2)]'
$ ksh93 -c 'echo "$((x))"'
Linux
ksh93: psvar: parameter not set
$ ksh93 -c '[ x -lt 2 ]'
Linux
ksh93: [: psvar: parameter not set
$ bash -c 'echo "$((x))"'
Linux
0
$ bash -c '[[ $x -lt 2 ]]'
Linux
$ bash -c 'typeset -i a; export a="$x"'
Linux
$ bash -c 'typeset -a a=([x]=1)'
Linux
$ bash -c '[ -v "$x" ]'
Linux
$ mksh -c '[[ $x -lt 2 ]]'
Linux
$ zsh -c 'echo "$((x))"'
Linux
0
$ zsh -c 'printf %d $x'
Linux
0
$ zsh -c 'integer x'
Linux
$ zsh -c 'exit $x'
Linux

Altre letture a:


x='P=3'; : $(($x + 5))sarà impostato Psu 8, ma x='P=3'; : $((x + 5))sarà impostato Psu 3(in zsh, ksho bash). "Lo stesso accade con $((x + 1))..." non è corretto ora; sarà impostato PATHsu 2, come un tempo.
mosvy,

@mosvy, giusto grazie (e per la tua modifica precedente). Corretto ora.
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.