2010-08-25 40 views
5

Tôi hiện đang khôi phục từ một cuộc tấn công XSS khó chịu và nhận ra rằng tôi chưa bao giờ làm vệ sinh đầu vào trên một số biểu mẫu trên trang web của tôi. Tôi đã sử dụng tính năng Tìm kiếm tệp trong Notepad ++ để tìm kiếm $_POST trong tất cả các tệp PHP của tôi và nhận được gần 5.000 kết quả. Bây giờ, tôi thực sự không muốn đi và thêm một cách thủ công strip_tags vào tất cả các kết quả đó, nhưng thay thế tất cả sẽ không thực hiện thủ thuật ... và tôi là một tổng noob khi nói đến những thứ như biểu thức chính quy .

Có cách nào để làm điều này một chút ít tẻ nhạt?

Trả lời

2

bạn có thể đặt điều này trong một tập tin (ví dụ như safe.php)

foreach ($_POST as $key => $value) { 
    $_POST[$key] = is_array($key) ? $_POST[$key]: strip_tags($_POST[$key]); 
} 

Sau đó đặt require_once("safe.php"); trong mỗi mỗi file php của bạn (hoặc một tập tin rằng tất cả các tập tin php của bạn đã bao gồm)
Đó là một hack xấu xí .. nhưng nó có thể tiết kiệm thời gian của bạn.

+0

Tuyệt vời.Điều này thật đúng với gì mà tôi đã tìm kiếm. –

+0

Điều này sẽ không bảo vệ khỏi XSS khi có các trường biểu mẫu có các tên như 'foo [bar]' hoặc 'foo []' mà PHP tự động chuyển thành mảng. – Tgr

+0

@Tgr: vâng, điều này sẽ hoàn toàn thất bại như bạn đã nói, nhưng tôi nghĩ anh ta có ý tưởng tùy chỉnh theo những gì anh ta cần – w00d

6

Hmm, tôi nghĩ array_walk_recursive sẽ làm các trick:

function custom_strip(&$val, $index) { 
    $val = strip_tags($val); 
} 
array_walk_recursive($_POST, 'custom_strip'); 
0

Rất đơn giản. Đặt điều này lên trên mỗi tệp HOẶC của bạn trong một tệp tiêu đề chung được gọi ngay từ đầu mỗi lần:

function mystriptag(&$item) 
{ 
    $item = strip_tags($item); 
} 

array_walk($_POST, mystriptag); 
+0

Điều này sẽ không bảo vệ khỏi XSS khi có các trường mẫu có tên như 'foo [bar]' hoặc 'foo []' mà PHP tự động chuyển thành mảng. – Tgr

18

Chỉ cần sử dụng array_map().

$Clean = array_map('strip_tags', $_POST); 

Hoặc nếu bạn muốn nó trở lại vào biến $_POST:

$_POST = array_map('strip_tags', $_POST); 

Nó có thể là một ý tưởng tốt hơn mặc dù sử dụng một biến khác nhau và thay đổi tất cả xảy ra $_POST để $Clean trong các tập tin của bạn.

0

Bạn có thể chỉ array_mapstrip_tags-$_POST, nhưng nó là đẹp hơn nhiều để viết một chức năng tùy chỉnh cho việc thu thập dữ liệu từ nó:

function post_data($name) { 
    global $post_cache; 
    if (in_array($name, $post_cache)) { 
     return $post_cache[$name]; 
    } 
    $val = $_POST[$name]; 
    if (is_string($val)) { 
     $val = strip_tags($val); 
    } else if (is_array($val)) { 
     $val = array_map('strip_tags', $val); 
    } 
    $post_cache[$name] = $val; 
    return $val; 
} 

Điều này sẽ làm cho mã của bạn dễ đọc hơn (những người khác nhìn vào nó thường sẽ giả rằng $_POST['foo'] là dữ liệu trong trường biểu mẫu foo, không phải đôi khi bạn đã xử lý trước), sẽ không gây ra sự cố với plugin hoặc thư viện để truy cập trực tiếp $ _POST, giúp dễ dàng thêm logic vào $_POST tiền xử lý (unescape khi magic quotes được kích hoạt là một trong những phổ biến) mà không cần săn lùng tất cả các nơi s trong mã của bạn, nơi bạn đã sử dụng dữ liệu POST, và giúp bạn tiết kiệm từ nhức đầu rất lớn khi bạn nhận ra có một vài lĩnh vực POST, nơi bạn cần thẻ HTML. Nói chung, đó là một ý tưởng thực sự tồi tệ để trực tiếp thay đổi bất kỳ siêu dữ liệu nào.

Ngoài ra, tốt hơn là vệ sinh dữ liệu trên đầu ra chứ không phải trên đầu vào. sử dụng khác nhau sẽ đòi hỏi các phương pháp khác nhau, ví dụ, nếu bạn sử dụng

<div class="user_photo"> 
    <img src="<?php echo photo_path($user_id) ?>" alt="<?php echo $user_name ?>" /> 
</div> 

sau đó $user_name là một vector tấn công XSS và strip_tags không giúp chống lại nó ở tất cả; bạn sẽ cần htmlspecialchars. Nếu dữ liệu người dùng được sử dụng làm URL, bạn sẽ cần một phương pháp khác để bảo vệ chống lại các URL javascript: v.v.

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