Interruzione sandbox del codice eval PHP

11

Ho notato un commento strongmente sottovalutato qui: link

function eval_syntax($code)
{
    $braces = 0;
    $inString = 0;

    // We need to know if braces are correctly balanced.
    // This is not trivial due to variable interpolation
    // which occurs in heredoc, backticked and double quoted strings
    foreach (token_get_all('<?php ' . $code) as $token)
    {
        if (is_array($token))
        {
            switch ($token[0])
            {
            case T_CURLY_OPEN:
            case T_DOLLAR_OPEN_CURLY_BRACES:
            case T_START_HEREDOC: ++$inString; break;
            case T_END_HEREDOC:   --$inString; break;
            }
        }
        else if ($inString & 1)
        {
            switch ($token)
            {
            case ''':
            case '"': --$inString; break;
            }
        }
        else
        {
            switch ($token)
            {
            case ''':
            case '"': ++$inString; break;

            case '{': ++$braces; break;
            case '}':
                if ($inString) --$inString;
                else
                {
                    --$braces;
                    if ($braces < 0) return false;
                }

                break;
            }
        }
    }

    // If $braces is not zero, then we are sure that $code is broken.
    // We run it anyway in order to catch the error message and line number.

    // Else, if $braces are correctly balanced, then we can safely put
    // $code in a dead code sandbox to prevent its execution.
    // Note that without this sandbox, a function or class declaration inside
    // $code could throw a "Cannot redeclare" fatal error.

    echo "Braces: ".$braces."\r\n";
    $braces || $code = "if(0){{$code}\n}";

    if (false === eval($code)) {}
}

eval_syntax("file_put_contents('/home/yourname/Desktop/done.txt', 'OVERWRITTEN');");

Ho provato a ignorare il codice e portare all'esecuzione di input utente malizioso con eval , ma non ho potuto. Mi chiedo perché sia stato downvoted.

Come puoi vedere se le parentesi graffe non corrispondono, non aggiunge 'if(0){' . $code . '} ed esegue l'input dell'utente così com'è con parentesi graffe non corrispondenti che generano eccezioni e non verranno realmente eseguite.

Se le parentesi graffe sono una corrispondenza, chiama eval , ma poiché è all'interno di if {0} "sandbox", non fa nulla. Come può qualcuno aggirare questo?

So che la valutazione è insicura, ma voglio sapere qual è il trucco qui. Come si può ignorare la sicurezza di if (0) e le parentesi graffe nel codice sopra?

Ho provato ad aggiungere // {in modo da squilibrare le parentesi graffe e non aggiungerà if (0) e chiama eval, ma token_get_all rovina tutto ciò.

    
posta JohnDoes 24.01.2018 - 02:28
fonte

1 risposta

1

Penso che questo commento dal codice che hai postato riassuma i miei pensieri:

// We need to know if braces are correctly balanced. // This is not trivial due to variable interpolation // which occurs in heredoc, backticked and double quoted strings

Tenere presente che il risultato dell'esecuzione errata del controllo del codice è una vulnerabilità legata all'esecuzione di codice in modalità remota. Lavorare su articoli non banali è ovviamente la norma per gli ingegneri, ma se si sta lavorando su un compito estremamente difficile e un errore porta al tipo più grave di vulnerabilità della sicurezza - beh, chiaramente che è una ricetta per il disastro. In effetti vale la pena sottolineare che il commento che hai postato è stato il secondo tentativo degli autori a questo. Il suo primo tentativo di contenere almeno un errore che (presumibilmente) era vulnerabile alla "fuga dalla sandbox" e gli imponeva di ricominciare. Di sicuro non mi fiderò della sicurezza della mia applicazione per uno script singolo scritto in una casella di commento su qualche pagina a caso sul web. Tanto più che (a meno che mi manchi qualcosa) questo commento si trova in una pagina che descrive un linguaggio integrato che fa esattamente la stessa cosa. Mi fiderei del linguaggio integrato prima di un ragazzo casuale su Internet.

Indipendentemente dal fatto che qualcuno abbia già trovato o meno un exploit, ciò non cambia il fatto che questa è generalmente una cattiva idea in primo luogo. Cosa succede se ci sono altre opzioni di fuga a cui l'autore non ha pensato? Ad esempio, un sacco di exploit là fuori hanno fatto affidamento sulla confusione su diverse codifiche. Potrebbe essere possibile che un utente malintenzionato inserisca una parentesi graffa usando una codifica diversa da quella nel file, ma ancora supportata da PHP, che quindi non verrà registrato come rinforzo nei suoi assegni, ma verrà riconosciuto come tale da PHP, consentendo un attaccante per superare il controllo del bilanciamento del tutore. Certo, quella particolare via d'attacco potrebbe non effettivamente essere possibile, ma sto principalmente cercando di enfatizzare il punto generale. Ci possono essere molti "trucchi" difficili da prendere in situazioni come questa, e il risultato della mancanza di uno di questi in questo codice è una vulnerabilità legata all'esecuzione di codice in modalità remota.

Di fronte a "Get perfect o estremamente vulnerabile" la mia prima preferenza è "Just do not do it". Ciò è seguito da un strong "non fidarsi di un commento casuale su Internet", specialmente se esiste un linguaggio integrato facilmente accessibile che fa esattamente la stessa cosa ma (presumibilmente) in modo sicuro.

Modifica per aggiungere . Vale la pena fare un commento su eval . Hai detto "So che eval è insicuro, ma" ... Questo non è assolutamente vero. L'utilizzo di eval è generalmente disapprovato per alcuni motivi:

  1. Se non altro tende a avere scarse prestazioni
  2. Se usato in modo improprio, può certamente creare reali problemi di sicurezza
  3. In genere viola le migliori pratiche di programmazione

Tuttavia, come ogni strumento, può avere il suo tempo e posto. Quindi, per essere chiari, il problema non è che eval sia insicuro. La domanda è se o meno eval viene usato in modo sicuro (e correttamente) qui. Per tutte le ragioni sopra delineate, non penso che sia usato correttamente qui, ma è diverso da una frase "eval è insicura".

    
risposta data 11.10.2018 - 14:29
fonte

Leggi altre domande sui tag