Quanto è sicuro compilare un pezzo di codice sorgente da uno sconosciuto casuale? [chiuso]

40

Supponiamo che sto rivedendo il codice inviato dai candidati per dimostrare le loro capacità. Chiaramente non voglio eseguire gli eseguibili che inviano. Non così chiaramente preferirei non eseguire il risultato della compilazione del loro codice (solo per esempio, Java consente di nascondere il codice eseguibile nei commenti ).

E riguardo la compilazione del loro codice? Voglio gli avvisi del compilatore se non altro, ma se il loro codice contiene sequenze di caratteri intelligenti che sfruttano il mio compilatore e il mio compilatore compromette la mia macchina?

Quando trovo Google per le "vulnerabilità del compilatore", i risultati che ricevo riguardano l'ottimizzazione del compilatore e l'emissione del codice e se il codice emesso è sicuro come il codice sorgente originale doveva essere.

I compilatori sono in genere convalidati per garantire che non compromettano il computer dell'utente durante la compilazione di una parte di codice intelligente? Quanto è sicuro compilare un pezzo di codice da uno sconosciuto?

    
posta sharptooth 23.06.2015 - 13:27
fonte

13 risposte

32

Dipende.

Questo pezzo di makefile potrebbe cancellare la tua home directory:

all:
    rm -rf ~

Quindi, se hai bisogno di usare uno strumento (come cmake o makefile system), allora non è sicuro. Dipende solo da quanto malintenzionato è il codificatore.

Dall'altro lato, i compilatori sono programmati da persone, quindi hanno dei bug. Quindi, forse potrebbe essere possibile che qualcuno abbia trovato un modo per eseguire codice dannoso durante la compilazione.

Come suggerito nei commenti, se vuoi essere sicuro che non vengano fatte cose divertenti alla tua macchina, usa una macchina virtuale.

    
risposta data 23.06.2015 - 14:52
fonte
23

Sono abbastanza sicuro da qualche parte nel business ci sono alcuni ragazzi intelligenti che hanno già creato un tale hack per una lingua specifica e una versione del compilatore. Il mio posto preferito per cercare qualcosa del genere sarebbe probabilmente il Concorso internazionale Obfuscated C - (non so se c'è qualcosa comparabile per Java). Tuttavia, in realtà, quanto in alto consideri il rischio, supponendo che

  • il richiedente fa un'impressione plausibile su di te: vuole davvero il lavoro nella tua azienda (e non una causa)

  • il tizio non sa quanta revisione viene eseguita sul tuo

  • non sa quale versione del compilatore esatta stai usando

  • lui / lei non sa se usi un ambiente virtuale o un compilatore online, per sicurezza

  • non accetti programmi troppo grandi per essere effettivamente rivisti

  • non compili nulla che ti sembri sospetto

  • non ci sono molte persone al mondo che sanno davvero come realizzare tecnicamente un compito del genere (e googling da solo non ti darà un "quick ref" o tutorial su questo, come hai già scoperto da te stesso).

Quindi, anche se la compilazione non è "totalmente sicura" in teoria, IMHO in realtà il rischio è estremamente basso che il tuo "compilatore viene imbrogliato".

    
risposta data 23.06.2015 - 14:23
fonte
11

Dobbiamo distinguere diversi casi:

  1. Un bug nel compilatore. Come ogni programma complesso, un compilatore potrebbe avere bug e uno di questi bug potrebbe essere sfruttabile.
  2. Un cavallo di Troia. L'autore dell'attacco può farti eseguire codice arbitrario come parte del processo di compilazione. A Makefile , a build.xml , a configure script di shell ecc. Tecnicamente, questo non è dovuto alla compilazione del codice dell'attaccante ma piuttosto alla creazione dell'ambiente di compilazione.
  3. Lingue che consentono l'esecuzione di codice arbitrario in fase di compilazione. Il linguaggio macro di Scala è Scala, il linguaggio macro di Common Lisp è Common Lisp, il linguaggio macro di Template Haskell è Haskell. Scala ha anche plugin per compilatori, che sono di nuovo un codice Scala arbitrario che viene eseguito in fase di compilazione. F # ha provider di tipi.
  4. Lingue che consentono il calcolo di Turing in fase di compilazione. I sistemi di tipo Scala e Haskell sono completi di Turing, come i modelli di C ++. Puoi fare in modo che il compilatore esegua calcoli di Turing arbitrari in fase di compilazione, inclusi, ma non limitati a cicli infiniti. Nota che Turing-complete significa solo che puoi calcolare ogni funzione calcolabile da Turing, non significa che puoi accedere al filesystem o qualcosa del genere. Ma puoi creare un programma che impiegherà infinitamente a compilare.
  5. Tempi di compilazione molto lunghi. Ad esempio, le regole di C # per la risoluzione del sovraccarico sono così complesse che è possibile codificare qualsiasi problema 3-SAT come risoluzione di sovraccarico di C #. 3-SAT è, ovviamente, notoriamente NP-completo. In altre parole, secondo le nostre attuali conoscenze, è impossibile trovare un algoritmo efficiente per la risoluzione del sovraccarico in C #. Non è possibile rendere la compilazione infinitamente lunga, ma non ci vuole un grande programma per rendere la compilazione più lunga della vita dell'universo, che è praticamente la stessa cosa.

# 4. e # 5. al massimo risulterà in un diniego di servizio. In pratica, i compilatori C ++ e Scala limitano la quantità di ricorsione che si può fare, in modo che non sia effettivamente possibile scrivere un ciclo infinito. In Scala, questo è solo un vincolo di implementazione, ma in C ++, è esplicitamente consentito dalle specifiche, credo.

# 2. è tecnicamente fuori dal campo di applicazione della domanda perché la domanda riguardava la compilazione del codice non eseguendolo (OTOH, c'è una domanda filosofica profonda: se il controllo di tipo di un programma Haskell può eseguire una computazione arbitraria di Turing, è una compilazione o un programma in esecuzione?)

# 1. è improbabile. Da un lato, i compilatori di produzione sono molto complessi, quindi la probabilità di bug è alta. D'altra parte, sono rigorosamente testati, dopotutto, gestire gli input mal formati è parte della descrizione del lavoro di un compilatore. Anche se non sono stati testati, saranno comunque bombardati da codice malformato ... basta guardare alcune domande StackOverflow per esempi di ciò che i junk lanciano ai loro compilatori!

Questo ci lascia con 3. Alcuni compilatori possono limitare il tipo di accesso al codice di tempo compilato dal sistema, ma per alcuni casi d'uso, l'accesso completo è inevitabile. Lo scopo dei provider di tipi di F #, ad esempio, è di "falsificare" i tipi sintetici per i dati il cui sistema di tipi non corrisponde a F #, in modo da poter interagire con un servizio web che ha uno schema WSDL in un tipo strongmente tipizzato moda. Tuttavia, per fare ciò, il provider del tipo deve avere accesso alla risorsa dello schema WSDL sul file system o sul web, quindi è necessario avere accesso al filesystem e alla rete.

Quindi, è sicuro? Tecnicamente, no. È rischioso? Non proprio.

    
risposta data 23.06.2015 - 17:18
fonte
3

Non ci dovrebbero essere rischi solo compilare il codice. In theory potrebbe esserci un bug nel compilatore che un hacker intelligente potrebbe sfruttare, ma i suoni sono estremamente improbabili.

Ricorda che building potrebbe non essere sicuro. Ad esempio in C # 'build event' consente di specificare linee di comando arbitrarie da eseguire prima e dopo la costruzione, che è ovviamente pericoloso e molto più facile da sfruttare rispetto a dire overflow del buffer nel codice del compilatore.

    
risposta data 23.06.2015 - 14:06
fonte
3

Invece di speculare, in realtà mi sono preso la briga di fare qualche ricerca su questo argomento prima di rispondere, andando alla risorsa più autorevole che potessi pensare ( Dettagli CVE ). Questo elenco completo di exploit di sicurezza divulgati pubblicamente è probabilmente il migliore che si possa fare per valutare i livelli di minaccia di vari tipi di software.

Non ho avuto il tempo di leggere tutti del materiale disponibile, ovviamente, ma ho selezionato alcuni compilatori, IDE e editor di testo "primari" per ottenere una valutazione delle minacce di esempio . Se sei seriamente intenzionato a eseguire qualsiasi software, dovresti almeno vedere quali minacce ci sono. Si noti inoltre che il software più vecchio è generalmente più bugger di un software più recente, quindi eseguire l'ultima versione di ciò che si sta utilizzando è l'ideale.

In primo luogo, possiamo dare un'occhiata a vari editor di testo. Sembra che i migliori editor siano i più semplici. Vi se stai usando una shell Linux, o Blocco note se sei in Windows. Qualcosa senza capacità di formattazione, senza analisi, solo visualizzazione diretta dei dati e interruzione automatica dell'analisi se un singolo carattere è al di fuori dello schema di codifica corrente. Persino Notepad ++ ha avuto una manciata di vulnerabilità. Evita problemi complessi durante la visualizzazione di file non attendibili.

In secondo luogo, possiamo guardare gli IDE. Se si sceglie di aprire il file in un IDE, è necessario tenere presente che alcuni IDE hanno segnalato bug. Apparentemente Visual Studio ha avuto exploit disponibili attraverso il meccanismo delle estensioni, quindi aprire una soluzione potrebbe essere problematico. Evitare gli IDE evita un'intera classe di problemi tra te e il codice non affidabile. Attaccare con VI sembra molto più sicuro.

In terzo luogo, possiamo guardare i compilatori reali. Ne ho esaminati alcuni, tra cui Adobe, Microsoft, Java e GNU C / C ++, e ho trovato che in generale, compilazione del codice (e persino costruzione , assumendo che non si file) è relativamente sicuro, ma ognuno di questi compilatori ha o ha avuto degli exploit di sicurezza che potrebbero derivare dall'esecuzione effettiva dei binari compilati. In altre parole, non potevano prendere il tuo sistema semplicemente compilando, ma potevano eseguire il codice.

Quindi, in conclusione, supponendo che il metodo di consegna non abbia già dirottato il tuo sistema (ad esempio il tuo client di posta elettronica è stato violato, o l'unità USB che ha rilevato era infetto ...), leggendo il codice sorgente e compilando il codice sorgente è probabilmente sicuro. Effettuando ricerche sul software specifico, è possibile renderlo ancora più sicuro, ad esempio convalidando che il file si trovi nella pagina di codice corretta, ecc. L'esecuzione del codice dovrebbe essere eseguita solo su hardware a cui semplicemente non interessa. Non una VM, ma un intero computer fisicamente diverso senza accesso alla rete e nessun file sensibile o dispositivo esterno. Anche se pensi capisci il codice, una semplice ricerca mostra che anche i compilatori hanno bug che potrebbero consentire a un exploit di overflow del buffer nascosto di nascondersi da dietro ed eseguire codice arbitrario, ma solo se scegli di esegui o esegui il debug del programma. La compilazione effettiva dovrebbe essere sicura.

    
risposta data 23.06.2015 - 23:30
fonte
2

Bene, inizierei con "rivedere il loro codice". Perché è necessario eseguire effettivamente il codice?

A parte questo, ci sono molti compilatori online in cui puoi semplicemente inserire il codice e compilarlo e / o eseguirlo. Puoi renderlo un requisito: si compila in questo e in quello compilatore online.

Ecco un esempio di una pagina con compilatori online: compilatori online

Il codice per la revisione di un colloquio di lavoro non dovrebbe essere così ampio che tu non capisca cosa sta succedendo.

    
risposta data 23.06.2015 - 14:05
fonte
2

Are compilers typically validated to ensure they won't pwn the user machine when compiling some clever piece of code?

In generale sono troppo complessi e spesso scritti usando linguaggi in cui non è pratico dimostrare questa proprietà.

Forse non con questo specifico intento, ma la nozione di compilatori di test fuzz è almeno nota ( LLVM può ora testarlo da solo ). I test intesi a catturare l'input che blocca il compilatore a causa di bug del compilatore saranno tend anche a rivelare difetti sfruttabili.

Ovviamente dovresti esaminare se il compilatore specifico che ti interessa è testato o testato in fuzz per trovare potenziali arresti anomali e se i bug così trovati sono effettivamente corretti. La regola generale è che se ci sono degli arresti anomali peggiori delle eccezioni di memoria non archiviata, quindi senza approfondire ulteriormente i dettagli, è necessario considerare una seria possibilità che possano essere sfruttati in exploit.

How safe is it to compile a piece of code from a stranger?

Sfortunatamente, quanto è lungo un pezzo di corda. In linea di principio l'e-mail potrebbe sfruttare il tuo client di posta, oppure il codice sorgente potrebbe sfruttare l'editor di testo o cppcheck, prima che raggiunga anche il tuo compilatore. Il suggerimento di Sebastian nei commenti di usare un compilatore online è piuttosto buono, ma ovviamente il codice deve essere in una forma che il compilatore accetterà.

Qualsiasi linguaggio o compilatore con possibilità di esecuzione di codice generale in fase di compilazione è ovviamente altamente sospetto. I modelli C ++ sono funzionalmente completi ma non hanno (voluto) accesso al sistema, quindi sono relativamente a basso rischio. BЈовић menziona make come estremamente ad alto rischio (dal momento che sta eseguendo il codice dello straniero, è solo che il codice sembra essere scritto nella lingua make , non in C ++). Se il compilatore eseguirà system , allora sarai sulla stessa barca. Lavoravo con un assemblatore che, se ricordo bene, poteva eseguire un'esecuzione arbitraria del codice in fase di compilazione. Era pensato per calcolare tabelle di ricerca, ma non credo che nulla ti abbia impedito di effettuare chiamate di sistema.

In pratica , se il codice mi sembra OK e penso di capirlo, allora considererei estremamente a basso rischio compilarlo, molto meno rischi di dire "navigare in internet con un browser bloccato ". Faccio cose più rischiose di routine sulla mia macchina per uso generale, ma molte di esse non farei ad esempio all'interno di un laboratorio di virus o su un server critico. Se il codice è di aspetto buffo o evidentemente offuscato, potrei non rischiare di compilarlo perché, a parte il rischio che potrebbe contenere un exploit nascosto nella spazzatura illeggibile, è un codice spazzatura. Il codice subdolo è difficile ma possibile. Il codice subhanded che blocca la macchina tramite un exploit del compilatore deve contenere un payload eseguibile non banale, quindi è estremamente difficile.

Se vuoi approfondire la questione, prova a chiedere alla gente che ospita i compilatori online. Se non è stato fatto a loro allora (salvo il fatto che tu venga all'attenzione dell'NSA o equivalente) puoi ragionevolmente presumere che non ti sarà fatto. Hanno messo un po 'di impegno nell'esecuzione del loro compilatore in una sandbox adeguata, il che potrebbe essere più impegnativo di quanto non siate disposti ad andare, ma potrebbero almeno essere in grado di dirvi con quale frequenza la sandbox le ha risparmiate.

    
risposta data 23.06.2015 - 15:17
fonte
1

Sebbene questo sia generalmente un problema, ritengo che il problema sia inesistente a causa della configurazione.

Il richiedente ti ha inviato un codice sorgente. Come o perché è successo?

Beh, ovviamente ci sono solo tre possibilità:

  1. Hai dato al candidato un incarico per risolvere un particolare problema (ben definito) per valutare le sue capacità.
  2. Il candidato vuole mostrare qualcosa di interessante che ha scritto.
  3. Il richiedente è un coglione o una spia o una persona altrimenti malvagia e in realtà non è interessato ad essere assunto. Tutto ciò che spera è che sei abbastanza stupido da eseguire il suo codice.

Informazioni su 2) e 3)

Il rischio principale è distinguere tra 2) e 3). Le probabilità sono alte che se qualunque cosa abbia scritto vale la pena guardare , è qualcosa che puoi ottenere il codice sorgente online (da una fonte "neutrale") e che potresti già avere familiarità con, oppure è qualcosa che in realtà non vuoi guardare perché violerebbe la proprietà intellettuale di un concorrente (ex datore di lavoro). Quest'ultimo significherebbe che non vorresti assumere quella persona comunque.
Se è possibile ottenere la fonte online, farlo. Se è possibile verificare il contributo del richiedente a un software ben noto (incluso il software proprietario) con il suo nome da qualche parte nei crediti, farlo.
In ogni altro caso, ignora semplicemente ciò che ti ha inviato. O non vale la pena guardare, o illegale, o ad alto rischio.

Informazioni su 1)

Il richiedente ti ha inviato qualcosa perché gli hai dato un incarico. Se hai qualsiasi competenza (che presumo tu faccia!), Allora per un tipico incarico di programmazione (... che hai scelto te stesso!), Sarai in grado di dire se è una soluzione plausibile sembra che potrebbe funzionare osservando il codice sorgente per meno di 30 secondi (più probabilmente 10 secondi).

Se non puoi dire che il programma probabilmente funzionerà (o che cosa sta facendo) entro 30 secondi, colui che l'ha scritto non è il tipo di persona che vuoi assumere, fullstop. Vuoi gente che scrive codice che altri umani possano capire e mantenere. Tu non vuoi qualcuno che sta cercando di diventare intelligente con te, né qualcuno che vince regolarmente il concorso C offuscato. Non importa nemmeno se il programma funziona. Non appena un'altra persona non riesce a capire il codice, non "funziona" mai.
Se il programma sembra funzionare probabilmente, ma trovi qualcosa che sembra "strano" (ad esempio, sequenze di escape Unicode di Java, letterali stringa C ++, cose che assomigliano a trigreph, qualunque sia), considera l'assegnazione come "fail", sposta al prossimo richiedente. Non è necessario includere qualcosa di simile nel 99% di tutti i programmi (e, abbastanza sicuro, non nel tuo compito - dovrei sperare). Quindi se trovi qualcosa di "strano" come questo, il candidato non è qualcuno che vorresti assumere.

Se il codice supera questo primo triage, potresti passare altri 2-3 minuti a guardarlo più a fondo. Se sei ancora soddisfatto di ciò che vedi dopo, puoi eseguirlo tramite un analizzatore statico e compilarlo in una macchina virtuale a un livello di avviso elevato.

Questo dovrebbe far sorgere problemi che potresti aver perso durante la lettura dell'origine (come invocare un comportamento non definito o una riduzione della conversione).
La compilazione ti dirà innanzitutto se il richiedente ha la necessaria diligenza e attenzione ai dettagli, non tanto se ha abilità di programmazione. Proprio come scrivere correttamente il nome del datore di lavoro sulla tua applicazione e come eseguire il controllo ortografico del tuo CV prima di consegnarlo, è buona pratica assicurarti che qualsiasi codice sorgente che conduci compili senza errori (e preferibilmente senza avvisi). Se qualcuno non riesce a farlo, non vuoi assumerlo.

Il rischio di cose malvagie che accadono a questo punto (sfruttando il e del compilatore di compilazione della VM) è neglegabile, visto come hai già eseguito un controllo di plausibilità sul codice. Non succederà.

    
risposta data 24.06.2015 - 12:08
fonte
0

Se la possibilità ti preoccupa, prendi una macchina più vecchia (non la maggior parte di noi ne ha un po 'in giro?), installa la versione corrente di Linux e il compilatore e copia il codice sorgente su di essa, scollega il cavo di rete (o disattiva il WiFi) e compila i file. Se succede qualcosa di brutto, non * influirà su nient'altro.

E per il malware nel Makefile, eseguilo con il flag -n (IIRC, RTMF) per vedere cosa farà senza realmente farlo.

* A meno che, naturalmente, il programmatore non abbia codificato il malware in modo che sia in attesa di una riconnessione, ma in tal caso si a) pulisce la macchina; e b) inoltrare il curriculum del ragazzo alla NSA, perché è sprecato nel mondo commerciale: -)

    
risposta data 23.06.2015 - 19:20
fonte
0

La linea di fondo è che il rischio è . Il rischio è abbastanza basso come altre note, ma c'è un rischio. Ciò significa che devi fare due domande:

  1. Che cosa posso fare per mitigare il rischio?
  2. Il rischio è abbastanza alto che mi dovrebbe interessare?

Il secondo è ciò che hai postulato qui in questa domanda, ma è il focus sbagliato in questo caso particolare. La risposta alla mitigazione del rischio è chiara e facilmente disponibile: non compilare il codice sulla tua macchina . Hai due modi ovvi per compilarlo senza usare il tuo computer:

  1. Utilizza una macchina virtuale (come ha sottolineato @FlorianMargaine nei commenti). Basta fare uno snapshot prima di compilarlo e quindi ripristinare l'istantanea quando hai finito.
  2. Utilizza un servizio ospitato (come un compilatore online).

Questi modi per mitigare il rischio sono così ovvi, economici e facilmente accessibili che non vale la pena spendere un sacco di tempo cercando di analizzare quanto è grande il rischio. Basta fare uno di questi e averne fatto.

    
risposta data 24.06.2015 - 01:06
fonte
0

Visual Studio ti avvisa in realtà se apri un progetto da una posizione non sicura (e, g, scaricata o condivisa in rete).

Un esempio di come questo potrebbe essere sfruttato sarebbe con un progetto WPF: è possibile fare riferimento a classi .NET da XAML e, per fornire IntelliSense, VS carica ed esegue le classi di riferimento in fase di progettazione.

Ciò significa che un utente malintenzionato può rilasciare una .dll dannosa nella directory bin, sostituire il codice sorgente con quello non dannoso e in fase di progettazione, la DLL viene eseguita. Dopo la prima build, ogni traccia del file binario dannoso è scomparsa.

Quindi, anche se tutto il codice fornito è "pulito", il compilatore è privo di bug e, naturalmente, non si esegue mai manualmente alcun codice .EXE, il codice dannoso potrebbe essere comunque eseguito in background. (Per essere al sicuro da quell'attacco specifico, puoi semplicemente assicurarti che non ci siano binari nell'albero delle directory prima di aprire la soluzione: VS ti chiederà quindi di creare la soluzione prima di fornire IntelliSense in fase di progettazione.)

Probabilmente esistono vettori simili con altri linguaggi / sistemi operativi.

    
risposta data 24.06.2015 - 04:15
fonte
0

Leggere il codice sorgente: totalmente sicuro. Compilazione del codice sorgente: totalmente sicuro. Esecuzione di file binari compilati: beh ... dipende.

Compilare è solo il computer che legge il codice sorgente e scrive il suo equivalente in forma binaria. Dopo la compilazione, hai solo 2 documenti: uno leggibile dall'uomo e un altro leggibile dal computer. A meno che tu non abbia il computer a leggere (cioè eseguire) il secondo documento, non accadrà nulla.

    
risposta data 23.06.2015 - 14:06
fonte
-1

Penso che tu sia preoccupato per uno dei due sapori:

  • malware sofisticato, basato sugli exploit : improbabile, soprattutto perché questi sono mirati a hardware e / o software molto specifici e [in base alla tua domanda] probabilmente il tuo aggressore non ha quel livello di conoscenza del sistema.
  • cose che si confondono con il tuo ambiente : direttive di scherzi malevoli (ad esempio eliminazione della directory home) o direttive sconsiderate / incompetenti che cambiano il comportamento del tuo sistema (ad esempio riscrittura delle variabili di ambiente PATH o LIBRARY)

Alcune persone hanno suggerito macchine virtuali o vecchi sistemi, ma offro una soluzione molto più semplice: compila come utente diverso con autorizzazioni ridotte / differenti . Molto più semplice della configurazione di una macchina virtuale o di un computer dedicato.

Se nell'improbabile caso in cui il tuo sistema venga ingaggiato da exploit in fase di compilazione, ripristina dai backup (hai quelli, giusto?).

    
risposta data 23.06.2015 - 23:26
fonte

Leggi altre domande sui tag