Quale misura di sicurezza si dovrebbe implementare prima di eseguire i file caricati dall'utente?

39

Voglio fare un piccolo puzzle di programmazione sul mio sito web. Ci sarà un compito. All'utente verrà chiesto di caricare un file sorgente C ++ con la loro soluzione. Il file dovrebbe essere compilato, eseguito con qualche input e controllato se produce output corretto. Quali sono i rischi per la sicurezza? Come faccio ad assicurarmi che il file caricato non sia in grado di fare qualcosa di malevolo?

In alternativa, ci sono siti come Tutorials Point che ti permettono di compilare ed eseguire il codice C ++. Come gestiscono la sicurezza?

    
posta Jen 06.02.2017 - 02:30
fonte

3 risposte

53

È impossibile analizzare un programma per scoprire se farà qualcosa di malevolo. Questo è vero indipendentemente dal fatto che si stia tentando di analizzare il codice sorgente o compilato.

Il modo per fare ciò che si richiede è compilare ed eseguire il codice in una sandbox. Una volta che il programma è terminato (o dopo un timeout che hai deciso) distruggi la sandbox.

La sicurezza di una tale costruzione è sicura quanto la sandbox che stai utilizzando. A seconda dei requisiti del codice necessario per eseguire la sandbox potrebbe essere qualcosa di semplice come la modalità sicura di Linux, o qualcosa di complicato come una macchina virtuale in piena regola, idealmente senza connettività di rete.

Più complicata è la sandbox, maggiore è il rischio di una vulnerabilità di sicurezza nella sandbox che compromette un progetto altrimenti valido.

Alcune lingue possono essere compilate in modo sicuro all'esterno di una sandbox. Ma ci sono lingue in cui persino la loro compilazione può consumare quantità imprevedibili di risorse. Questa domanda su un sito affiliato mostra alcuni esempi di come un piccolo codice sorgente può esplodere in un grande output.

Se il compilatore stesso è privo di vulnerabilità, potrebbe essere sufficiente impostare limiti sulla quantità di CPU, memoria e spazio su disco che è consentito consumare. Per una maggiore sicurezza è possibile eseguire il compilatore all'interno di una macchina virtuale.

Ovviamente questi metodi possono essere combinati per un ulteriore livello di sicurezza. Se dovessi costruire un sistema del genere, probabilmente inizierei una macchina virtuale e all'interno della macchina virtuale userei ulimit per limitare l'utilizzo delle risorse del compilatore. Quindi collegherei il codice compilato in un wrapper per eseguirlo in modalità sicura. Infine, ancora all'interno della macchina virtuale eseguirò l'eseguibile collegato.

    
risposta data 06.02.2017 - 02:49
fonte
28

Questo è un problema davvero difficile, e uno di tutti i giudici di codice online deve risolvere. Fondamentalmente, stai chiedendo come puoi impedire a qualcuno che può eseguire codice arbitrario sulla tua macchina di prenderlo in consegna.

Ho fatto il codice su un giudice online ( Kattis ) per circa un decennio, e qui ci sono alcune delle mie esperienze di costruzione le soluzioni di sicurezza per questo tipo di scenario:

  1. Le versioni precedenti erano basate su un carcere di Solaris. Risulta che si può causare un sacco di scempio in una prigione, e non ti dà la granularità di cui hai bisogno.
  2. Abbiamo implementato una soluzione di filtraggio delle chiamate di sistema usando ptrace. Ciò introduce un overhead molto (più di un contesto) su una chiamata di sistema e mantenere il profilo di sicurezza sincronizzato mentre i compilatori e i corridori cambiano è un incubo. L'ultimo chiodo nella bara di questa soluzione era il threading. Se si consente il threading, un'applicazione può utilizzare un thread per riscrivere la systemcall tra l'ispezione e l'esecuzione e, ad esempio, Java richiede il threading.
  3. In questi giorni usiamo una combinazione di cgroup e namespace. Questo dà un overhead sorprendentemente basso, e poiché fanno parte delle primitive di sicurezza nel kernel di Linux, sono robusti. Dai un'occhiata a MOE Isolate per avere un'idea di come questo può essere fatto. Isolare molto probabilmente risolve il tuo problema.

Si noti che mentre i contenitori, come la finestra mobile o le macchine virtuali, sono popolari, potrebbero non essere la scelta migliore per una soluzione di sicurezza in questo tipo di scenario. È difficile ottenere il controllo a grana fine e il monitoraggio delle risorse che si desidera, è difficile impedire che un processo dannoso si avviti all'interno del contenitore e, l'avvio e la distruzione dei contenitori comporta un sovraccarico eccessivo.

    
risposta data 06.02.2017 - 14:45
fonte
7

Nel caso particolare di un sito web di puzzle, considera l'alternativa: non preoccuparti. Chiedi ai partecipanti di caricare l'output in modo da non dover eseguire codice non affidabile. Ciò consente di risparmiare potenza di calcolo, evita i rischi per la sicurezza e consente alle persone di competere in qualsiasi lingua. Se c'è un premio in palio, puoi verificare manualmente la voce vincente.

Se la forma del tuo puzzle lo consente, puoi frustrare le soluzioni di copia e incolla generando input casuali e scrivendo un verificatore. Ecco come funziona Google Code Jam. Vedi link

    
risposta data 06.02.2017 - 16:32
fonte

Leggi altre domande sui tag