2010-08-17 31 views
5

thể trùng lặp:
PHP: How To Disable Dangerous FunctionsLàm thế nào để từ chối việc sử dụng các chức năng PHP nguy hiểm?

Hi, đây là tình hình của tôi: Tôi phải cho khách hàng của tôi nhập mã PHP, nhưng chỉ có các chức năng an toàn như chức năng chuỗi, chức năng ngày, vv Vì vậy, tôi cần danh sách hàm PHP nguy hiểm để loại bỏ chúng bằng cách sử dụng chuỗi thay thế trước khi lưu vào tệp PHP. Bất kì lời đề nghị nào?

Trả lời

7

Hãy quên nó đi. Danh sách trắng chức năng đáng tin cậy là không thể trong php. Ví dụ:

$x = 'e' . str_replace('y', 'x', 'yec'); 
...lots of code... 
$x('format c:'); 

thực tế tùy chọn là

+1

@stereofrog Đó là lý do tôi không giới thiệu nó. Vui lòng chỉnh sửa câu trả lời của tôi để làm cho nó ít khó hiểu hơn. Tôi kinh khủng khi giải thích. – NullUserException

+0

Không nên là "chức năng đáng tin cậy ** danh sách trắng ** là không thể trong PHP"? Bởi vì danh sách đen có thể sử dụng disable_functions. – wimvds

+0

Không nhận thấy rằng, tôi sẽ chỉnh sửa nó sau đó: p. – wimvds

1

Cho người dùng khả năng để nhập mã PHP là thực sự nguy hiểm . Xem xét tất cả các tùy chọn khác trước khi triển khai. Một số loại trình tạo mã PHP. Được truyền cảm hứng trên Trình tạo truy vấn.

Nếu bạn quyết định cho phép mã PHP của khách hàng, tốt hơn nên sử dụng danh sách trắng. Bạn nên sử dụng cụm từ thông dụng để trích xuất các chức năng này từ mã được đăng.

+4

PHP không phải là ngôn ngữ thông thường. – Gumbo

+0

@Gumbo: Vui lòng giải thích điều gì liên quan đến tình huống này? –

+1

@Stegeman Bạn không thể sử dụng cụm từ thông dụng trên ngôn ngữ không thường xuyên. – NullUserException

1

Điều bạn dự kiến ​​làm là cực kỳ khó khăn nếu bạn muốn làm đúng. Tôi sẽ bắt đầu bằng parsing mã php đã nhập, kiểm tra từng chức năng được gọi, không cho phép backticks hoàn toàn, v.v.

Nói cách khác: Nếu bạn muốn cho phép một tập con PHP bạn phải thực hiện lexer của riêng bạn (ngay cả khi PHP cung cấp cho bạn parser ngoài hộp).

2

Theo như tôi biết, bạn chỉ có thể sử dụng một cách tiếp cận đen-list:

Tất nhiên, bạn phải xem xét như thế nào khả thi đó là để duy trì một danh sách cập nhật của tất cả các hàm dựng sẵn được xác định bởi tất cả các phần mở rộng có thể.

Một khả năng tôi có thể nghĩ ra được cách viết một tokenizer đơn giản:

http://es2.php.net/manual/en/function.token-get-all.php

Sau đó bạn có thể kiểm tra các chức năng sử dụng chống lại một danh sách trắng.

Cập nhật: Tôi đã bị ấn tượng sai rằng token_get_all() sẽ xác định cuộc gọi chức năng nhưng thực tế thì không. Tất cả đều là T_STRING s.

+0

1, tôi không hiểu tại sao mọi người có xu hướng phức tạp hơn các vấn đề như thế này, over-compicating nó sẽ không làm cho nó an toàn hơn, dính vào các phương pháp ban đầu như 'disable-functions' và' disable-classes' – RobertPitt

+0

@stereofrog, tôi đã tìm ra ý của bạn (bạn không thực sự nói) và chỉnh sửa bài viết của tôi cho phù hợp. –

+0

Tài liệu mã thông báo của PHP.net khá thiếu. Chúng loại bỏ một số mã thông báo và định nghĩa một vài mã thông báo không chính xác - hoặc thông tin đó hoặc cách sử dụng của chúng bằng 'token_get_all()' và bởi các thông báo lỗi/cảnh báo của PHP khác nhau và chúng sẽ đi theo sau. –

2

Tùy chọn bảo mật và dễ bảo trì nhất sẽ là lập trình một "ngôn ngữ mini" chuyên dụng trong php. Bạn có thể biến nó thành một tập hợp con của php, hoặc làm cho nó trông giống như các công thức Excel, hoặc thậm chí là tạo ra công thức của riêng bạn. Bằng cách này, bạn sẽ luôn có toàn quyền kiểm soát những gì đang xảy ra.

//

chỉ để cho vui, đây là một Lisp nhỏ cho bạn

function lisp($x) { 

    if(is_string($x)) { 
     $re = '~\(([^()]*)\)~'; 
     while(preg_match($re, $x)) 
      $x = preg_replace_callback($re, 'lisp', $x); 
     return trim($x); 
    } 

    $x = preg_split('~\s+~', $x[1]); 
    $e = array_shift($x); 
    if(!$x) 
     return is_numeric($e) ? floatval($e) : $e; 

    switch($e) { 
     case '+': return lisp($x[0]) + lisp($x[1]); 
     case '-': return lisp($x[0]) - lisp($x[1]); 
     case '*': return lisp($x[0]) * lisp($x[1]); 
     case '/': return lisp($x[0])/lisp($x[1]); 

     case 'concat': return lisp($x[0]) . lisp($x[1]); 
    } 

    return function_exists($e) ? 
     call_user_func_array($e, array_map('lisp', $x)) : ''; 
} 

$input = ' 
    (strtolower 
     (concat 
      (strrev olleh) 
      (+ 22 20)))'; 

echo lisp($input); // hello42 

;))

+0

Đó là khả năng * rất nhiều * công việc. – NullUserException

+0

Bạn có thể tạo một lisp-1 động. Bạn không cần phải nói với họ nó là lisp. Hoặc nếu bạn thích, bạn có thể đi lấy LIME cho PHP và triển khai đại số infix, có lẽ bên trong [dấu ngoặc vuông] và tạo một cái gì đó trông giống như TCL. Tại sao nó phải giống như PHP? – Ian

+0

hoặc Bạn có thể viết một trình phân tích cú pháp của một tập hợp con của PHP trong PHP và chỉ chạy các hàm được chọn! : D – naugtur

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