2010-04-04 24 views
11

Tôi đang cố gắng để bảo vệ bản thân mình từ sql injection và đang sử dụng:Giải mã mysql_real_escape_string() cho outputting HTML

mysql_real_escape_string($string); 

Khi đăng HTML nó trông giống như sau:

<span class="\&quot;className\&quot;"> 
<p class="\&quot;pClass\&quot;" id="\&quot;pId\&quot;"></p> 
</span> 

Tôi không chắc chắn bao nhiêu biến thể khác real_escape_string thêm vào vì vậy không muốn chỉ thay thế một vài và bỏ lỡ những người khác ... Làm cách nào để "giải mã" điều này trở lại thành HTML được định dạng chính xác, như sau:

html_entity_decode(stripslashes($string)); 
+0

Nếu người dùng có thể kiểm soát chuỗi $, thì đây là lỗ hổng XSS. – rook

Trả lời

12

Các mysql_real_escape_string() thủ công trang cho bạn biết nhân vật đang trốn:

mysql_real_escape_string() gọi MySQL của thư viện chức năng mysql_real_escape_string, mà prepends backslashes đến ký tự sau: \ x00 \ n, \ r, \, ', "và \ x1a.

Bạn có thể đảo ngược thành công việc thoát bằng cách thay thế các ký tự thoát này bằng các biểu mẫu chưa thoát.

mysql_real_escape_string() không được sử dụng để khử trùng HTML mặc dù ... không có lý do gì để sử dụng nó trước khi xuất dữ liệu trang web. Nó chỉ nên được sử dụng trên dữ liệu mà bạn sắp đưa vào cơ sở dữ liệu. Quá trình thanh trùng của bạn sẽ giống như thế này:

Input

  1. Chấp nhận người dùng nhập vào từ một hình thức hoặc HTTP yêu cầu
  2. Tạo truy vấn cơ sở dữ liệu sử dụng mysql_real_escape_string()

Output

  1. Fetch dữ liệu ra khỏi cơ sở dữ liệu
  2. Chạy bất kỳ dữ liệu người dùng định nghĩa thông qua htmlspecialchars() trước khi in

Sử dụng một trình điều khiển cơ sở dữ liệu khác nhau như MySQLi hoặc PDO sẽ cho phép bạn sử dụng chuẩn bị phát biểu, mà chăm sóc thoát hầu hết các yếu tố đầu vào cho bạn. Tuy nhiên, nếu bạn không thể chuyển đổi hoặc tận dụng lợi thế của chúng, thì chắc chắn sử dụng mysql_real_escape_string() ... chỉ sử dụng nó trước khi chèn dữ liệu.

+0

Tôi muốn giới thiệu các câu lệnh chuẩn bị (ví dụ: http://www.php.net/manual/en/class.pdostatement.php) trên 'mysql_real_escape_string'. Và 'htmlspecialchars' không phải lúc nào cũng là lựa chọn đúng đắn. Đôi khi danh sách trắng là một lựa chọn tốt hơn. –

+0

Lưu ý! Nếu bạn có 'magic_quotes', ngay cả với PDO, bạn sẽ cần sử dụng 'stripslashes()' trước khi đặt chuỗi vào cơ sở dữ liệu để tránh các dấu gạch chéo kép. – mrserge

+0

Nhưng không có hệ thống hiện đại nào có magic_quotes trên. Tính năng đó đã bị ngừng sử dụng trong nhiều năm. –

7

Bạn đã làm mọi thứ rối tung lên.

mysql_real_escape_string không cần bất kỳ giải mã nào.

nếu bạn lấy lại dữ liệu của mình bằng dấu gạch chéo, điều đó có nghĩa là đã thoát hai lần. Và thay vì tước bỏ các dấu gạch chéo thêm, bạn không nên thêm chúng.

Chưa kể rằng bất cứ điều gì thoát được lỗi thời và bạn nên

sử dụng báo cáo

thay vì bất cứ điều gì chuỗi thoát chuẩn bị.

Vì vậy, không bao giờ thoát, không bao giờ giải mã.
Sự cố được giải quyết.

+0

$ query = "bảng INSERT INTO SET html = '$ html'"; không phải là SQL tiêu chuẩn, bạn nên sử dụng bảng INSERT INTO (html) VALUES ('content'); Điều này làm việc trong tất cả các cơ sở dữ liệu, không chỉ MySQL. –

+0

@Frank Heikens Nhưng tôi đang làm việc với mysql. Và tôi sử dụng rất nhiều tính năng cụ thể của mysql. Hãy nói với tôi không sử dụng PHP vì nó không được hỗ trợ ở khắp mọi nơi. Thật là một bình luận vô nghĩa! –

7

mysql_real_escape_string được sử dụng để ngăn SQL injection khi lưu trữ dữ liệu do người dùng cung cấp vào cơ sở dữ liệu, nhưng phương pháp tốt hơn là sử dụng dữ liệu ràng buộc sử dụng PDO (ví dụ). Tôi luôn khuyên bạn nên sử dụng nó thay vì làm rối tung thoát.

Điều đó đang được nói, liên quan đến câu hỏi của bạn về cách hiển thị sau đó - sau khi dữ liệu được lưu trữ, khi bạn truy xuất dữ liệu hoàn chỉnh và hợp lệ mà không cần phải "không thoát". Trừ khi bạn thêm các trình tự thoát của riêng bạn, vì vậy xin đừng làm điều đó.

-2

Tôi nghĩ rằng một số câu trả lời khác bỏ lỡ vấn đề rõ ràng ...

Bạn đang sử dụng mysql_real_escape_string về nội dung đầu vào (như bạn nên nếu không sử dụng chuẩn bị phát biểu).

Sự cố của bạn là với đầu ra.

Vấn đề hiện tại là bạn đang gọi html_entity_decode. Chỉ stripslashes là tất cả những gì bạn cần để khôi phục lại văn bản gốc. html_entity_decode là những gì đang rối tung lên dấu ngoặc kép của bạn, vv, vì nó đang thay đổi chúng. Bạn thực sự muốn xuất ra html, không chỉ văn bản thuần túy (đó là khi bạn sẽ sử dụng html_entities, v.v.). Bạn đang giải mã một cái gì đó bạn muốn mã hóa.

Nếu bạn chỉ muốn phiên bản văn bản hiển thị, bạn có thể sử dụng các thực thể. Nếu bạn đang lo lắng về thẻ xấu, hãy sử dụng thẻ thoát và chỉ cho phép các thẻ bạn muốn (chẳng hạn như b, i, v.v.).

Cuối cùng, hãy nhớ mã hóa và giải mã theo thứ tự thích hợp. nếu bạn chạy mysql_real_escape_String (htmlentities ($ str)), thì bạn cần chạy html_entity_decode (stripslashes ($ str)). Thứ tự của các hoạt động quan trọng.

CẬP NHẬT: Tôi không nhận ra rằng html_entity_decode cũng loại bỏ các dấu gạch chéo. Nó không được ghi chép rõ ràng trên trang đó, và tôi chưa bao giờ bắt được nó. Tôi vẫn sẽ tự động chạy nó mặc dù, như hầu hết html mà tôi trình bày tôi muốn để lại như là thực thể, và ngay cả khi tôi không, tôi muốn đưa ra quyết định đó bên ngoài lớp db của tôi, trên cơ sở từng trường hợp. Bằng cách đó, tôi biết các dấu gạch chéo đã biến mất.

Dường như áp phích gốc đang chạy htmlentities (hoặc chương trình nhập liệu của anh ấy, như tinymce đang làm việc đó cho anh ấy) và anh ấy muốn chuyển nội dung trở lại nội dung. Vì vậy, html_entity_decode ($ Str) nên là tất cả những gì được yêu cầu.

+1

bạn đã sai. anh ta không cần phải tước các dấu gạch chéo. Ne cần phải thêm nó đúng cách. Do chữa bệnh decease, không triệu chứng. –

+0

Anh ấy cần phải cắt các dấu gạch chéo ra, khi anh ta chạy chuỗi thoát trên nó trước tiên. Anh ta mã hóa nó, bây giờ anh ta cần giải mã nó để loại bỏ các dấu gạch chéo ở đầu ra. Do đó \ xuất hiện trước ". – Cryophallion

+1

Bạn không biết cách hoạt động của nó. Vì vậy, tốt hơn cấm bản thân bạn trả lời cho đến khi bạn tìm hiểu một số. Không tước cần thiết. Hãy thử nó cho mình. –

0

Không chắc những gì đang xảy ra với định dạng như tôi có thể nhìn thấy nó nhưng hình thức html của bạn

<span class="\&quot;className\&quot;"> 
<p class="\&quot;pClass\&quot;" id="\&quot;pId\&quot;"></p> 
</span> 

nên đơn giản;

<span class="className"> 
<p class="pClass" id="pId"></p> 
</span> 

Khi bạn lấy lại, trước khi bạn đưa nó vào cơ sở dữ liệu, bạn thoát khỏi nó bằng cách sử dụng mysql_real_escape_string() để đảm bảo bạn không bị tấn công tiêm sql.

Do đó, bạn đang thoát các giá trị sẵn sàng để đặt văn bản tiếp theo.

Khi bạn lấy nó ra khỏi cơ sở dữ liệu (hoặc hiển thị BẤT K of của nó cho người dùng dưới dạng html) thì bạn thoát nó một lần nữa đã sẵn sàng cho địa điểm đó tiếp theo (html) với htmlentities() v.v. Tấn công XSS.

Điều này tạo thành phần EO của câu thần chú FIEO, Đầu vào bộ lọc, Đầu ra thoát, mà bạn nên xăm ở bên trong mí mắt của mình.

+0

Bạn có chắc chắn muốn biểu mẫu này được thoát không? Tôi đang nghi ngờ sâu sắc. Nếu ai đó sử dụng định dạng HTML, họ thường muốn nó hoạt động, không phải là thẻ hiển thị. –

-1

Tôi đã tự hỏi tại sao thói quen này không có thói quen giải mã đi kèm. Nó có thể được giải thích bởi MySQL theo cùng một cách như thể nó không được thoát. Bạn nhận được kết quả không thoát khi bạn thực hiện $row=mysql_fetch_array($res, MYSQL_ASSOC)';

0

Vâng, tôi đã sử dụng cách này theo cách cũ và cho đến nay tôi không thể thấy bất kỳ điều gì sai với cách tiếp cận của mình. Rõ ràng đó là một chút thô nhưng nó được công việc làm:

function mysql_unreal_escape_string($string) { 
    $characters = array('x00', 'n', 'r', '\\', '\'', '"','x1a'); 
    $o_chars = array("\x00", "\n", "\r", "\\", "'", "\"", "\x1a"); 
    for ($i = 0; $i < strlen($string); $i++) { 
     if (substr($string, $i, 1) == '\\') { 
      foreach ($characters as $index => $char) { 
       if ($i <= strlen($string) - strlen($char) && substr($string, $i + 1, strlen($char)) == $char) { 
        $string = substr_replace($string, $o_chars[$index], $i, strlen($char) + 1); 
        break; 
       } 
      } 
     } 
    } 
    return $string; 
} 

Điều này nên bao gồm hầu hết các trường hợp.

-1

Thậm chí nếu đó là câu hỏi cũ ... Tôi đã có cùng một vấn đề so với Peter Craig. Trong thực tế, tôi đã đối phó với một CMS cũ. Để ngăn chặn SQL Injection, tất cả các giá trị $ _POST và $ _GET là "sql-escaped". Thật không may này được thực hiện ở một điểm trung tâm vì vậy tất cả các mô-đun của bạn đang nhận được tất cả các dữ liệu sql-thoát! Trong một số trường hợp, bạn muốn hiển thị trực tiếp những dữ liệu này, do đó bạn phải đối mặt với một vấn đề: làm thế nào để hiển thị một chuỗi thoát sql mà không gettng nó từ DB? Câu trả lời là: stripcslashes sử dụng (KHÔNG stripslashes !!)

http://php.net/manual/en/function.stripcslashes.php

-1

sử dụng chức năng sau để loại bỏ dấu gạch chéo trong khi hiển thị trên trang HTML:

stripslashes();

ví dụ: $ html = stripslashes ($ html); HOẶC $ html = stripslashes ($ row ["fieldname"]);

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