Czy to wystarczy, aby uniknąć zastrzyku SQL?Czy jestem bezpieczny od wstrzyknięcia mysql?
mysql_real_escape_string(htmlentities (urlencode($_POST['postmessage'])));
Czy to wystarczy, aby uniknąć zastrzyku SQL?Czy jestem bezpieczny od wstrzyknięcia mysql?
mysql_real_escape_string(htmlentities (urlencode($_POST['postmessage'])));
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.
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:
+1 dla przygotowanych wyciągów. Mogą również pomóc w osiągnięciu wydajności w odpowiednich sytuacjach. –
+1 dla przygotowanych oświadczeń –
<3 Przygotowane oświadczenia :) –
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.
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ę.
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. –
@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). –