2011-11-22 32 views
5

tôi đã kịch bản CGI sau:Làm thế nào để untaint gọi hệ thống trong 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 

Khi tôi thực hiện lệnh nó mang lại cho tôi điều này

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

Làm thế nào dòng 10 có thể được cố định?

Trả lời

5

Sử dụng được xây dựng trong grep chức năng, ví dụ:

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

+1. Tại sao sử dụng lệnh hệ thống khi có cách tốt hơn để đạt được kết quả mong muốn. – flesk

3

Việc chuyển đổi -T chỉ cảnh báo bạn về khả năng đầu vào bị nhiễm độc: http://perldoc.perl.org/perlsec.html#Taint-mode

Bạn cần phải untaint đó cho mình, ví dụ như sử dụng

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

Đó không phải là một thử nghiệm rất phức tạp, và có thể không quá an toàn, trừ khi bạn có kiểm soát hoàn toàn các kết quả phù hợp với \w.

EDIT: Đã thay đổi giải pháp tối thiểu của tôi để phản ánh thông tin được đưa ra trong các nhận xét bên dưới.

+1

Hoặc thực hiện một số kết hợp như: my ($ untaint_data) = $ td = ~ m/^ \ s * (\ w +) \ s * $/;. – XoR

+4

Thay thế không làm mất giá trị. Chỉ có nhiệm vụ từ một nhóm biểu thức chính quy được ghi lại ('($ untainted) = $ tainted = ~/(pattern) /;', '$ tainted = ~/(pattern) /; $ untainted = $ 1;') sẽ làm mờ đi một biểu thức. Xem "Rửa và phát hiện dữ liệu bị nhiễm độc" trong ['perlsec'] (http://search.cpan.org/perldoc?perlsec). – mob

+0

@mob: Cảm ơn thông tin. +1. – flesk

3

Tôi nghĩ rằng vấn đề ở đây là toán tử backtick thực thi mã hiệu quả bên ngoài môi trường perl, và do đó hoàn toàn không đáng tin cậy, tức là. bị nhiễm độc.

Bạn có thể, tất nhiên, hãy thử làm một cái gì đó như thế này trước khi dòng vi phạm:

$ENV{"PATH"} = ""; 

Bạn có thể sẽ vẫn nhận được một lỗi từ dòng này:

my $file = "justafile.txt"; 

Để khắc phục điều đó, bạn có thể chỉ cần cung cấp cho nó một đường dẫn tuyệt đối, ví dụ:

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

Bạn gần như chắc chắn sẽ phải đưa ra một đường dẫn tuyệt đối tới lệnh grep mà bạn đang thực hiện với toán tử backtick, vì việc xóa các biến môi trường sẽ làm mất đường dẫn. Nói cách khác làm:

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

Bạn cũng có thể muốn sao chép các giá trị của $ENV trước khi bạn rõ ràng nó, chỉ trong trường hợp bạn cần nó sau này ...

Hope một số điều này giúp!

+2

Lỗi khái niệm: Dữ liệu bị nhiễm độc, không phải hoạt động được thực hiện trên chúng. Xem đầu ra của: 'perl -T -MDevel :: Peek -e'Dump \ @ARGV' "Tôi long trọng thề rằng tôi không được tốt." – daxim

8

Toàn bộ điểm làm mờ là đảm bảo rằng đầu vào không được kiểm soát không thể được cung cấp cho các chức năng không an toàn tiềm ẩn.

Trong trường hợp này, biến số $searchterm của bạn có thể chứa đầu vào không mong muốn có thể cho phép kẻ tấn công thực thi các chương trình tùy ý trên hệ thống của bạn.

Do đó, bạn có cần phải:

  1. untaint biến bằng cách đảm bảo rằng nó phù hợp với một regexp xác định trước (xem @ câu trả lời flesk của), tại thời điểm đó Perl giả định rằng bạn biết những gì bạn đang thực hiện hoặc

  2. không sử dụng backticks (theo câu trả lời của @eugene y).

Nếu bạn đang sử dụng backticks bạn cũng nên xác định đường dẫn đầy đủ để lệnh grep để bạn không phụ thuộc vào $PATH.

Các vấn đề liên quan