Thành thật mà nói, tôi nghĩ tác giả của hàm này không biết XSS và SQL injection là gì hoặc chính xác thì hàm được sử dụng làm gì.
Chỉ để đặt tên cho hai điều kỳ quặc:
- Sử dụng
stripslashes
saumysql_real_escape_string
xóa các dấu gạch chéo được thêm bởimysql_real_escape_string
. -
htmlentities
thay thế các nhân viên trò chuyện<
và>
được sử dụng trongstrip_tags
để xác định các thẻ.
Hơn nữa:Nói chung, các hàm bảo vệ XSS agains không thích hợp để bảo vệ các hàm SQL tiêm vào agains và ngược lại. Bởi vì mỗi ngôn ngữ và ngữ cảnh có các ký tự đặc biệt riêng cần được quan tâm.
Lời khuyên của tôi là tìm hiểu lý do tại sao và làm thế nào có thể tiêm mã cũng như cách bảo vệ chống lại nó. Tìm hiểu các ngôn ngữ bạn đang làm việc, đặc biệt là các ký tự đặc biệt và cách thoát khỏi những ngôn ngữ này.
Chỉnh sửa Dưới đây là một số ví dụ (có thể kỳ lạ):Hãy tưởng tượng bạn cho phép người dùng của mình nhập một số giá trị sẽ được sử dụng làm phân đoạn đường dẫn trong URI mà bạn sử dụng trong một số mã JavaScript trong onclick
giá trị thuộc tính. Vì vậy, bối cảnh ngôn ngữ trông như thế này:
- Giá trị thuộc tính HTML
- Chuỗi JavaScript
- Phân đoạn đường dẫn URI
- Chuỗi JavaScript
Và để làm cho nó thú vị hơn:Bạn đang lưu trữ giá trị đầu vào này trong cơ sở dữ liệu.
Bây giờ để lưu trữ chính xác giá trị đầu vào này vào cơ sở dữ liệu của bạn, bạn chỉ cần sử dụng mã hóa thích hợp cho ngữ cảnh mà bạn sắp chèn giá trị đó vào ngôn ngữ cơ sở dữ liệu của mình (tức là SQL); phần còn lại không thành vấn đề (chưa). Vì bạn muốn chèn nó vào khai báo chuỗi SQL, các ký tự đặc biệt theo ngữ cảnh là các ký tự cho phép bạn thay đổi ngữ cảnh đó. Đối với khai báo chuỗi các ký tự này (đặc biệt) là "
, '
và \
ký tự cần được thoát. Nhưng như đã nêu, các câu lệnh chuẩn bị sẵn sẽ làm được tất cả những công việc đó cho bạn, vì vậy hãy sử dụng chúng.
Bây giờ bạn có giá trị trong cơ sở dữ liệu của mình, chúng tôi muốn xuất chúng đúng cách. Ở đây, chúng tôi tiến hành từ ngữ cảnh trong cùng đến ngữ cảnh ngoài cùng và áp dụng mã hóa thích hợp trong từng ngữ cảnh:
- Đối với phân đoạn đường dẫn URI ngữ cảnh chúng ta cần phải thoát khỏi (ít nhất) tất cả những nhân vật cho phép chúng ta thay đổi bối cảnh đó; trong trường hợp này là
/
(rời khỏi đoạn đường dẫn hiện tại),?
và#
(cả hai đều rời khỏi ngữ cảnh đường dẫn URI). Chúng tôi có thể sử dụngrawurlencode
cho điều này. - Đối với chuỗi JavaScript ngữ cảnh mà chúng ta cần quan tâm đến
"
,'
và\
. Chúng tôi có thể sử dụngjson_encode
cho điều này (nếu có). - Đối với giá trị thuộc tính HTML chúng ta cần quan tâm đến
&
,"
,'
và<
. Chúng tôi có thể sử dụnghtmlspecialchars
cho điều này.
Bây giờ mọi thứ cùng nhau:
'… onclick="'.htmlspecialchars('window.open("http://example.com/'.json_encode(rawurlencode($row['user-input'])).'")').'" …'
Bây giờ nếu $row['user-input']
là "bar/baz"
đầu ra là:
… onclick="window.open("http://example.com/"%22bar%2Fbaz%22"")" …
Nhưng sử dụng tất cả các chức năng này trong những ngữ cảnh này không phải là quá mức cần thiết. Bởi vì mặc dù các bối cảnh có thể có các ký tự đặc biệt giống nhau nhưng chúng có trình tự thoát khác nhau. URI có cái gọi là mã hóa phần trăm, JavaScript có các chuỗi thoát như \"
và HTML có các tham chiếu ký tự như "
. Và việc không chỉ sử dụng một trong các hàm này sẽ cho phép phá vỡ ngữ cảnh.