Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: SQL Injection/Insertion
Forum PHP.pl > Forum > PHP
Stron: 1, 2, 3, 4, 5, 6, 7, 8, 9
kilas88
Cytat(japolak @ 28.07.2011, 20:29:43 ) *
chciałbym sie dowiedzieć jakie jest/są w "miarę" skuteczne zabezpieczenie/a przed tym atakiem

szukalem na tym forum... i co któryś post przekierowujecie do tego.. .

poczytałem kilka stron tego tematu.. i jednym słowem tu jest wielka sieczka:

kazdy sie "przekrzykuje" tak jak tirowcy stojący w korku przekrzykują osobówki mijające ich bokiem..

rozwiązując dany problem mamy mnóstwo rozwiązań i w zależności od problemu stosujemy odpowiednie ku temu rozwiązanie - jeden napisze swój algorytm, ktoś inny usiądzie nad tym samym problemem i wypluje zupełnie inny kod. zmierzam więc do tego, że nie ma "złotego" rozwiązania, inaczej dawno temu ktoś napisałby program, który zastąpiłby programistów i pisał programy za nich wink.gif
pyro
Cytat(japolak @ 28.07.2011, 20:29:43 ) *
chciałbym sie dowiedzieć jakie jest/są w "miarę" skuteczne zabezpieczenie/a przed tym atakiem

szukalem na tym forum... i co któryś post przekierowujecie do tego.. .

poczytałem kilka stron tego tematu.. i jednym słowem tu jest wielka sieczka:

kazdy sie "przekrzykuje" tak jak tirowcy stojący w korku przekrzykują osobówki mijające ich bokiem..


skoro temat jest tematem tak ważnym może "moderacja" by podsumowała go i napisała w pierwszym poście na co tak naprawdę trzeba zwrócić uwagę..


Zobacz na phpmagazyn.pl
gargamel
Nie znalazłem w temacie, więc pozwolę sobie dodać przykładowe użycie PDO.
Prosty skrypt, więc myślę że pozwoli zrozumieć o co w tym chodzi, osobie która zaczyna z nim zabawę:
  1. $conn = new PDO("mysql:host=$host;dbname=$db", $user, $pass);
  2.  
  3. $sql = "SELECT user_id, user_name, user_email FROM users WHERE login = :login AND password = :password ;";
  4.  
  5. $q = $conn -> prepare( $sql );
  6.  
  7. $q -> execute(
  8. ':login' => $_POST['login'],
  9. ':password' => $_POST['password']
  10. )
  11. );
  12.  
  13. if( $q -> rowCount() > 0 ){
  14.  
  15. while( $r = $q -> fetch() ){
  16. echo 'Witaj ' . $r['user_name'] .'. Twoje id to: ' . $r['user_id'] . ', Twój email to: '. $r['user_email'];
  17. }
  18.  
  19. }
  20. else{
  21. echo 'Nie znaleziono użytkownika!';
  22. }
Inscure
Byłby ktoś tak miły, żeby streścić cały ten temat do jednego posta wybierając najlepsze i najskuteczniejsze metody, przy okazji usuwając posty wprowadzające w błąd?

Z góry dzięki wink.gif
Noidea
@Inscure
W celu zabezpieczenia się przed atakami SQL Injection używa się prepared statements. Wszystkie powyższe posty które mówią co innego wprowadzają w błąd. wink.gif


Bardziej streścić się chyba nie da
skowron-line
A pro po tematu znalazłem dziś na dzone.com
http://php.dzone.com/news/hardening-php-sql-injection
thek
@Noidea: nie spłycaj tak, bo nie masz do końca racji. Zabezpieczanie przed sql injection jest zazwyczaj kilkupoziomowe i powiedzenie "używaj prepared statements a bedzie cacy" jest po prostu ignorancją. Ono zabezpiecza, ale nie wszędzie jest możliwe do zastosowania to raz, a dwa, że prawidłowe zabezpieczenia działają jeszcze zanim cokolwiek do bazy zaczniesz wrzucać i obejmują filtrowanie danych oraz ich walidację.
Noidea
PDO jest dostępne w PHP gdzieś od wersji 5.1. MySQLi chyba jeszcze dłużej. Sterowniki do mniej popularnych baz również mają obsługę prepared statements. Myślę, że już najwyższy czas, żeby społeczność zakończyła wsparcie dla staroci pokroju 4.x. Ewentualnie można napisać
Cytat
Aby zabezpieczyć się przed SQL Injection używaj prepared statements
opis...
opis...
opis...

gdzieś na dole, małymi literami:
Jeśli na twoim hostingu nie ma obsługi prepared statements dla twojej bazy danych to
a) zmień hosting
LUB
cool.gif poczytaj innych sposobach zabezpieczania [link]


Takie coś przynajmniej nie będzie mącić w głowie początkującym, którzy wielopoziomowe zabezpieczenie przed SQL Injection rozumieją tak:



Cytat
a dwa, że prawidłowe zabezpieczenia działają jeszcze zanim cokolwiek do bazy zaczniesz wrzucać i obejmują filtrowanie danych oraz ich walidację.

Przed SQL Injection zabezpieczają prepared statements.
Filtrowanie i walidacja zabezpiecza przed tym, żeby użytkownik nie ustawił sobie wieku -12345 lat, nazwiska zawierającego cyfry, czy adresu email bez małpy. To, że niektóre rygorystyczne filtry (np. login mogący składać się wyłącznie z liter i cyfr) zabezpiecza przed SQL Injection to tylko efekt uboczny. Dlatego uważam, że sposoby poprawnej walidacji danych powinny być przedstawione w podczepionym temacie o walidacji danych.
thek
Noidea... A ja napiszę, że zamiast prepared statements można użyć procedur składowanych i też będę miał rację. To na co chciałem zwrócić uwagę to fakt, że wspomniane przez Ciebie rozwiązanie nie jest jedyne i niepodważalne to raz, a dwa, że nie jest problemem napisać nowy serwis od zera i zastosować każdy myk jaki się zna. Programista wielokrotnie musi grzebać w czyimś kodzie, który "pierwszej świeżości" być nie musi i konieczność jego bezpiecznego utrzymania także jest ważna, mimo wprowadzania swoich poprawek. Możesz przemycać własne sztuczki, ale możesz dostać serwis, gdzie jesteś zmuszony zapomnieć o mechanizmach ochrony Ci znanych bo próba pisania w php5 = przepisanie całego core i masy elementów zależnych, czyli w zasadzie napisania serwisu od zera. Pół biedy gdy serwis wspiera kilka wersji i sobie po stronie serwera ustawisz które pliki idą jako php4, a jakie przez php5, ale i tak będzie to bagno z wydzielonymi funkcjonalnościami i gdzieś w końcu umoczysz zapewne bezpieczeństwo przez przypadek choćby. Wtedy tylko konkretna walidacja Cię może jakoś poratować, ale nie zabezpieczy i tak, bo część przydatnych funkcji jest dopiero od php5 i masz potencjalnie przydatne funkcje odcięte od arsenału. Witamy w prawdziwym świecie, a nie jego wycinku. I nie zapomnij o kompatybilności kodu wstecz. Naprawdę fajnie się pisze "rób tak i tak, olej resztę rozwiązań", tyle że jest to najczęściej prosta droga do tego by pokpić sprawę i puścić na produkcję bubel. Pamiętaj, że Twój komp to nie jedyna konfiguracja dla serwerów, a ja już wystarczająco wiele widziałem ustawień w php.ini, które powodowały, że zgrzytałem zębami. Nie wspominam nawet o aplikacjach firm trzecich, które zakładają sobie hostingodawcy i które mają w zamyśle chronić serwery, a wyjątkowo często sprawiają masę problemów. Sam niedawno kląłem na czym świat stoi, gdy się okazało, że hostingodawca filtruje dane $_POST i $_GET przez co 90% akcji administratorskich kończyło się errorem 403. A potem szukaj wiatru w polu bo kod poprawny się sypie, choć na developerskim śmigał jak marzenie. Powiesz klientowi, że ma sobie serwer zmienić lub doinstalować jakiś pakiet czy skompilować z obsługą określonego bo Twój konfig to ma i użyłeś przy pisaniu serwisu? wink.gif Nie sądzę.

A to co mówiłem o wieloetapowości ochrony to jest ważna rzecz. Po co zezwalać na zapis do bazy głupot, skoro można i powinno się je odsiać już wcześniej. Należy nie tylko kontrolować co wchodzi ale i wychodzi z bazy. Większość osób zwraca tylko na to pierwsze uwagę, ignorując choćby pobieżne sprawdzenie danych otrzymanych
Noidea
Sparametryzowane wywołanie procedur składowanych zabezpiecza przed SQL Injection. Ale jeśli będziemy to wywołanie sklejali ze stringów, to może nam to nic nie dać. O ile w przypadku MySQL ciężko będzie to wykorzystać, bo mysql_query nie zezwala na więcej niż jedną instrukcję, to dla innych baz już takiego ograniczenia nie ma:
  1. <?php
  2. // SQL Server
  3.  
  4. $_GET["user_id"] = "1234; DROP TABLE users";
  5.  
  6. $query = "EXEC getUserById " . $_GET["user_id"];
  7. echo $query; // EXEC getUserById 1234; DROP TABLE users
  8.  
  9. $result = sqlsrv_query( $conn, $query ); // Instrukcje wykonają się poprawnie. Obie.
  10. ?>


Chodzi mi o to, że najwyższy już czas przedstawiać użytkownikom nowoczesne rozwiązania problemów. Funkcje mysql_* siedzą w pehapie już od przeszło dziesięciu lat. Doczekały się następców, nieobarczonych charakterystycznymi dla nich problemami (ręczne zabezpieczanie przed sql injection, błędy zamiast wyjątków, itd.). Ale pomimo to są w 90% przypadków przedstawiane jako podstawowe rozwiązanie problemu wykorzystania baz danych w php.
Co ciekawe gdy ludzie zadają na stackoverflow pytania odnośnie C#, nie dostają odpowiedzi z stylu "hmm... nie podałeś wersji .NET pod którą piszesz, więc na wszelki wypadek podam ci rozwiązanie dla .NET 1.1 z 2001 roku". Nie, zamiast tego piszą "W .NET 4.0 możesz bardzo łatwo zrobić to przy użyciu XXX oraz YYY (...)". Dzięki temu wiesz jak rozwiązać problem, lub szukasz odpowiedników XXX i YYY dla starszej wersji .NET.
Więc zgadzam się ze wszystkim o czym mówisz, oprócz:
Cytat
Programista wielokrotnie musi grzebać w czyimś kodzie, który "pierwszej świeżości" być nie musi

Otóż świeży kod, datowany na 2011 rok, również jest pisany przy użyciu mysql_* i zabezpieczany ręcznie przy użyciu mysql_real_escape_string, co nie zawsze się młodym programistom udaje, przykład:
  1. mysql_query( "SELECT * FROM users WHERE id = " . mysql_real_escape_string( $_GET["id"] ) );
  2. // albo
  3. mssql_query( "SELECT * FROM users WHERE username = '" . addslashes( $_GET["name"] ) . "'" );


Dlatego ja nadal obstaję przy swoim i uważam, że aby pisać kod zabezpieczony przed SQL Injection, należy korzystać z prepared statements. A gdy już na prawdę nie ma innej możliwości, to wtedy czytamy o addslashes, magic_quotes, mysql_real_escape_string, rzutowaniu na typy liczbowe, itd. Może dzięki temu kilku początkujących zacznie pisać swoje pierwsze zapytania od razu w PDO.
kuba32
Witam, chciałbym się dowiedzieć czy mając włączone magic_quotes na serwerze i zapytanie sformułowane w taki sposób: "SELECT * FROM tabela WHERE id='$id'" jest możliwość wstrzyknięcia niechcianego zapytania (brak jakiejkolwiek filtracji danych)? Jeżeli tak (a zapewne tak jest) to w jaki sposób atakujący może tego dokonać?

Pozdrawiam
drozdii07
magic_quotes to najgorsze co może być.. Wyłącz to i napisz swoją walidację a nie jakieś cuda smile.gif Nie jestem pewien ale chyba da się bez problemów włamać nawet z magic_ - Jeśli się mylę, poprawcie smile.gif
kuba32
No właśnie niby mówi się, że magic_quotes jest ble i fuj, ale szukałem sposobów na jego obejście no i jakoś nie znalazłem (być może źle po prostu szukałem), więc jak na razie jedyne zagrożenie które dostrzegam w jego użytkowaniu to po prostu problemy kiedy swoją aplikacje będziemy musieli przenieś na serwer na którym magic_quotes jest wyłączone.

Pozdrawiam, mam nadzieję że ktoś będzie potrafił mnie uświadomić dlaczego magic_quotes to zło
erix
Cytat
kiedy swoją aplikacje będziemy musieli przenieś na serwer na którym magic_quotes jest wyłączone.

Albo gdy będziesz płakać, gdy w końcu z PHP to wyrzucą (bo obiło mi się o uszy, że są takie plany).

Cytat
Pozdrawiam, mam nadzieję że ktoś będzie potrafił mnie uświadomić dlaczego magic_quotes to zło

http://en.wikipedia.org/wiki/Magic_quotes

Mam nadzieję, że ludzie kiedyś nauczą się korzystać z wyszukiwarek i tego, co mają pod nosem.
henio
Chciałbym dowiedzieć się czy używanie PDO i metod prepare(), execute() jest bezpieczne z punktu widzenia SQL Injection? Czy mimo to warto używać add/stripslashes
fr33d0m
Przeczytałem cały temat i zastanawia mnie dlaczego nie pojawiło się filtrowanie $_GET, $_POST etc. przy pomocy array_map funkcją htmlspecialchars, trim i mysql_real_escape_string. Takie filtrowanie jest bardzo skuteczne i nawet jeśli zapytanie do bazy jest źle skonstruowane i nie filtrowane, takie jak poniżej to potencjalny hacker nic nie zdziała.
  1. $sql = mysql_query(SELECT * FROM news WHERE id=$_GET['id']);



Oczywiście dla pewności należy przy tym pamiętać o poprawnych typach kolumn w SQL i mimo wszystko rzutowaniu na (int), sprawdzaniu długości (substr) i dla szerszej ochrony wykrywanie przedwcześnie zalogowanych kont, które szukają dziur.

Poza tematem via msg, to chętnie wymienię się informacją jak ominąć filtr mysql_real_escape_string za ominięcie is_numeric - wiem że się da.
SHiP
O ile w normalnych warunkach wszystko jest ok to jeżeli sprzedajemy aplikację chinczykowi to może być już problem. Zróbcie sobie bazę z kodowaniem i sprawdzcie taki kodzik:

  1. <?php
  2. date_default_timezone_set('Europe/Warsaw');
  3. if(!empty($_GET))
  4. {
  5. $db = new mysqli('localhost', 'uzytkownik', 'haslo', 'nazwa_bazy');
  6. $db -> set_charset('big5'); // kodowanie bazy big5!!
  7.  
  8. $login = addslashes($_GET['login']);
  9. $password = addslashes($_GET['password']);
  10.  
  11. $result = $db->query('SELECT * FROM users WHERE login="'.$login.'" AND password=MD5("'.$password.'")');
  12.  
  13. if($row = $result->fetch_assoc())
  14. {
  15. print_r($row);
  16. }
  17. }
  18. ?>


Teraz w adresie wystarczy podać np.

Kod
http://localhost/testsql.php?login=admin%f4%22+OR+1=1+--&password=qwerty


Efekt:
  1. SELECT * FROM users WHERE login="admin?" OR 1=1 --" AND password=MD5("qwerty")


Sytuacja wygląda analogicznie z mysql_real_escape_string() - w koncu to prawie identyczna funkcja jak addslashes

@fr33d0m: jeślichcesz, to mogę wysłać Ci przez msg listę kodowań i wytłumaczenie dlaczego jest tak a nie inaczej.

Pozdro
fr33d0m
Nie zagłębiam się aż tak w inne kodowanie niż europejskie bo jest mi to nie potrzebne. Aby zapobiec i zrozumieć SQL Injection/Insertion trzeba zawężyć krąg kodowań do naszych rodzimych, które są często używane bo nowym userom przez przykład kodowania z Chin można tylko w głowie zamieszać.



---edit:
@SHiP
Wierzę na słowo, że przy zabezpieczeniu kodowań wszystkich znaków świata trzeba mieć głowę na karku. smile.gif
Potrafię pominąć mysql_real_escape_string. A swoją drogą to z matematyki miałem 5 więc doskonale wiem dlaczego jest tak, jak jest w kodowaniu Chińskim. wink.gif
SHiP
Chodziło mi o przedstawienie przykładu, który pokaże, że używanie metod typu addshasles() to pomyłka. Problem chińskiego kodowania nie jest trywialny. Pisząc dużą aplikację(np. taki wordpress) należy wziąć pod uwagę, że będą z niej korzystać Azjaci z kodowaniami bogatymi w różne fajne znaczki.

PS: co do Twojej propozycji. Umiesz złamać mysql_real_escape_string() czy is_numeric() ? Bo nie wiem co, za co chcesz się wymieniać
pyro
Cytat(SHiP @ 13.10.2011, 12:11:06 ) *
Sytuacja wygląda analogicznie z mysql_real_escape_string() - w koncu to prawie identyczna funkcja jak addslashes


A to akurat nieprawda, bo mysql_real_escape_string() zwraca uwagę na kodowanie
cudny
Cytat(pyro @ 4.11.2011, 17:46:58 ) *
A to akurat nieprawda, bo mysql_real_escape_string() zwraca uwagę na kodowanie

A tu też nie do końca jest pięknie z tym kodowaniem mysql_real_escape_string(); biggrin.gif

http://forum.php.pl/index.php?s=&showt...st&p=911748
pyro
Cytat(cudny @ 5.11.2011, 12:00:35 ) *
A tu też nie do końca jest pięknie z tym kodowaniem mysql_real_escape_string(); biggrin.gif

http://forum.php.pl/index.php?s=&showt...st&p=911748


No akurat jest, bo na MySQL5 (chyba 5.0.23, nie szukałem) to już nie działa. A jak ktoś ma zamiar korzystać z MySQL4 to nie ma po co się babrać z omijaniem filtrów bo jest kilka innych exploitów na tak starą wersję pozwalającą na zdalne wykonanie kodu.
ficiek
Jest prosty sposób na szybkie wyczyszczenie danych w razie włączonych magic_quotes (w wypadku gdy nie możemy go wyłączyć).

  1. <?php
  2. function stripslashes_gpc(&$value)
  3. {
  4. $value = stripslashes($value);
  5. }
  6. array_walk_recursive($_GET, 'stripslashes_gpc');
  7. array_walk_recursive($_POST, 'stripslashes_gpc');
  8. array_walk_recursive($_COOKIE, 'stripslashes_gpc');
  9. array_walk_recursive($_REQUEST, 'stripslashes_gpc');
  10. }
  11. ?>
cudny
Cytat(pyro @ 5.11.2011, 20:48:46 ) *
No akurat jest, bo na MySQL5 (chyba 5.0.23, nie szukałem) to już nie działa. A jak ktoś ma zamiar korzystać z MySQL4 to nie ma po co się babrać z omijaniem filtrów bo jest kilka innych exploitów na tak starą wersję pozwalającą na zdalne wykonanie kodu.


Nie chcę tutaj polemizować na ten temat bo nie mogę znaleźć info. na ten temat. Masz jakieś linki ?
pyro
Cytat(cudny @ 7.11.2011, 23:45:47 ) *
Nie chcę tutaj polemizować na ten temat bo nie mogę znaleźć info. na ten temat. Masz jakieś linki ?


Linki do czego? Mam 3 wersje MySQL5+ i na żadnym z nich nie działa to co opisał tamten użytkownik na blogu.
fernet
Temt SQL Injection/Insertion nigdy mnie nie dotyczyl ale jesli nad tym sie zastanowic to porzadna kontrola tresci zalatwia sprawe w 70% a jak to komus to nie wystarcza to tak jak na ssl kazda strona ma swoj super tajny klucz to niech i akcja na bazie bedzie miala swoj super tajny klucz. Przed akcja z baza jakies autorskie fikumiku na tresci a podczas odczytywania mikufiku i pozamiatane. Wtedy nawet przegladanie phpMyAdmin nikomu nic nie da co prawda bedze mogl w ramach akcji protestu skasowac cala baze danych ale od czego jest backup.
sebekzosw
takie pytanie - dane filtrować mysql_real_escape_string przed dodaniem do bazy czy zaraz po odebrania formularza? chodzi oto, że między tymi akcjami mam jeszcze sprawdzanie czy coś zostało podane, weryfikacja np meila i inne weryfikacje. stąd to pytanie.

bo ocenie robię to po odebraniu formularza:
  1. $title= isset($_POST['title']) ? $sql->html($_POST['title']) : '';
  2.  
  3. if(empty($title))
  4. $form['info'] .= 'Wpisz tytuł podstrony'."\n";
  5.  
  6. //zapytanie dodajace wpis do bazy

nospor
Przeczytaj do czego służy mysql_real_escape_string a poznasz odpowiedź na swoje pytanie.
szymon1215
Użycie PDO w następujący sposób
  1. $pdo = new PDO("mysql:host=localhost;dbanme=xxx", "root", "");
  2. $zap = $pdo->prepare("INSERT INTO `uzytkownicy` (`login`, `haslo`, `email`) VALUES(:login, :haslo, :email)");
  3. $zap->bindValue(":login", $_POST['login'], PDO::PARAM_STR);
  4. $zap->bindValue(":haslo", $_POST['haslo'], PDO::PARAM_STR);
  5. $zap->bindValue(":email", $_POST['email'], PDO::PARAM_STR);
  6. $zap->execute();
  7. $zap->closeCursor();

jest wystarczającym zabezpieczeniem?
Mephistofeles
Tak.
Dominator
Jeśli będę używał PDO zamiast MySQL do łączenia się z bazą danych to jest mniejsze prawdopodobieństwo, że ktoś może wykorzystać SQL Injection ?
Mephistofeles
Po pierwsze nie zamiast MySQL, co najwyżej mysql_ smile.gif.
Po drugie tylko jeśli będziesz używał zapytań preparowanych i podpinania parametrów, wtedy prawdopodobieństwo -> 0.
Dominator
A gdzie mogę zobaczyć przykład zapytań preparowanych ?
Mephistofeles
Stronę wcześniej w tym temacie biggrin.gif.
Dominator
Czyli ten kod jest preparowaniem zmiennych, tak ?

  1. $pdo = new PDO("mysql:host=localhost;dbanme=xxx", "root", "");
  2. $zap = $pdo->prepare("INSERT INTO `uzytkownicy` (`login`, `haslo`, `email`) VALUES(:login, :haslo, :email)");
  3. $zap->bindValue(":login", $_POST['login'], PDO::PARAM_STR);
  4. $zap->bindValue(":haslo", $_POST['haslo'], PDO::PARAM_STR);
  5. $zap->bindValue(":email", $_POST['email'], PDO::PARAM_STR);
  6. $zap->execute();
  7. $zap->closeCursor();
d3ut3r
tak.
Dominator
Dobra, po przeczytaniu lektury w tym temacie od dnia dzisiejszego będę korzystał z PDO.

Dzięki smile.gif

A w jaki bezpieczny sposób wyciągać dane użytkowników za pomocą PDO ?
Cadmer
Witam
Chciałbym potwierdzić kilka rzeczy:
1. Czy funkcja mysqli_real_escape_string jest tak samo nic niewarta jak mysql_real_escape_string? Oczywiście na dzień dzisiejszy (PHP 5.4).
2. Czy w przypadku liczb całkowitych rzutowanie na inta jest wystarczającym zabezpieczeniem czy są jakieś cudowne metody pozwalające obejść to?
3. Czy htmlentities chroni przed XSS?
I od razu chciałbym zaznaczyć że nie jestem upartym durniem broniącym się rękami i nogami przez używaniem prepared statements, tylko jakiś czas temu przeczytałem to i stwierdzenie tam zawarte nie daje mi spokoju:
Cytat
SQL injections are not the reason to write slower code, php mysql driver provides several ways to escape the input.
pyro
Cytat(Cadmer @ 21.01.2013, 22:12:19 ) *
1. Czy funkcja mysqli_real_escape_string jest tak samo nic niewarta jak mysql_real_escape_string? Oczywiście na dzień dzisiejszy (PHP 5.4).


Obie są stworzone do tego, co mają robić, i stwierdzenie, że są nic nie warte to pitolenie po całości.

Cytat(Cadmer @ 21.01.2013, 22:12:19 ) *
2. Czy w przypadku liczb całkowitych rzutowanie na inta jest wystarczającym zabezpieczeniem czy są jakieś cudowne metody pozwalające obejść to?


Wystarczy

Cytat(Cadmer @ 21.01.2013, 22:12:19 ) *
3. Czy htmlentities chroni przed XSS?


Między innymi tak.
Cadmer
Dzięki z szybką i konkretną odpowiedz.
Co do 1. to chyba zostałem źle zrozumiany też wydaje mi się (bo brak mi wiedzy na ten temat) że te funkcja działa jak powinna, lecz wcześniej w tym wątku, albo gdzieś indziej, wyczytałem że ma problemy z kodowaniem znaków itp. itd.
To jeszcze tak dla pewności - używanie mysqli_real_escape_string jest tak samo efektywne (albo chociaż porównywalne) z używaniem prepared statements? Oczywiście jeśli chodzi o zabezpieczenie przez SQL Injection.
pyro
Cytat(Cadmer @ 21.01.2013, 23:19:03 ) *
Dzięki z szybką i konkretną odpowiedz.
Co do 1. to chyba zostałem źle zrozumiany też wydaje mi się (bo brak mi wiedzy na ten temat) że te funkcja działa jak powinna, lecz wcześniej w tym wątku, albo gdzieś indziej, wyczytałem że ma problemy z kodowaniem znaków itp. itd.
To jeszcze tak dla pewności - używanie mysqli_real_escape_string jest tak samo efektywne (albo chociaż porównywalne) z używaniem prepared statements? Oczywiście jeśli chodzi o zabezpieczenie przez SQL Injection.


Musisz przeczytać do czego służy jedno i drugie... bo jak w ciemno będziesz wszędzie stosował "funkcje zabezpieczające" nie rozumiejąc co one robią, to prawdopodobnie i tak zostawisz luki, pomimo ich zastosowania.
Cadmer
Na dobrą sprawę moim problemem nie jest niewiedza jeśli chodzi o techniki obrony przed SQL Injection, chodzi bardziej o to że nie mam pojęcia jak wygląda taki atak (hakowanie mnie kompletnie nie interesuje), oczywiście poza teorią i prostymi przykładami - tylko jak dla mnie przed tym chroniło magic quotes, a tu czytam że w 5.4 zostało praktycznie rzecz ujmując wywalone. Przez co trochę zgłupiałem.
Ale poczytałem na spokojnie i rozwiałem większość swoich wątpliwości. Swoją drogą polecam tą stronę - wszystko w jednym miejscu i konkretnie na temat.
Mam jeszcze dwa pytania na które nie znalazłem konkretnych odpowiedzi.
W przypadku gdy chcę umieścić w bazie treść np. komentarza, posta, wiadomości itp. czyli gdy jest duża dowolność wpisywanych danych oraz ma być to później wyświetlone. Widzę dwa rozwiązania:
1. Zdekodować taką treść używając htmlentities i zapisać w takiej postaci w bazie. Niby nie jest to złe rozwiązanie ale ciężko będzie takie coś edytować z poziomu bazy danych.
2. Zastosować przed umieszczaniem w bazie mysqli_real_escape_string, a przy wyświetleniu użyć htmlentities. Nie ma to wady pierwszej metody ale nie jestem pewien czy samo mysqli_real_escape_string wystarczy.
Czy do switcha można wystrzyknąć złośliwy kod? Czyli czy takie coś:
  1. switch($_GET['cos'])
  2. { ... }

jest potencjalnie niebezpieczne? Wiem że to ogólnie zła praktyka bo uczy złych nawyków, ale chodzi mi konkretnie czy switch jest narażony na taki atak.
pyro
Cytat(Cadmer @ 22.01.2013, 17:49:30 ) *
W przypadku gdy chcę umieścić w bazie treść np. komentarza, posta, wiadomości itp. czyli gdy jest duża dowolność wpisywanych danych oraz ma być to później wyświetlone. Widzę dwa rozwiązania:
1. Zdekodować taką treść używając htmlentities i zapisać w takiej postaci w bazie. Niby nie jest to złe rozwiązanie ale ciężko będzie takie coś edytować z poziomu bazy danych.
2. Zastosować przed umieszczaniem w bazie mysqli_real_escape_string, a przy wyświetleniu użyć htmlentities. Nie ma to wady pierwszej metody ale nie jestem pewien czy samo mysqli_real_escape_string wystarczy.


1 metoda odpada zupełnie, bo jest to bardzo zła praktyka, jeśli chodzi o cały projekt.

Co do reszty, przeanalizuj poniższy przykład:

  1. <?php
  2.  
  3. // ....
  4.  
  5. $user_id = $_GET['user_id'];
  6. $result = mysql_query('SELECT * FROM users WHERE id = '.mysql_real_escape_string($user_id));
  7.  
  8. // .....
  9.  
  10. ?>


I sam mi odpowiedz na pytanie czemu ten urywek kodu jest podatny na ataki.

Cytat(Cadmer @ 22.01.2013, 17:49:30 ) *
Czy do switcha można wystrzyknąć złośliwy kod? Czyli czy takie coś:
  1. switch($_GET['cos'])
  2. { ... }

jest potencjalnie niebezpieczne? Wiem że to ogólnie zła praktyka bo uczy złych nawyków, ale chodzi mi konkretnie czy switch jest narażony na taki atak.


To też zależy. Z reguły nie, ale w przypadku udziwniania, też można zostawić lukę pozwalającą na włamanie.
Cadmer
Cóż można tam wstawić ID jakiegokolwiek użytkownika, co niekoniecznie jest błędem zależy co miałby ten kod robić. Nie powinno się raczej nigdy za to wybierać wszystkich kolumn z tabeli przy pomocy * z wielu powodów. Jeśli chodziło Ci o coś innego to tak jak pisałem wcześniej nie znam się na magicznych jak dla mnie sposobach wczepiania kodu zapytań.
Piotrbaz
Cytat(pyro @ 22.01.2013, 18:08:50 ) *
1 metoda odpada zupełnie, bo jest to bardzo zła praktyka, jeśli chodzi o cały projekt.



Mógłbyś jakoś rozwinąć ? Właśnie jestem na etapie 'zabezpieczania' danych z postów i komentarzy i miałem zamiar użyć htmlspecialchars lub htmlentities. Oczywiście nie w kontekście SQL Injection, bo od tego mam PDO, ale np ataków XSS.
pyro
Cytat(Cadmer @ 22.01.2013, 22:22:41 ) *
Cóż można tam wstawić ID jakiegokolwiek użytkownika, co niekoniecznie jest błędem zależy co miałby ten kod robić. Nie powinno się raczej nigdy za to wybierać wszystkich kolumn z tabeli przy pomocy * z wielu powodów. Jeśli chodziło Ci o coś innego to tak jak pisałem wcześniej nie znam się na magicznych jak dla mnie sposobach wczepiania kodu zapytań.


Nie, zupełnie nie o to chodzi. Jako user_id podstaw sobie (zakładam, że w tabeli są kolumny id, username, password):

Kod
-1 UNION SELECT 1, DATABASE(), 3


I zobacz co się stanie. Zabezpieczone przez mysql_real_escape_string(), a luka nadal jest. Magia, co?


Cytat(Piotrbaz @ 3.02.2013, 18:05:56 ) *
Mógłbyś jakoś rozwinąć ? Właśnie jestem na etapie 'zabezpieczania' danych z postów i komentarzy i miałem zamiar użyć htmlspecialchars lub htmlentities. Oczywiście nie w kontekście SQL Injection, bo od tego mam PDO, ale np ataków XSS.


Dane do wyświetlania zabezpiecza się właśnie przy wyświetlaniu, a nie ładuje do bazy już w zmienionej formie. Chodzi o integralność danych i czytelność tego co wpisują użytkownicy.
Piotrbaz
No ok, czyli htmlspecialchars() stosuje przed wyświetleniem danych użytkownikowi. Czy przed zapisem danych do bazy ograniczam się tylko zabezpieczeniem przed SQL Injection ? (co załatwia podpinanie w PDO)
pyro
Tak, prepared statements w PDO powinny załatwić sprawę. No chyba że integer przez przypadek potraktujesz jako string.
Wasper
Czesc,

troche tego duzo, szczerze, nie mam czasu czytac wszystkich stron.Ale mam pytanie apropo mysql_real_escape_string.
Wszyscy pisza, zeby uzywac do zmiennych przed wstawieniem do zapytania...
a nie mozna finalnego zapytania w calosci przepuscic przez to? Czy to bedzie mialo jakis nieoczekiwany efekt?
!*!
Zostaw te bzdury zaczynające się od mysql_* w manualu i przejdź na PDO, a nie będziesz mieć takich problemów.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.