2011-11-22 9 views
5

Mam następujący skrypt CGI:Jak untaint wywołanie systemowe w CGI.pm

#!/usr/bin/perl -T 
use strict; 
use warnings; 
use CGI::Carp qw(fatalsToBrowser); 
use CGI qw/:standard/; 
my $query = CGI->new(); 
my $searchterm = param('name'); 

my $file = "justafile.txt"; 
# Begin searching terms and ignoring case 
my @entries = `grep -i \"$searchterm\" $file`; # Line10 
chomp @entries; 
# Do something 

Kiedy wykonać polecenie daje mi to

Insecure dependency in `` while running with -T switch at /foo/cgi-bin/mycode.cgi line 10. 

Jak linia 10 może być stałe?

Odpowiedz

5

pomocą wbudowanego grep funkcji, np:

open my $fh, '<', $file or die $!;  
my @entries = grep /$searchterm/i, <$fh>; 
+4

+1. Po co używać poleceń systemowych, gdy istnieje lepszy sposób osiągnięcia pożądanego rezultatu. – flesk

3

tylko Przełącznik -T ostrzega o możliwym wejściu skażonej: http://perldoc.perl.org/perlsec.html#Taint-mode

trzeba go untaint siebie, na przykład za pomocą

my $safe_searchterm = ""; 
$safe_searchterm .= $_ for $searchterm =~ /\w+/g; 

To nie jest zbyt wyrafinowany test, a może i niezbyt bezpieczny, chyba że masz ompletnie kontrolować co pasuje do \w.

EDYCJA: Zmieniono moje minimalne rozwiązanie, aby odzwierciedlić informacje podane w komentarzach poniżej.

+1

Lub wykonaj niektóre dopasowania, takie jak: my ($ untaint_data) = $ td = ~ m/^ \ s * (\ w +) \ s * $/;. – XoR

+4

Substytucja nie odznacza wartości. Tylko przydział z przechwytywanej grupy wyrażenia regularnego ('($ untainted) = $ tainted = ~/(pattern) /;', '$ tainted = ~/(pattern) /; $ untainted = $ 1;)) odznacza wyrażenie. Zobacz "Pranie i wykrywanie splamionych danych" w ['perlsec'] (http://search.cpan.org/perldoc?perlsec). – mob

+0

@mob: Dzięki za informację. +1. – flesk

3

Myślę, że problem polega na tym, że operator backtick skutecznie wykonuje kod spoza środowiska perl, a zatem całkiem słusznie nie jest zaufany, tj. skażony.

Możesz, oczywiście, spróbować zrobić coś takiego przed linią naruszającego:

$ENV{"PATH"} = ""; 

Będziesz prawdopodobnie nadal pojawia się błąd z tej linii:

my $file = "justafile.txt"; 

to naprawić, ty może dać absolutną ścieżkę, np .:

my $file = "/home/blah/justafile.txt"; 

Prawie na pewno trzeba Podaj bezwzględną ścieżkę do komendy grep, którą wykonujesz również operatorem backtick, ponieważ wyczyszczenie zmiennych środowiskowych spowoduje utratę ścieżki. Innymi słowy zrobić:

# Begin searching terms and ignoring case 
my @entries = `/bin/grep -i \"$searchterm\" $file`; # Line10 

kupili także skopiować wartość $ENV zanim je skasować, tylko w przypadku trzeba to później ...

Nadzieja niektórych to pomaga!

+2

Błąd koncepcyjny: dane są skażone, a nie wykonywane na nich operacje. Zobacz dane wyjściowe: 'perl -T -MDevel :: Peek -e'Dump \ @ARGV '" Uroczyście przyrzekam, że nic nie darzę. " – daxim

8

Cały problem skażenia polega na tym, że niezaznaczone dane wejściowe nie mogą zostać dostarczone potencjalnie niebezpiecznym funkcjom.

W tym przypadku zmienna $searchterm może zawierać nieoczekiwane dane wejściowe, które mogą umożliwić osobie atakującej wykonanie dowolnych programów w systemie.

Dlatego albo trzeba:

  1. untaint zmienna poprzez zapewnienie, że pasuje wstępnie ustalona regexp (patrz @ odpowiedź Flesk za), w którym momencie Perl zakłada, że ​​wiesz co nie można użyć ani cofnięć (na odpowiedź @eugene y).

Jeśli używasz odwrócone, pojedyncze apostrofy należy również podać pełną ścieżkę do polecenia w grep tak, że nie jesteś w zależności od $PATH.

Powiązane problemy