La funzione di importazione delle funzioni della shell bash genera inevitabilmente un problema di escalation dei privilegi?

13

Anche senza il problema immediato di esecuzione del codice dei comandi di trascinamento Shellshock , in che misura la funzionalità delle funzioni di importazione bash dall'ambiente dà origine a una vulnerabilità completa di escalation dei privilegi?

Per essere chiari, ci sono molti programmi setuid, e alcuni di essi chiameranno direttamente o indirettamente script, o useranno la chiamata system(3) , che nella maggior parte dei Linux passa attraverso bash . La domanda è in che misura, supponendo che i sistemi abbiano binari di setuid installati , questa funzione di bash consente l'escalation dei privilegi locali.

  • Ad esempio, se la chiamata a uno script consente l'override dei built-in? In tal caso, ciò può dar luogo a un'escalation di privilegi in combinazione con un eseguibile setuid e la chiamata a system(3) , eseguendo l'override ad es. ls , cd o qualcosa di innocuo?
  • Un tale vettore di escalation richiede di chiamare uno script (nel qual caso si potrebbe potenzialmente sovrascrivere ls o qualsiasi comando utilizzato dallo script che non ha utilizzato un percorso completo)?
  • Le funzioni importate sono potenzialmente utilizzate in qualsiasi momento dal normale percorso di esecuzione di /bin/sh -c ARGUMENTS anche quando il primo argomento non è uno script?
  • Potresti semplicemente dare a una variabile di ambiente lo stesso nome del primo argomento a system ?
  • In tal caso ciò significa che ogni chiamata a system(3) da un eseguibile setuid, su un sistema in cui /bin/sh è bash, è un vettore di escalation di privilegi?
posta Ben 29.09.2014 - 13:07
fonte

4 risposte

6

Questi test vengono eseguiti su un sistema senza patch:

# ls='() { echo NO; }' bash -c 'ls'
NO

il carattere jolly * è obbligatorio o perl sostituirà la chiamata di sistema con una combinazione fork / exec

# ls='() { echo NO; }' perl -e 'system("ls *");'
NO

Tuttavia ls non è un builtin:

# type ls
ls is hashed (/bin/ls)
# type echo
echo is a shell builtin

Quindi proviamo a sovrascrivere l'eco incorporato ("command" sovrascrive il built-in per evitare la ricorsione):

# echo='() { command echo NO; }' bash -c 'echo YES'
NO

Finora abbiamo dimostrato che:

  1. può sovrascrivere un built-in
  2. e non richiede uno script per essere chiamato
  3. anche quando il primo argomento non è uno script
  4. ogni chiamata a "sistema" è un vettore, che fornisce i privilegi del chiamante

Penso che i "sistemi" e "popen" nudi siano marci, penso che la maggior parte degli usi di questi non si preoccupino di sfuggire ai meta-caratteri della shell nei dati degli utenti.

Ho questa chiamata quando voglio che la shell produca pipeline o usi i built-in della shell, ma richiede ancora fork / exec:

exec("sh", "-c", "\"$0\" \"$1\" | tee -a \"$2\"", ...);

La tecnica diventa bash per fare riferimento agli argomenti dei comandi -c, $ 0 è il primo di questi argomenti, oppure "-" può essere usato come riempitivo:

exec("sh", "-c", "\"$1\" \"$2\" | tee -a \"$3\"", "--", ...);

Questo test viene eseguito su un sistema con patch:

$ env "BASH_FUNC_ls()=() { echo NO ; }" bash -c 'ls'
NO

mostra chiaramente che questo problema non ha nulla a che fare con shellshock.

Sebbene gli autori di script o di strumenti che usano script debbano sapere per validare l'input dell'utente e dovrebbero sapere validare / pulire l'ambiente (dato che contiene input dell'utente) alcune parti dell'ambiente possono aver bisogno di essere preservate, e puo ' essere sempre facile vedere quali potrebbero essere;

XAUTHORITY, DBUS_SESSION_BUS_ADDRESS, XDG_SESSION_DESKTOP, SSH_AUTH_SOCK sono alcune e altre variabili di ambiente importanti potrebbero non essere ancora state inventate

si chiama "ambiente" per una ragione. Il PERCORSO può essere disinfettato, ma il primo comando inviato a system () può essere installato

La pagina man sudoedit scrive:

Running shell scripts via sudo can expose the same kernel bugs that make
setuid shell scripts unsafe on some operating systems (if your OS has a
/dev/fd/ directory, setuid shell scripts are generally safe).

Tuttavia questo non è vero per gli script di shell bash setuid a meno che non rifiutino di importare tutte le funzioni di bash

    
risposta data 29.09.2014 - 15:30
fonte
2

"Può dare origine a un'escalation di privilegi in combinazione con un eseguibile setuid ...?"

Non puoi avere script setuid su GNU, quindi supponiamo che un binario setuid chiami direttamente uno script Bash. Nota prima di iniziare che si tratta di un design estremamente scadente ed è esplicitamente raccomandato da GNU e di nuovo nel manuale setuid . Nota anche che ld eliminerà le variabili d'ambiente più nefaste e che non è possibile in GNU / Linux inserire il codice in un processo setuid o ottenere un dump di esso (a meno che tu non sia root). Quindi gli attacchi basati sull'ambiente richiedono un binario setuid scritto male.

Shellshock non ha assolutamente alcun ruolo nello sfruttamento di questi binari setuid. Se il binario segue i consigli di sanità, non chiamerà nessuno script di shell, non chiamerà il sistema e farà in modo che tutte le chiamate di exec* eseguite non siano influenzate da variabili d'ambiente non attendibili, non sarà vulnerabile ad alcun escalation di privilegi di progettazione. Se il binario setuid non convalida l'input non fidato, sarà comunque vulnerabile.

Il motivo per cui non dovresti sistemare o lanciare una shell non è perché l'ambiente scelto dal callee non fidato verrebbe portato nella nuova shell (che dipende interamente dalle pratiche di programmazione) ma perché se avessi commesso qualche errore tu consentirebbe un attacco confuso con un ambito illimitato anziché consentire solo operazioni specifiche: il sistema verrebbe semplicemente compromesso a un livello più ampio estensione rispetto a qualsiasi altro scenario.

Chiamare un binario setuid con un ambiente simile a Shellshock da Bash farà sì che l'istanza di Bash elabori i primitivi Bash aggiuntivi con i privilegi tuoi , non i privilegi del binario setuid chiamato in seguito, che dovrebbe già assumere comunque un ambiente ostile.

"Un tale vettore di escalation richiederebbe la chiamata di uno script?"

Shellshock implica che Bash venga invocato con un ambiente sotto il controllo di un principal che ha privilegi inferiori a quello che ha invocato Bash in primo luogo.

Se nessuno sta invocando Bash, il carico utile di Shellshock è inutile poiché non verrà elaborato (proprio come un exploit OpenSSL non funziona su Microsoft Word).

"Le funzioni importate sono potenzialmente utilizzate in qualsiasi momento dal normale percorso di esecuzione di / bin / sh -c ARGUMENTS anche se il primo argomento non è uno script?"

Se l'argomento è uno script di shell e /bin/sh punta a Bash, Bash può essere sfruttato. Tuttavia non vi è assolutamente alcun interesse nel fare ciò poiché stai usando i tuoi privilegi per eseguire il comando. Non ottieni alcun privilegio (a meno di assumere una configurazione di SELinux o AppArmor in cui hai più privilegi utilizzando /bin/sh -c di chiamare direttamente qualcosa, tale configurazione sarebbe interrotta e non intenzionale).

Se l'argomento è un binario, viene chiamato il binario. Microsoft Word utilizza le funzioni da un Firefox in esecuzione contemporaneamente? No. Lo stesso è vero qui: il caricatore caricherà il codice binario ed eseguirà il binario, non eseguirà il codice buggy da un altro binario. L'unico scenario in cui è possibile modificare il comportamento di un binario tramite l'iniezione di codice e non è possibile eseguire iniezioni di codice sui processi setuid.

"Potresti semplicemente dare a una variabile d'ambiente lo stesso nome del primo argomento del sistema?"

Sì, ma il sistema non legge una variabile di ambiente, esegue un comando. Le variabili d'ambiente sono solo un dizionario di nome: coppie di stringhe. Non sostituiscono ogni singolo testo che verrà utilizzato in futuro, indipendentemente dalla semantica. Un programma deve fare un uso esplicito di una variabile d'ambiente leggendolo e decidendo di prendersene cura.

"Se è così significa che ogni chiamata al sistema (3) da parte di un eseguibile setuid, su un sistema in cui / bin / sh è bash, è un vettore di escalation di privilegi?"

Assolutamente no. Una chiamata a system da un binario setuid è solo una cattiva idea, perché se ci fosse una vulnerabilità, le conseguenze sarebbero ridicolmente disastrose. Una chiamata a system su un SO che utilizza Bash non modifica nulla sul fatto che le escalation di privilegi richiedono due principal: Shellshock causerebbe un'escalation di privilegi solo quando un principal privilegiato più alto decide di chiamare Bash con un ambiente non verificato fornito da un privilegiato inferiore .

Nella maggior parte dei casi, una simile chiamata di sistema sarebbe già indesiderabile perché ci sono diversi modi non Shellshock in cui una tale configurazione potrebbe diventare sbagliata, e le precauzioni da adottare per evitare gli attacchi confusi esistenti potrebbero impedire anche Shellshock. / p>     

risposta data 29.09.2014 - 17:42
fonte
2

Se il tuo set (u | g) id binary conserva il suo vero [ug] id, la risposta è no.

Quando e [ug] id! = real [ug] id, e non invocato in modalità privilegiata ( -p ), bash elimina i suoi privilegi:

Bash shell.c:main()

  if (running_setuid && privileged_mode == 0)
    disable_priv_mode ();

Quando si esegue in modalità privilegiata, o quando bash è patchato per non rilasciare i privilegi quando viene chiamato come / bin / sh (es .: Debian ha una tale patch , per evitare di rompere vecchi programmi [ug] id impostati, come UUCP), bash non importa funzioni dall'ambiente. Bash controlla se sta eseguendo l'id [ug], o in modalità privilegiata ( -p ), e non importa le funzioni dall'ambiente in questo caso.

Bash shell.c:main()

  /* Initialize internal and environment variables.  Don't import shell
     functions from the environment if we are running in privileged or
     restricted mode or if the shell is running setuid. */
#if defined (RESTRICTED_SHELL)
  initialize_shell_variables (shell_environment, privileged_mode||restricted||running_setuid);
#else
  initialize_shell_variables (shell_environment, privileged_mode||running_setuid);
#endif

Bash variables.c:initialize_shell_variables()

  /* If exported function, define it now.  Don't import functions from
 the environment in privileged mode. */
  if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
    
risposta data 30.09.2014 - 20:38
fonte
-1

Sì!

La dimostrazione che l'esportazione della funzione di bash è solo un rischio è piuttosto semplice:

/bin/bash
SHELL=/bin/bash
export SHELL
ls() { echo executing /tmp/booby_trapped_ls ; }
declare -fx ls
perl -e 'system ("ls *") ;'
    
risposta data 29.09.2014 - 17:02
fonte

Leggi altre domande sui tag