2011-02-03 32 views
8

Tôi đã kế thừa máy chủ web chứa mã yêu cầu register_globals để bật. Hầu hết nó là mã tùy chỉnh được viết bởi những người ngẫu nhiên đã đến và đi qua nhiều năm. Tôi đã sửa phần lớn nó trong các kịch bản mà tôi biết, nhưng vấn đề của tôi là tìm ra những cái mà tôi không biết.Tìm tập lệnh PHP yêu cầu register_globals

Tôi đang xem xét viết một ứng dụng để quét qua mọi thư mục trên máy chủ web để xác định các tập lệnh PHP yêu cầu register_globals. Có một chiến lược tốt để làm điều này?

Một phương pháp tôi đã xem xét liên quan đến việc buộc PHP phải báo cáo tất cả các lỗi, thực thi tập lệnh và kiểm tra thông báo biến không xác định. Tôi có thể xây dựng một ứng dụng đọc luồng STDERR cho điều này.

Có phương pháp nào tốt hơn bạn có thể nghĩ đến không?

+3

+1 cho không chỉ đơn giản là sử dụng 'chiết xuất()' để lấy mã crappy làm việc nhưng thực sự sửa chữa nó – ThiefMaster

Trả lời

6

Hầu hết các IDE sẽ hiển thị cho bạn các biến không xác định, ví dụ PHPStorm. Bạn có thể cho phép nó quét tất cả các tệp nguồn của bạn và bạn sẽ được thông báo về các biến không xác định trong tất cả các mã của bạn, whiteout thực sự thực thi nó.

Đây có lẽ là biến thể đơn giản và không đau đớn nhất. Hoặc bạn có thể viết kịch bản của riêng mình bằng cách sử dụng Tokenizer và xác định tất cả T_VARIABLE s, trước đây không được khởi tạo bằng cách sử dụng cấu trúc T_VARIABLE'='expr. Nhưng điều này sẽ dễ bị lỗi hơn. Sử dụng IDE có thể sẽ cho bạn kết quả tốt hơn với ít nỗ lực hơn.

+0

Cảm ơn, tôi không biết về PHPStorm. Tôi sẽ cho rằng một thử sau ngày hôm nay. Tôi cũng có thể xem Tokenizer. Con đường đó có lẽ sẽ quá đắt đối với tôi, nhưng có lẽ tôi sẽ xây dựng một thứ gì đó với nó, và giải phóng nó cho những người khác sử dụng. – Brad

+0

@Brad: Và, bạn có sử dụng PHPStorm không? Hay bạn đã viết một cái gì đó cho mình? – NikiC

+0

Tôi đang đợi PHPStorm để lấy lại cho tôi về giấy phép giáo dục miễn phí của tôi. Họ có một quy trình phê duyệt thủ công. Nhìn qua nó mặc dù, tôi tin rằng sẽ làm công việc, hoặc ít nhất là giúp đỡ đáng kể. – Brad

3

Giả sử tập tin duy nhất luôn luôn sử dụng register_globals được bật hoặc tắt, bạn có thể tạo một danh sách tất cả các tên yếu tố biểu mẫu được gửi đến một kịch bản và sau đó kiểm tra kịch bản này nếu nó được sử dụng $fieldname mà không chứa $_REQUEST['fieldname'] (hoặc $_POST, $_GET mảng).

Phương pháp "kiểm tra thông báo" sẽ là ok nếu bạn có thể đảm bảo mức độ mã rất cao trong khi thực hiện các kiểm tra đó (để đảm bảo bạn không bỏ lỡ bất kỳ thứ gì - các phần chưa được khám phá phải được kiểm tra thủ công).

+0

Vấn đề là, tôi không có cách nào để biết những gì đang được đệ trình lên một kịch bản.Tôi không nói về một vài trang ở đây và ở đó, hoặc thậm chí chứa các ứng dụng ... nhưng hơn 200.000 trang web và các tập lệnh PHP. Rất nhiều kịch bản lệnh này tham khảo các tập lệnh khác và một số tập lệnh xử lý các bài đăng từ các máy chủ/trang web khác. Điểm tốt về các đường dẫn mã có thể. Tôi đã giả định rằng PHP tạo ra một 'E_NOTICE' cho bất cứ nơi nào trong mã, nhưng chỉ nhận ra rằng sẽ không thể cho đến khi nó thực thi mã bằng cách sử dụng tham chiếu. – Brad

2

Trong khi kiểm tra nhật ký của bạn để biết các triệu chứng của tập lệnh được viết bằng cách mong đợi các vars toàn cầu có thể hữu ích, đọc qua mã là cách duy nhất để thực sự thực hiện việc này. Nếu bạn muốn tự động hóa điều này, bạn sẽ cần phải xây dựng hoặc dựa vào một trình thông dịch PHP; nếu không bạn sẽ bỏ lỡ những thứ được lồng vào bên trong các điều kiện, evals tiềm năng, v.v.

+0

Cảm ơn nhận xét của bạn. Tôi đã hy vọng tìm một cách để dựa vào PHP.exe, nhưng như bạn đã chỉ ra, chỉ cần thực thi nó sẽ bỏ lỡ các mục trong các câu lệnh có điều kiện. Nó trông giống như phương pháp thủ công có thể là con đường để đi, nếu một số IDE PHP không thể giúp tôi xác định chúng. – Brad

1

Có một cách để xác định vị trí tập quán của đăng ký hình cầu là các chuỗi trong mã đang chạy. Bạn có thể tạo tập lệnh sau và sử dụng tùy chọn ini PHP auto_prepend_file để thêm mã vào mã hiện tại của mình.

<?php 

class revealGlobalsUsage { 

    public $globalName; 
    public $globalVal; 

    public function __construct($name, $val) 
    { 
     $this->globalName = $name; 
     $this->globalVal = $val; 
    } 

    public function __toString() 
    { 
     $backtrace = debug_backtrace(); 

     // log backtrace here... 

     return $this->globalVal; 
    } 
} 

// overwrite globals that have been set from GET and POST requests 
foreach ($_REQUEST as $name => $val) { 
    // Strings that are cast to integers will fail as there 
    // is no __toString equivalent for integers/bool/float etc. 
    if (is_string($val) && !is_numeric($val)) { 
     $GLOBALS[$name] = new revealGlobalsUsage($name, $val); 
    } 

    // You can log all GET/POST requests here... 
} 

Đối với số nguyên vv bạn sẽ cần phải vá PHP của bạn: https://gist.github.com/ircmaxell/1966809

1

Tôi chạy vào vấn đề này bản thân mình trong một codebase khổng lồ với hàng ngàn tập tin. Lấy cảm hứng từ giải pháp được đăng bởi @sschueller Tôi đã thử nghiệm mã auto_prepend_file này để ghi lại các lần xuất hiện để điều tra. Phương pháp này cũng nên được sử dụng kết hợp với phân tích cú pháp/tokenizing để nắm bắt tất cả các lần xuất hiện.

<?php 

$vars = get_defined_vars(); 

foreach ($vars as $var => $value) { 
    if (in_array($var, array('$_SERVER', '$_REQUEST', '$_GET', '$_POST', '$_COOKIE', '$_SESSION', '$_FILES', '$_ENV'))) { 
     // only examine the local symbols, not superglobals 
     continue; 
    } 

    if (array_key_exists($var, $_REQUEST) && $value == $_REQUEST[$var]) { 
     error_log(sprintf("register_globals reliance detected in %s for variable %s=%s", $_SERVER['SCRIPT_FILENAME'], $var, $value), 3, "/var/tmp/register_globals.log"); 
    } 
} 
Các vấn đề liên quan