2010-08-28 11 views

Odpowiedz

8

Myślę, że wprowadzasz zamieszanie w dwa problemy bezpieczeństwa: SQL injection i cross-site scripting (XSS).

Strona internetowa jest podatna na wstrzyknięcia SQL, gdy niewłaściwie odkażone dane wejściowe użytkownika są używane w zapytaniu SQL wysyłanym do bazy danych SQL.Ten kod, na przykład, wprowadza podatności SQL injection:

mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . $_POST['postmessage'] . "')"); 

Ten problem można łatwo rozwiązać, uciekając wejście użytkownika z funkcji takich jak mysql_real_escape_string:

mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string($_POST['postmessage']) . "')"); 

To wszystko, co trzeba zrobić , ale trudną częścią jest pamiętanie, aby zrobić to dla każdego elementu danych wejściowych użytkownika, który jest używany w instrukcji SQL.

Strona internetowa jest podatna na ataki typu cross-site scripting, gdy dane wejściowe użytkownika są używane w kodzie HTML wysyłanym do klienta. Ten kod, na przykład, wprowadza lukę XSS:

echo "<div class='postmessage'>" . $_POST['postmessage'] . "</div>"; 

XSS luka jest ustalona przez ucieczce wprowadzanych przez użytkownika z funkcji takich jak htmlspecialchars:

echo "<div class='postmessage'>" . htmlspecialchars($_POST['postmessage']) . "</div>"; 

Ponownie, jest to łatwe do zrobienia, ale łatwo zapomnieć.

Zazwyczaj dane wprowadzone przez użytkownika do bazy danych, która ma być używana do późniejszego wysyłania kodu HTML, są zapisywane w niezmienionej postaci. Oznacza to, że użyto tylko mysql_real_escape_string. Jednakże, można uniknąć wprowadzania danych przez użytkownika w celu zapobiegania XSS, a następnie uciec ciąg XSS bezpieczny aby zapobiec SQL injection:

mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string(htmlspecialchars($_POST['postmessage'])) . "')"); 

Korzyścią jest to, że nie trzeba pamiętać, aby uciec wartości z bazy danych z htmlspecialchars przed zapisaniem ich w HTML. Wadą jest to, że niektóre wartości mogą wymagać ucieczki z różnymi funkcjami. Na przykład nazwa użytkownika prawdopodobnie uciekłaby pod numer htmlspecialchars, ale "postmessage" może pozwolić na BBcode, Markdown lub podzbiór HTML. Jeśli unikniesz wszystkich danych wejściowych, aby zapobiec XSS, musisz usunąć wartości z bazy danych za pomocą np. htmlspecialchars_decode.

Jednym z problemów jest to, że unescaping ten uciekł łańcuch nie zawsze zwraca oryginalny łańcuch (unescape(escape($orig)) niekoniecznie jest taka sama jak $orig). Nawet z htmlspecialchars i htmlspecialchars_decode, użycie innego stylu cytowania spowoduje ten problem. Innym przykładem jest to, że jeśli użyto strip_tags, to informacja jest usuwana nieodwracalnie; nie będzie można cofnąć strip_tags. Tak więc, wielu programistów decyduje się na użycie mysql_real_escape_string tylko do zapisania wartości do bazy danych i htmlspecialchars (lub cokolwiek innego), aby przygotować ciąg znaków z bazy danych do użycia w HTML.

+0

Czy nie byłoby lepiej użyć przygotowanych oświadczeń, czystszych do obejrzenia i być może łatwiejszych w użyciu, gdy już się z tym uporasz. –

+1

@Xeross: Zdecydowanie. Przygotowane instrukcje ułatwiają konsekwentne unikanie danych wprowadzanych przez użytkownika. Jednak w odpowiedzi na pytanie OP chciałem się upewnić, że zrozumiał on powody używania 'mysql_real_escape_string' (lub jakiegoś mechanizmu ucieczki DB) i' htmlentities' (lub jakiegoś mechanizmu ucieczki XSS). –

21

mysql_real_escape_string() jest jedyną metodą trzeba tutaj.
Przed wstawieniem danych do bazy danych nie należy wykonywać htmlentities() ani urlencode(). Te metody są zwykle kodowane podczas renderowania widoku, który oferujesz swoim użytkownikom.

Lepszym sposobem uniknięcia iniekcji SQL jest użycie przygotowanych oświadczeń .


Zasoby:

na ten sam temat:

+0

+1 dla przygotowanych wyciągów. Mogą również pomóc w osiągnięciu wydajności w odpowiednich sytuacjach. –

+0

+1 dla przygotowanych oświadczeń –

+0

<3 Przygotowane oświadczenia :) –

1

Powinieneś również upewnić się, że używasz "w miejscu, w którym wstawiasz swój kod.

Na przykład, jeśli nie

$_POST['userid'] = mysql_real_escape_string($_POST['userid']); 
mysql_query('SELECT * FROM user WHERE userid = '. $_POST['userid']); 

mysql_real_escape_string nie pomoże nic. To dlatego, że $ _POST ['userid'] nie jest otoczony przez '.

więc należy zrobić

$_POST['userid'] = mysql_real_escape_string($_POST['userid']); 
mysql_query('SELET * FROM user WHERE userid = \''. $_POST['userid'] .'\''); 

zamiast.

Używanie mysql_real_escape_string na zmiennych nie oznacza automatycznie, że są one bezpieczne w każdym zapytaniu.

Innym podejściem byłoby użycie Przygotowanych instrukcji.

1

Tak, ale istnieje powód, dla którego nie należy używać mysql_real_escape_string(). Po pierwsze, jest to rodzaj bólu. Po drugie, musisz pamiętać o używaniu go za każdym razem. Po trzecie, sprawia, że ​​twój kod jest brzydki. Po czwarte, musisz pamiętać, aby zacytować swoje struny. Po piąte, trudniej jest wstawiać w ten sposób bloby do bazy danych.

Nauka PDO poprawi Twoje życie na dłuższą metę. Trudniej jest się nauczyć niż po prostu używać mysql_real_escape_string(), ale długoterminowe korzyści przewyższają niedogodności związane z krzywą uczenia się.

Powiązane problemy