Come passare in modo sicuro le variabili agli script abilitati per root?


13

Questa domanda è del tutto generale e non si applica solo alla mia situazione, ma ... Ho un piccolo dispositivo busybox in cui desidero che un utente non root sia in grado di eseguire uno script particolare con i privilegi di root. Ad esempio, qualcosa come questo piccolo script per abilitare DHCP, dove l'unica variabile ( $1) da inviare sulla cmdline (!!) è il nome host da inviare:

#!/bin/bash
udhcpc -b -i eth0 -h $1

eseguire udhcpc in questo modo richiede l'accesso come root, quindi per fare questo ho intenzione di modificare /etc/sudoersper contenere questa riga:

joe ALL = NOPASSWD: /path/to/enable_dhcp.sh

che dovrebbe consentire a "joe" di eseguire facilmente quello script con i privilegi di root semplicemente eseguendo:

sudo /path/to/enable_dhcp.sh

e non mi viene chiesta una password (che è quello che voglio, dato che voglio che Joe sia in grado di scrivere questo).

Ora .. So (o almeno penso di farlo) che l'utilizzo $1in uno script che può essere facilmente eseguito con i privilegi di root è un'idea ORRIBILE poiché puoi iniettare quello che vuoi in quello.

Quindi ... qual è il modo migliore per affrontarlo? Come posso lasciare che joe faccia quello che voglio con i privilegi di root, consentirgli di passare una variabile (o effettivamente farlo come con una variabile d'ambiente), senza essere troppo aperto agli attacchi di iniezione?

Risposte:


14

L'esecuzione degli script della shell in sudoè sicura a condizione che sudosia configurata per ripristinare l'ambiente . Al contrario, se sudonon ripristina l'ambiente, l'esecuzione di uno script di shell non è sicura, anche se lo script non utilizza i suoi parametri (vedere Consenti setuid su script di shell ). Assicurarsi di avere Defaults env_resetin /etc/sudoerso che questa opzione è di default in fase di compilazione ( sudo sudo -V | grep envdovrebbe includere Reset the environment to a default set of variables).

Non vi è alcun pericolo particolare nell'uso dei parametri dello script. $1è una stringa, tutto ciò che devi assicurarti è che la stai usando come stringa. (Ad esempio, non farlo eval "$1".) Ovviamente, è particolarmente importante qui non fare ipotesi sul contenuto della variabile e mettere virgolette doppie attorno a tutte le sostituzioni di variabili (cioè scrivere "$1", no $1). Nota che mettere doppie virgolette attorno alle sostituzioni variabili non è specifico per gli script in esecuzione con privilegi, è qualcosa che devi fare sempre.

Potresti voler convalidare ulteriormente il parametro, a seconda di cosa udhcpcsuccede con qualcosa che non assomiglia a un nome host. Ad esempio, questo eseguirà un primo controllo sintattico:

#!/bin/sh
case "$1" in
  *[!:-.0-9A-Za-z]*|-*) echo 1>&2 "Badly formed host name!"; exit 3;;
esac
udhcpc -b -i eth0 -h "$1"

Altre cose da considerare che potrebbero avere un impatto sul comportamento di quel comando: directory di lavoro corrente e cosa indicano stdin, stdout, stderr, gestori di segnale e ulimits. Ad esempio, consentendo i core dump (su <kbd> Ctrl- \ </kbd>), potresti consentire all'utente di sporcare / eseguire / bloccare che sul mio sistema è un tmpfs con dimensioni molto limitate e potrebbe consentire un DoS.
Stéphane Chazelas,

5

È necessario associare l'input passato a un modello valido noto.

Ad esempio, sembra che un indirizzo IP possa essere un input valido per te. Quindi potresti usare qualcosa del genere:

if [[ "$1" =~ ^[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9]$ ]]
then
  udhcpc -b -i eth0 -h "$1"
else
  echo "Don't mess with me pork chop."
fi

Nota che regexp non è stato testato, sei responsabile di assicurarti che regexp non consenta nulla di pericoloso.

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.