2014-11-29 9 views
8

In esecuzione perl one-liner dalla riga di comando ha security implications.Possiamo forzare sempre perl utilizzare sempre tre argomenti aperti durante l'esecuzione dalla riga di comando?

Il problema è che le opzioni -n/-p innescare l'operatore diamante <>, che utilizzano due argomenti sotto forma di open, quindi con il nome di file contenenti caratteri speciali, perl non funziona come previsto:

$ perl -pe '' 'uname|' 
Linux 

O più pericoloso quando il nome del file inizia con >, ad esempio >file. In questo caso, il file verrà troncato.

Per aggirare questo problema, siamo in grado di:

  • modulo Usa ARGV::readonly da CPAN.
  • Implementare funzionalità come modulo ARGV::readonly da noi stessi:

perl -pe 'BEGIN{$_.="\0" for @ARGV} ...' ./* 

  • opzione Usa -i, come perl verifica la presenza di file di esisteva prima di elaborarlo.
  • Utilizzare l'opzione -T per attivare la modalità di contaminazione.

Penso che tutte le soluzioni possano risolvere questo problema, ma hanno anche i loro effetti collaterali. Se siamo in grado di forzare perl utilizzare sempre il modulo di argomento di open, sarà una soluzione migliore.

Mi chiedo, lo possiamo fare, forza perl utilizzare sempre il modulo di argomento open?

Nota

La questione si applicano solo per il caso in cui l'esecuzione perl uno liners da linea di comando, perché (ovviamente) si può sempre usare tre formano argomento di open in script Perl.

+0

capisco il tuo punto, ma non vedo come l'output di 'perl -pe '' 'uname |'' non è quello che la gente si aspetta, e avrei pensato che il pericolo maggiore è 'perl -pe" 1 ""> myfile "'. Penso che tutti i file di input da riga di comando dovrebbero essere aperti usando la forma a tre parametri con il secondo parametro sempre impostato su '<'. – Borodin

+0

@Borodin: ''uname |'' è un nome file valido, invece di aprirlo, il comando 'uname' viene eseguito e collegato a' perl'. E immaginiamo che il comando possa essere 'rm -rf $ HOME'. Sì, tranne per l'opzione '-i', quando si desidera modificare il file sul posto. Puoi leggere il link che ho fornito nella mia domanda per maggiori dettagli. – cuonglm

risposta

2

Nella mia risposta precedente, ho ipotizzato che la magia di filehandle ARGV emulasse l'argomento a 2 argomenti aperto ma in realtà non passava attraverso la funzione integrata di Perl open. Quindi l'ho approfondito e penso di aver trovato una soluzione a questo problema.

La funzione Perl_nextargv in doio.c è dove perl esegue l'I/O attorno al filehandle ARGV.

All'interno del ciclo while di quella funzione, esistono due tipi di chiamate per aprire i filehandle. Quando LIKELY(PL_inplace) è true (vale a dire, quando perl viene eseguito con lo switch -i), la chiamata è do_open_raw. Se LIKELY(PL_inplace) è falso, la chiamata è do_open6. Quest'ultima chiamata è in grado di aprire pipe a comandi esterni, che è in generale ciò che l'OP non desidera.

Quindi, ecco la soluzione: nel file di origine doio.c, sostituire quelli do_open6 chiamata (s) in Perl_nextargv con do_open_raw e ricostruire perl dai sorgenti. Per perl-5.22.0, il codice originale sembra

if (LIKELY(!PL_inplace)) { 
     if (nomagicopen 
       ? do_open6(gv, "<", 1, NULL, &GvSV(gv), 1) 
       : do_open6(gv, PL_oldname, oldlen, NULL, NULL, 0) 
      ) { 
      return IoIFP(GvIOp(gv)); 
     } 
    } 

e il codice alterato sembra

if (LIKELY(!PL_inplace)) { 
     if (do_open_raw(gv, PL_oldname, oldlen, O_RDONLY, 0)) { 
      return IoIFP(GvIOp(gv)); 
     } 
    } 

(il parametro nomagicopen è vero quando si utilizza the new <<>> syntax from perl 5.22.0. Credo che potremmo semplicemente impostarlo a true nella parte superiore della funzione e non è necessario modificare altro, ma la modifica di cui sopra è una soluzione generale per perl precedente).

uscita

Esempio:

$ original-perl -pe '' a b c 'date|' 
Can't open a: No such file or directory 
Can't open b: No such file or directory. 
Can't open c: No such file or directory. 
Mon Sep 21 18:41:37 PDT 2015 

$ modified-perl -pe '' a b c 'date|' 
Can't open a: No such file or directory. 
Can't open b: No such file or directory. 
Can't open c: No such file or directory. 
Can't open date|: No such file or directory. 
+0

+1 per l'hacking della sorgente 'perl'. Mi chiedo perché 'perl 'abbia ancora usato due argomenti forma? La modifica di '<>' si comporta come '<<>>' interrompe la retrocompatibilità? – cuonglm

+0

È Perl, quindi sì, ci sono probabilmente degli script là fuori che dipendono da questo comportamento. Forse un giorno avremo le opzioni '-N' e' -P' come '-n' e' -p' che avvolgono lo script in 'while (<<>>) {...}'. – mob

1

Si potrebbe utilizzare in combinazione con ARGV::readonlyalias:

alias perl='perl -MARGV::readonly' 

O semplicemente educare le persone che stanno digitando i oneliners "cattivi".

+0

mi dispiace, l'ho corretto. –

+1

Oppure è possibile aggiungere '-MARGV :: readonly' alla variabile di ambiente' PERL5OPT' – mob

4

Probabilmente si desidera eseguire questa operazione solo per one-liner (utilizzando lo switch -e), quindi è necessario personalizzare lo ARGV::readonly a tale scopo.

package Sanitize::ARGV; 
if ($0 eq '-e') { 
    @ARGV = map { # from ARGV::readonly 
     s/^(\s+)/.\/$1/; 
     s/^/< /; 
     $_.qq/\0/; 
    } @ARGV; 
} 
1; 

Per forzare l'utilizzo di questo pacchetto a livello di sistema, è possibile utilizzare un alias come Patrick J.S.suggerisce

alias perl='perl -MSanitize::ARGV' 

o impostare un livello di sistema PERL5OPT variabile

PERL5OPT="-MSanitize::ARGV" 

E se si vuole essere più paranoico, nascondere il perl di sistema (rinominarlo in qualcosa di incomprensibile) e sostituirlo con un wrapper

#!/bin/bash 
THE_REAL_PERL=/usr/bin/glorbqweroinuerqwer 
$THE_REAL_PERL -MSanitize::ARGV "[email protected]" 

L'avvolgitore shell comunque rispettare le personalizzazioni utente a PERL5OPT

Nel caso generale, è possibile utilizzare il meccanismo CORE::GLOBAL per sovrascrivere la funzione integrata open, ad es.

package SafeOpen; 
use Carp; 
BEGIN { 
    *CORE::GLOBAL::open = sub (*;[email protected]) { 
     goto &CORE::open if @_ > 2; 
     Carp::cluck("OH MY GOD USING THE TWO-ARG open ARE YOU LIKE INSANE?"); 
     return CORE::open($_[0], '<', $_[1] // $_[0]); 
    }; 
} 
1; 

e quando questo modulo è in uso si cattura qualcuno nell'atto di usare un 2-Arg open chiamata. Sfortunatamente, penso che il meccanismo della magia del filehandle ARGV lo ignori, quindi non è ancora d'aiuto con i nomi buffi sulla riga di comando in una riga singola.

+0

Sì, conosco i metodi per verificare l'integrità '@ ARGV'. La mia domanda riguarda c'è comunque per forzare 'perl' a usare tre argomenti aperti? – cuonglm

+0

Puoi impostare un sotto 'CORE :: GLOBAL :: open' (e l'ho provato per vedere se avrebbe risolto il tuo problema), ma penso che il meccanismo magico 'ARGV' lo ignori. – mob

+0

Bene, questo è quello che ho menzionato nella mia domanda. E immagino che impostare 'CORE :: GLOBAL :: open' non abbia effetti. Da quando l'opzione '-n' e' -p' attivano l'operatore diamond '<>', che usa la forma a due argomenti di 'open'. – cuonglm

Problemi correlati