Sudo in cascata per l'elevazione dei privilegi

6

Intendo utilizzare l'utente con privilegi minimi per eseguire una determinata attività. Il problema è che coinvolge una sorta di catena di responsabilità e si traduce come una catena sudo nei miei script, diffondendo l'attività generale in molti punti.

File Sudoer

"www-data"      ALL = (webadmin) NOPASSWD: /home/webadmin/scripts/git-deploy.sh
"webadmin"      ALL = (root) NOPASSWD: /root/scripts/copy-deploy ""

Dettagli

Per rendere più tangibile il paragrafo precedente: Alcune richieste vengono inviate ad Apache. Il lavoratore è in esecuzione come www-data Attraverso mod_php, lo script /home/webadmin/scripts/git-deploy.sh viene lanciato usando

<?php
exec('/'.escapeshellarg($gitRepo))

$gitRepo è alimentato dallo script seguente:

    $bitBucketUrl=json_decode($request->getContent(),true);

    if(isset($bitBucketUrl['url'])){
        $bitBucketUrl=$bitBucketUrl['url'];
        if(!preg_match('/\.git$/',$bitBucketUrl)){
            $bitBucketUrl.='.git';
        }
    }else{
        $result='bad url';
    }

    if(preg_match('/^[email protected]:TEAM\/[a-zA-Z0-9\.-]+\.git$/',$bitBucketUrl)){
        exec(escapeshellcmd('sudo -u webadmin /home/webadmin/scripts/git-deploy.sh '.escapeshellarg($bitBucketUrl)),$results);
        $result=$results;
    }else{
        $result=$bitBucketUrl;
    }

Naturalmente, lo script /home/webadmin/scripts/git-deploy.sh controlla $1

#!/bin/bash
valid=^[email protected]:TEAM/[a-zA-Z0-9-]+\.git$
if [[ $1 =~ $valid  ]]; then
  name=${1#[email protected]:TEAM/}
  name=${name%.git}
  fullName=/home/webadmin/websites/$name
  if [[ -e $fullName ]] ; then
    echo "$fullName exists, will do a git pull instead"
    echo "cd $fullName && git pull"
  else
    echo "/usr/bin/git clone $1"
  fi
  if [[ -e $fullName/deploy/apache-conf/ ]]; then
    #sudo -u root /root/scripts/copy-deploy
  fi
fi

Nota: so che è solo eco, questa è la versione di prova con utenti fittizi.

Ogni script è solo u+rwx dal suo proprietario (700).

Domanda

  1. Sta diffondendo le sceneggiature in vari luoghi giocando contro la sicurezza? (Più difficile capire cosa sta succedendo)
  2. Vedi qualcos'altro che non va?
posta programaths 26.03.2014 - 17:36
fonte

1 risposta

2

Prima di tutto, cosa stai cercando di fare ? Stai spiegando come stai facendo ma non qual è il tuo obiettivo finale. Valuta la possibilità di rivedere la tua domanda per aggiungere ulteriori dettagli al riguardo.

Detto questo, per il resto di questa risposta presumo che tu stia facendo una sorta di proxy (?) per il mirror dei repository GIT. Che suona come un problema già risolto, ad es. utilizzando git git .

Tuttavia, risolvendo le vostre domande specifiche nell'ordine:

Is spreading the scripts in various places playing against security ? (Harder to grasp what is going on)

Sì. Al momento hai le seguenti "parti mobili":

  1. Uno script PHP che analizza quello che sembra essere l'URL del repository inviato tramite una richiesta HTTP
  2. Uno script di shell che chiama altri binari (git)
  3. Tutto racchiuso in sudo
  4. Diffondi su molti server, come hai detto

Un errore in qualsiasi di quanto sopra potrebbe comportare un compromesso del sistema.

Inoltre, un problema potrebbe insinuarsi in una fase successiva: cosa succede se trovi un bug in una copia dello script e dimentichi di replicarlo sugli altri server? Cosa succede se git restituisce un errore oscuro che non è possibile analizzare e si finisce con un danneggiamento dei dati dell'utente (che viene quindi sottoposto a backup danneggiato)? Come vengono segnalati gli errori? Esiste un sistema di log centralizzato e, cosa più importante, c'è qualcuno che lo sta monitorando?

Do you see something else wrong ?

Sì e no. Lo script PHP controlla se c'è una chiave "url" nell'input JSON e, se non ce n'è alcuna, imposta "return" su "bad value". Quindi continua . Questa è una cattiva pratica: non un bug di per sé al momento, ma un bug che aspetta di accadere. Invece di continuare, è necessario interrompere qui il flusso di lavoro del programma e restituire un errore.

Ad esempio, cosa succede se in pochi mesi qualcun altro aggiunge del codice come:

/* previous code */
if(preg_match('/^[email protected]:TEAM\/[a-zA-Z0-9\.-]+\.git$/',$bitBucketUrl)){
    exec(escapeshellcmd('sudo -u webadmin /home/webadmin/scripts/git-deploy.sh '.escapeshellarg($bitBucketUrl)),$results);
    $result=$results;
}else{
    $result=$bitBucketUrl;
}

/* new code */
[...]
exec('sudo -u webadmin /home/webadmin/scripts/new-stuff.sh', $bitBucketURL);

Il codice che ho aggiunto contiene due bug: puoi individuarli?

  • Si potrebbe pensare che lo script new-stuff.sh venga eseguito solo se bitBucketURL contiene dati validi. Invece, viene eseguito indipendentemente da ciò che accade in anticipo poiché non si esegue il salvataggio nei rami else .
  • Non c'è escapeshellarg

Se ti ci sono voluti più di qualche secondo per individuare i bug, immagina qualcuno che non ha mai visto il tuo codice prima.

Ho omesso intenzionalmente il escape dal mio esempio di codice per un motivo: dovresti disinfettare i tuoi input una volta per tutte e continuare a utilizzarlo piuttosto che dover chiamare la famiglia di funzioni escape ogni volta che è necessario utilizzare l'input dell'utente. È troppo facile dimenticare una chiamata a escapeshellargs , soprattutto se richiede più sforzo (= digitazione). Invece, prova a fare l'uso corretto del tuo codice il percorso di minor resistenza . Ad esempio,

$bitBucketUrl=json_decode($request->getContent(),true);

potrebbe diventare:

$unsafe_user_input=json_decode($request->getContent(),true);
$safe_user_input = escapeshellarg($bitBucketUrl);
[...]
res = do_stuff(safe_user_input);
if (check_error(res))
{
    stop_with_error_message(message);

In questo modo ovvio quali sono unsafe_user_input e safe_user_input .

Potrebbero esserci altri problemi con il tuo approccio; l'idea di eseguire codice con il minimo privilegio è buona, ma è troppo ingegnerizzata e può avere effetti collaterali sgradevoli.

    
risposta data 03.06.2014 - 17:05
fonte

Leggi altre domande sui tag