2010-11-17 11 views

Trả lời

0

Tôi giả sử bạn có nghĩa là không cho phép người dùng để duyệt qua thư mục có?

Nếu bạn đang cố gắng ngăn chặn PHP của riêng bạn đi qua thư mục, bạn chỉ cần làm cho php hoạt động bình thường ngay từ đầu.

Những gì bạn cần phải ngừng sử dụng là một tập tin .htaccess sửa đổi ...

Options -Indexes 

(This all giả sử bạn đang nói về người dùng)

+0

MainMa hiểu những gì tôi đang cố gắng đạt được. – Johnny

+0

Anh ấy trả về '$ _GET', rõ ràng anh ta đang cố gắng ngăn chặn một cuộc tấn công tra tấn từ thư mục, vì vậy xin đừng nói" bạn chỉ nên làm cho php hoạt động bình thường ngay từ đầu ". – FluorescentGreen5

93

Vâng, một lựa chọn sẽ được so sánh thực con đường:

$basepath = '/foo/bar/baz/'; 
$realBase = realpath($basepath); 

$userpath = $basepath . $_GET['path']; 
$realUserPath = realpath($userpath); 

if ($realUserPath === false || strpos($realUserPath, $realBase) !== 0) { 
    //Directory Traversal! 
} else { 
    //Good path! 
} 

về cơ bản, realpath() sẽ giải quyết con đường cung cấp cho một con đường vật lý thực tế khó khăn (giải quyết symlink, .., ., /, //, v.v.) Vì vậy, nếu đường dẫn người dùng thực sự không bắt đầu với đường dẫn cơ sở thực, nó đang cố gắng thực hiện một traversal. Lưu ý rằng đầu ra của realpath sẽ không có bất kỳ "thư mục ảo" như . hoặc .. ...

+2

Cách thích hợp duy nhất để làm điều đó .. –

+0

Trình chỉnh sửa: strpos là đa byte an toàn rồi. Giới thiệu giải pháp thay thế mb có thể giới thiệu các lỗ hổng khác ... – ircmaxell

+1

Điều gì về các liên kết tượng trưng? Hoặc nếu tệp chúng tôi muốn kiểm tra chưa tồn tại thì sao? (tức là tạo một tệp mới trong một đường dẫn tiềm năng). – Petah

4

Nó không phải là đủ để kiểm tra các mẫu như ../ hoặc thích. Lấy "../" ví dụ URI mã hóa thành "% 2e% 2e% 2f". Nếu kiểm tra mẫu của bạn xảy ra trước khi giải mã, bạn sẽ bỏ lỡ nỗ lực truyền tải này. Có một số thủ thuật khác mà hacker có thể thực hiện để phá vỡ một bộ kiểm tra mẫu đặc biệt là khi sử dụng các chuỗi được mã hóa.

Tôi đã thành công nhất trong việc ngăn chặn những điều này bằng cách chuẩn hóa bất kỳ chuỗi đường dẫn nào tới đường dẫn tuyệt đối của nó bằng cách sử dụng thông tin như realpath() như ircmaxwell đề xuất. Chỉ sau đó tôi mới bắt đầu kiểm tra các cuộc tấn công traversal bằng cách kết hợp chúng với một đường cơ sở mà tôi đã xác định trước.

12

câu trả lời của ircmaxell không hoàn toàn chính xác. Tôi đã nhìn thấy giải pháp đó trong một số đoạn trích nhưng nó có lỗi liên quan đến đầu ra của realpath(). Chức năng realpath() loại bỏ các dấu phân cách thư mục dấu, vì vậy hình dung hai thư mục tiếp giáp như:

/foo/bar/baz/ 

/foo/bar/baz_baz/ 

Như realpath() sẽ loại bỏ các phân cách thư mục cuối cùng, phương pháp của bạn sẽ quay trở lại "con đường tốt" nếu $_GET['path'] là bằng" ../ Baz_baz" vì nó sẽ là một cái gì đó giống như

strpos("/foo/bar/baz_baz", "/foo/bar/baz") 

Có thể:

$basepath = '/foo/bar/baz/'; 
$realBase = realpath($basepath); 

$userpath = $basepath . $_GET['path']; 
$realUserPath = realpath($userpath); 

if ($realUserPath === false || strcmp($realUserPath, $realBase) !== 0 || strpos($realUserPath, $realBase . DIRECTORY_SEPARATOR) !== 0) { 
    //Directory Traversal! 
} else { 
    //Good path! 
} 
+1

"strcmp" đang làm gì trong mã của bạn? – Andrew

1

Bạn có thể bị cám dỗ để thử và sử dụng regex để loại bỏ tất cả ../s nhưng có một số chức năng đẹp được xây dựng vào PHP mà sẽ làm một công việc tốt hơn nhiều:

$ page = basename (realpath ($ _ GET));

basename - dải ra tất cả các thông tin thư mục từ con đường ví dụ ../pages/about.php sẽ trở về .ph p

đường dẫn thực - trả lại đường dẫn đầy đủ đến tệp, ví dụ: about.php sẽ trở thành /home/www/pages/about.php, nhưng chỉ khi tệp tồn tại.

Kết hợp chúng chỉ trả lại tên tệp nhưng chỉ khi tệp tồn tại.

+0

Tôi không nghĩ rằng điều này ngăn cản việc vượt qua! – Gerfried