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
logeen
Cytat(Vengeance @ 2005-05-14 20:44:37)
Union da się wiele razy wykorzystać nie stosując nawet jednego apostrofu!
Więc samo używanie addslashes() w przypadku posiadania MySQL 4 nie jest bezpieczne !

Mam w takim razie pytanko: w jaki sposób wykonać SQL Injection w takim skrypcie:
  1. <?php
  2. // Łączenie z serwerem MySQL itd.
  3.  
  4. // Logowanie administratora:
  5. mysql_query('SELECT * FROM admins WHERE user_login = '' . (get_magic_quotes_gpc() ? $_POST['login'] : addslashes($_POST['login'])) . '' AND user_password = '' . (get_magic_quotes_gpc() ? $_POST['password'] : addslashes($_POST['password'])) . ''');
  6.  
  7. // Zmiana hasła:
  8. mysql_query('UPDATE users SET user_password = '' . (get_magic_quotes_gpc() ? $_POST['password'] : addslashes($_POST['password'])) . '' WHERE user_id = ' . abs(intval($_GET['user_id'])));
  9.  
  10. // Albo:
  11. mysql_query('UPDATE users SET user_password = '' . (get_magic_quotes_gpc() ? $_POST['password'] : addslashes($_POST['password'])) . '' WHERE user_login = '' . (get_magic_quotes_gpc() ? $_GET['login'] : addslashes($_GET['login'])) . ''');
  12.  
  13. // Operacje końcowe: zamykanie połączenia itd.
  14. ?>

Jakoś nie widzę tutaj możliwości wykorzystania UNION poprzez SQL Injection dry.gif
Vengeance
Wiadomym jest, że nie w każdym się da... ale są przypadki gdzie tak jest. Przecież w UNION najczęściej chodzi o wyciągnięcie danych... więc nie musisz używać apostrofu. Gdy ktoś zrobi błąd w takim miejscu, iż użycie apostrofu nie jest wymagane (a najczęściej jest właśnie tylko w dyrektywach WHERE) to droga otwarta.
johnson
Nie zapominajmy, że przy union włamywacz musi znać nazwę tabeli i pól w tabeli mysql, a w przypadku, jeśli ktoś pisze skrypty sam i nie używa gotowców, prawdopodobieństwo, że włamywacz odgadnie nazwę tabeli i pola jest IMHO bardzo małe.
Vengeance
IMHO pokaz mi programiste co nie trzyma loginow i hasel w tabeli nazwą zblizonej do 'users' :]

Pozatym... wywolujac kontrolowane bledy SQL mozna czesto poznac spora czesc struktury bazy SQL.

Ale ogólnie to masz racje snitch.gif
logeen
Cytat(Vengeance @ 2005-07-07 18:53:24)
Gdy ktoś zrobi błąd w takim miejscu, iż użycie apostrofu nie jest wymagane (a najczęściej jest właśnie tylko w dyrektywach WHERE) to droga otwarta.

Tutaj się zgodzę, ale powiedzcie mi w takim razie, po co sztucznie wywalać UNION ze wszystkich danych podstawianych do zapytania, jeżeli można je tak zabezpieczyć, że nigdy nie będzie możliwości wykonania SQL injection (np. tak jak zaprezentowałem powyżej)? Czy to nie jest paranoja? Gdyby programiści IPB byli tak na to wyczuleni, to na tym forum w treści postów w ogóle nie dałoby się wpisać słowa "UNION" i jeszcze kilku innych, a jak widać da się smile.gif
Vengeance
Dlatego, że w takim forum wykonuje się masę zapytań i nie zawsze wszystkie 100% sprawdzisz. Więc lepiej w jednym miejscu filtrować niebezpieczne dane... by potem mieć pewność że do każdego zapytania dotrą w odpowiedniej formie... i że nie zapomnieliśmy gdzieś czegoś filtrować.
logeen
To jasne, ale zależy, co rozumiesz przez "filtrować". Jeżeli filtrowaniem nazywamy np. używanie funkcji "addslashes" czy "intval", to OK. Ale jeżeli to ma polegać na bezcelowym usuwaniu np. wszystkich wystąpień słowa "UNION" i innych podobnych z danych przesyłanych przez użytkownika, a podstawianych do zapytania, to ja tego nie rozumiem. Po co to usuwać, skoro i tak w żaden sposób nie może zaszkodzić, jeżeli odpowiednio przefiltrujemy dane? Na dodatek przez takie postępowanie zupełnie niepotrzebnie eliminujemy sobie możliwość wstawienia do bazy danych niektórych słów, co może być akurat potrzebne. Spróbujcie napisać np. tutorial używania unii w SQL, jeżeli z każdego tekstu wstawianego do bazy będziecie czyścić to słowo ;-)

Jak ktoś nie filtruje danych, to i tak żadne usuwanie "UNION" itp. mu nie pomoże, bo SQL injection można wykonać na wiele innych sposobów, kiedy nie przefiltrujemy danych wejściowych...
Vengeance
1. A kto mówi że strona musi traktować o czymś gdzie wystąpi UNION.
2. Zobacz ile skryptów (np. phpbb) jest podatnych na tego typu ataki
logeen
ad.1) Czyli co? Jeżeli zamierzasz zbudować np. forum dyskusyjne przeznaczone do dyskusji na temat języka SQL, to nie będzie się go dało zabezpieczyć, bo w takim przypadku usuwanie "UNION" z treści wysyłanych postów jest absolutnie nie do przyjęcia, a tylko to dałoby wystarczające zabezpieczenie?

ad.2) Skrypty są podatne, ponieważ programiści zapomnieli przefiltrować dane. Gdyby to zrobili, to by nie były podatne. Usuwanie "UNION" tutaj nic nie zmieni, ponieważ jeżeli dane wejściowe potraktujemy odpowiednio "addslashes" czy "intval", to żadne "UNION" przemycone w treści nam nie zaszkodzi. Do tego właśnie zmierzało moje pytanie, na które do tej pory nikt nie odpowiedział jasno i wyraźnie: czy jeśli stosujemy odpowiednią filtrację danych (np. taką jak zaprezentowałem), to wstawienie przez użytkownika "UNION" w danych wejściowych może się źle skończyć?
MStaniszczak
Nie ma sensu nic wywalać (filtrować żadnych słów). Grunt to dobrze wstawiać slashe a tam gdzie ich nie można dodać (np. identyfikatory) stosować odpowiednio is_number, is_integer, intval etc… Nie da rady o tym zapomnieć;-)

Dobry sposobem mogą być filtry w frameworku;-) Ew. klasa z metodami sprawdzającymi dane odpowiednich typów, a wówczaj wystarczy już coś w stylui:
  1. <?php
  2. try {
  3.  $id = CheckData::integer($_GET[&#8216;id’]);
  4.  $name = CheckData::string($_POST[&#8216;name’]);
  5.  $postcode = CheckData::postcode($_POST[&#8216;postCode’]);
  6. } catch(DataFormatException $e) {
  7.  echo &#092;"Zły format danych\";
  8. }
  9. ?>


Czy jakoś tak;-) Przy takiej organizacji łatwiej nawet poprawić ew. błąd czy luke w sposobie sprawdzania danych;-)

Pozdrawiam
Marcin Staniszczak
Imperior
Oświećcie mnie proszę i powiedzcie, gdzie przy zdrowych zmysłach programista może zostawić lukę, że można użyć UNION bez ani jednego apostrofa? Przecież to jest możliwe tylko przy czymś takim:

  1. SELECT *
  2. FROM users WHERE id = $string


O czym wogóle rozmawiacie... tak robią tylko początkujący-nieuświadomieni.
Vengeance
Imperior... są nawet tacy co robią

  1. SELECT *
  2. FROM users $warunki


Widac, ze analizowales malo skryptów i mało skomplikowanych zapytań widziałeś.

Cytat
tak robią tylko początkujący-nieuświadomieni

O ile mi wiadomo, to forum i ten wątek jest także dla takich a my staramy się ich uświadomić co może być błędem.

@logeen:
AD2. Prawdopodobnie masz racje i wykorzystanie wszędzie odpowiednich filtrów intval() itd... wystarczy, ALE

Mała opowieść:
Cytat
Zostałem adminem forum szkolnego. Obecnie jedyna możliwość posiadania dość fajnego i darmowego forum to phpBB. Pozatym
wcześniej też takie tam było i użytkownicy się przyzwyczaili.
Zrobiłem update do najnowszej wersji, ale wiadomo że i tak znajdą jakieś błędy (i znaleźli). Trzeba było więc zastosować właśne zabezpieczenia. Przecież nie będę naprawiał całego phpBB i w odpowiednich miejscach dawał intval() tam gdzie oni zapomnieli!

Zrobilem tak więc filtrację danych z GET i usuwam wszystkie "UNION".
Jeśli znajdziesz mi podobne w szybkosći implementacji i pod względem bezpieczeństwa rozwiązanie to z chęcią wysłucham.

A na forum dalej można pisać UNION gdyż filtruje tylko GET (phpBB do wszelkich rzeczy używa naszczęście tablic GET/POST/COOKIE a nie jedzie na superglobalach.
logeen
@Vengeance: Z tą opowieścią, to się z Tobą zgodzę. Z tym, że są pewne "ale":

1. Ten temat chyba raczej miał na celu przedstawienia zasad takiego pisania skryptów, aby nie były podatne na SQL injection, a nie poprawiania gotowych skryptów. Więc w przypadku, który podałeś, takie postępowanie może być uzasadnione, ale chyba raczej nie w sytuacji, kiedy piszemy cały skrypt od nowa.

2. Jeżeli w sytuacji, którą przedstawiłeś, nie przefiltruje się odpowiednio danych, to i tak usuwanie "UNION" niekoniecznie da 100% bezpieczeństwo, bo przecież są inne sposoby wykonania SQL injection niż tylko za pomocą unii. Natomiast faktycznie w sytuacji konieczności porawiania istniejących dziurawych skryptów, lepsze takie zabezpieczenie niż żadne.

3. Dane $_POST też przecież można spreparować, po prostu tworząc odpowiedni formularz i go wysyłając do skryptu sad.gif Co wiecej, można zrobić tak, żeby taki formularz wysłał nieświadomie administrator forum.
Vengeance
@logeen: Ale powiedzmy sobie prawde, że fora szkolne "hakują" tylko gówniarze co potrafią jedynie ściągnąć sploita z internetu. A te korzystają wyłącznie z GET i najczęściej właśnie z UNION (w przypadku phpBB). Ja nie mówie o pełnym zabezpieczeniu gotowca (bo to niemożliwe) ale o "zawężeniu kręgu niebezpieczeństwa" :]

Chyba doszliśmy do porozumienia smile.gif
johnson
Mówcie co chcecie, ale czy jest ktoś w stanie podać konkretny zestaw zabezpieczeń, który ustrzeże nas przed atakami poprzez php (oczywiście takie, które zależą od programisty) czy może nie ma sposobu na 100%-owe zabezpieczenie skryptów?
logeen
@johnson:
Odpowiedź brzmi: pełna filtracja (tzn. "addslashes", "intval" itp.) wszystkich danych zewnętrznych, które podstawiamy do zapytania SQL. Oczywiście jeżeli piszesz skrypt od zera, bo jeżeli poprawiasz bezpieczeństwo jakiegoś dziurawego gotowca, to trudno Ci będzie sprawdzić wszystkie linie kodu (ale nie jest to niewykonalne, bo tak naprawdę musimy odszukać tylko miejsca wywoływania zapytań SQL i sprawdzić, czy wszystkie zmienne podstawiane do kodu SQL są przefiltrowane) - wtedy można się dodatkowo zdecydować na rozwiązanie podane przez Vengeance, choć i tak nie będzie to pełne zabezpieczenie, niemniej powinno powstrzymać większość script kiddies.
brachu
jezeli mozna wtracic swoje 3 grosze.... to testowalem swoj system zlecen i o dziwo nie mozna sie do niego dostac za pomoca SQL injection, zasluga jest to domyslnych ustawien serwera oraz kilku funkcji sprawdzajacych poprawnosc - ktore wcale nie byly pisane w tym celu.... ogolnie warto jest pisac funkcje sprawdzajace poprawnosc wpisanych przez uzytkownika wartosci - nawet po to aby uniknac wpisywania glupot w wypadku gdy uzytkownikowi pomieszaja sie pola formularza winksmiley.jpg

pozdrawiam
MStaniszczak
A tu http://www.gajdaw.pl/varia/xss.html macie coś o atakcha na strony (nie SQL Injection więc troche OT;-) )

Pozdrawiam
Marcin Staniszczak
moron
czyli co? mysql_escape_string, stripslashes questionmark.gif
moglby ktos napisac jakas funkcje ktora by to robila?
logeen
  1. <?php
  2. /**
  3.  * Wstawia znaki unikowe w zapytaniach, dzieki czemu zapobiega atakowi "SQL injection".
  4.  * @param string $text Ciag tekstowy do zamiany
  5.  * @param resource $handle Identyfikator polaczenia
  6.  * @return string Ciag tekstowy po zamianie
  7.  */
  8. function mysql_escape($text, $handle=NULL)
  9. {
  10.     if (version_compare(phpversion(), '4.3.0', '>='))
  11.     {
  12.         if ($handle) return mysql_real_escape_string($text, $handle);
  13.         return mysql_real_escape_string($text);
  14.     }
  15. if (version_compare(phpversion(), '4.0.3', '>=')) return mysql_escape_string($text);
  16.     return addslashes($text);
  17. }
  18. ?>
qeuw
Jak można zabazpieczyć stronę jeżeli mam where id=$_GET['id'] and password=$password, wtedy wpisując kod w $_GET['id']= '7 --'
Zaniecha mi sprawdzanie hasła. Te funckje działają tylko w ściśle określonych przypadkach. Jak można było by zabezpieczyc przed pytaniami or,select,delete, into,update, w tablicy _GET, i mieć jakąś tam pewność że skrypt będzie zabezpieczony.
ActivePlayer
Cytat
Jak można zabazpieczyć stronę jeżeli mam where id=$_GET['id'] and password=$password, wtedy wpisując kod w $_GET['id']= '7 --'

uzyj is_numeric na $_GET['id']
h.4
Mam takie pytanie...

  1. <?php
  2.  
  3. $_POST['komentarz'] = mysql_real_escape_string($_POST['komentarz'];
  4. $_POST['komentarz2'] = mysql_real_escape_string($_POST['komentarz2'];
  5. $_POST['komentarz3'] = mysql_real_escape_string($_POST['komentarz3'];
  6.  
  7. ?>


i teraz jak zrobic zeby wszystkie dane z _POST przepuscic przez mysql_real_escape_string bez koniecznosci powtarzania tej funkcji do kazdej zmiennej... tylko zrobic to hurtem smile.gif

please help
ActivePlayer
Cytat
a jeśli zamiast _GET będzie _POST z jakimś tekstem?

to obejmiesz te dane w ' i wykonasz na nich mysql_escape_string()
wojto
Cytat(h.4 @ 2005-09-28 19:05:34)
i teraz jak zrobic zeby wszystkie dane z _POST przepuscic przez mysql_real_escape_string bez koniecznosci powtarzania tej funkcji do kazdej zmiennej... tylko zrobic to hurtem smile.gif

  1. <?php
  2. foreach($_POST as $a => $b) {
  3. $_POST[$a] = mysql_real_escape_string($b);
  4. }
  5.  
  6. ?>
?
qeuw
Otóz zrobilem funckje która zamienia wyrażenia sql na np. z UnIoN na !union!. Sądze że to w miare skuteczna metota gdzyż zawiera popularną składnie sql + wyrażenia opisane w phpmyadminie na stronie ze statystykami. A co to tej pętli to się bardzo mi przyda smile.gif
logeen
Cytat(qeuw @ 2005-09-28 20:08:04)
Otóz zrobilem funckje która zamienia wyrażenia sql na np.  z UnIoN na !union!. Sądze że to w miare skuteczna metota...

Fakt... tylko po co? KAŻDE zapytanie można skutecznie zabezpieczyć przed SQL Injection, bez usuwania z niego słów kluczowych SQLa, a jedynie poprzez odpowiednią filtrację danych, przed podstawieniem ich do zapytania. Przez "Filtrację" rozumiem wykonania np. addslashes (albo lepiej funkcji, którą podałem wcześniej) lub np. intval tam, gdzie jest to konieczne - w zależności od kontekstu. Ciekaw jestem jak rozwiążesz sprawę, kiedy "UNION" powinno się zapisać w bazie danych, np. w jakiejś treści wyświetlanej później na stronie WWW? Fakt, można zamieniać np. na "!union!", a potem przy wyświetlaniu z powrotem na "UNION", ale po co? Jak ktoś mi pokaże jak wykorzystać "UNION" do wykonania SQL Injection w prawidłowo zabezpieczonym skrypcie - np. takim, jak podawałem w tym temacie kilka postów wcześniej - to będę bardzo wdzięczny. Wg mnie jest to niemożliwe. Po co w takim razie narzucać sobie jakieś sztuczne ograniczenia, polegające na niemożności wystąpienia w rekordach bazy danych jakichś słów (np. "UNION")?
MalyKazio
Prawdę mówiąc ten temat jest strasznie zaśmiecony. Niby ktoś pisał, że ma być też pomoca dla początkujących a jedyną rzeczą przydatną dla mnie, jako bardzo początkującego, było słowo addslashes. Niestety nic poza tym... Ani jak to wykorzystać ani jak to potem wyciągnąć z bazy danych... trochę szkoda bo gdy założyłem temat z prośbą o prostą odpowiedź ( http://forum.php.pl/index.php?showtopic=40200 ) to mi się trochę "oberwało" a temat przyklejony to dla początkującego uzytkownika czarna magia.
Vengeance
MalyKazio: Znów ci się "oberwie" odemnie osobiście, bo skoro piszesz, że w tym temacie nic nie znalazłeś prócz addslashes() to śmię twierdzić, że czytać nie potrafisz i analizować kodów też nie!

Wiadomo, ile ludzi tyleż opini, dlatego w tym wątku znaleść można prawdziwe multum informacji o tym jak się zabezpieczyć. I nikt nie napiszę Ci jednego 100% sposobu - bo taki nie istnieje. Każdy ma jakieś zalety i wady, każda osoba faworyzuje innych.

Ktoś ci napiszę "używaj addslashes" a potem odnajdą lukę w tej funkcji i cała koncepcja bierze w łęb :]

Jeśli szukasz posegregowanych informacji to odsyłam do książek i artykułów. Tutaj jest forum, i nikt nie będzie edytował każdego postu tak aby początkujący mógł odczytać to jako książkę :/ A że się 5 stron czytać dokładnie ludziom nie chce.... no sorry.
the_foe
  1. <?php
  2. $win="\xA5\xC6\xCA\xA3\xD1\xD3\x8C\x8F\xAF\xB9\xE6\xEA\xB3\xF1\xF3\x9C\x9F\xBF";
  3. $iso="\xA1\xA6\xAC\xB1\xB6\xBC";
  4. $preg="/[^".$win.$iso."A-Za-z0-9_ -!@#\$%\^*\(\)\+=\{\}:;,.\\|\/\?]/s";
  5.  
  6. foreach ($_GET as $k=>$v){
  7. $_GET[$k]=preg_replace($preg,"\\1",$v);
  8. }
  9. foreach ($_POST as $k=>$v){
  10. $_POST[$k]=preg_replace($preg,"\\1",$v);
  11. }
  12. foreach ($_COOKIE as $k=>$v){
  13. $_COOKIE[$k]=preg_replace($preg,"\\1",$v);
  14. }
  15.  
  16. ?>


i po sprawie, nikt nie podskoczy
(mozna jeszcze trimowac, ale preg_replace nie przpusci chyba zero byte?)
kofaniutki_misio
Witam,

Czytałem posty na temat zabezpieczeń na stronie i zebrałem wszystko do kupy i wyszło mi coś takiego:

  1. <?
  2.  
  3. Function logs($msg) 
  4. { 
  5. global $HTTP_USER_AGENT, $_SERVER; 
  6. $url = sprintf("%s%s%s","http://",$_SERVER['HTTP_HOST'],$_SERVER['REQUEST_URI']); 
  7. $plik='http'; 
  8. if($_SERVER['HTTPS']=='on') 
  9.  { 
  10. $plik.='s'; 
  11. } 
  12. $plik.='://'.$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']; 
  13. if($_SERVER['QUERY_STRING']>' ') 
  14. { 
  15. $plik.='?'.$_SERVER['QUERY_STRING']; 
  16. } 
  17. if ($_SERVER["HTTP_X_FORWARDED_FOR"]) 
  18. { 
  19. if ($_SERVER["HTTP_CLIENT_IP"]) 
  20. { 
  21. $mz_user['proxy']=$_SERVER["HTTP_CLIENT_IP"]; 
  22. }else 
  23. { 
  24. $mz_user['proxy']=$_SERVER["REMOTE_ADDR"]; 
  25. } 
  26. $mz_user['ip']=$_SERVER["HTTP_X_FORWARDED_FOR"]; 
  27. }else 
  28. { 
  29. if ($_SERVER["HTTP_CLIENT_IP"]) 
  30. { 
  31. $mz_user['ip']=$_SERVER["HTTP_CLIENT_IP"]; 
  32. }else 
  33. { 
  34. $mz_user['ip']=$_SERVER["REMOTE_ADDR"]; 
  35. } 
  36. } 
  37. $h=@fopen('logs/logs.txt','a'); // pamietaj aby ustawic chmod na 622 
  38. @fwrite($h,date('H:i:s d-m-Y').'  ip: '.$mz_user['ip'].' proxy: '.$mz_user['proxy'].' plik: '.$plik.' url: '.$url.' atak na zmienną: $'.$msg.' '); 
  39. @fclose($h); 
  40. return $msg; 
  41. } 
  42.  
  43. //zabezpieczenia zmiennych
  44.  
  45. $akcja = $_GET['akcja'];
  46. $id = (int)$_GET['id'];
  47.  
  48. preg_replace( '%<script>%', '', $akcja);
  49. preg_replace( '%UNION%', '', $akcja);
  50.  
  51. $akcja = mysql_escape_string($akcja); 
  52.  
  53. if(!ereg ("[a-z_]", $akcja)) {
  54.  logs('akcja');
  55.  die('Naruszenie zasad bezpiczeństwa! Twoj adres IP został pobrany.');}
  56.  
  57. if(!ereg ("[0-9]", $id)) {
  58.  logs('id');
  59.  die('Naruszenie zasad bezpiczeństwa! Twoj adres IP został pobrany.');}
  60.  
  61.  
  62. //koniec zabezpiczeń zmiennych
  63.  
  64. ?>


funkcja logs wyrzuca do pliku bardzo przydatne informacje o gościu który próbuje cos namieszać. W postaci np:

"18:21:38 26-02-2006
ip: 127.0.0.1
proxy:
plik: http://localhost/~www/zabezpieczenia.php
url: http://localhost/~www/zabezpieczenia.php
atak na zmienną: $akcja"


Co tu jest niepotrzebne? a co źle!!

Dodam ze metoda ma pobierac z linku dwie zmienne $akcja i $id dla późniejszego użycia zapytania SQL. $akcja ma zawierać tylko ciąg małych literek a $id tylko liczbe.

Pozdrawiam.
vedeney
Sorry that not Polish,
but your functions are so funny smile.gif

e.g.
Why do you make global $_SERVER?questionmark.gif?
  1. <?php
  2. global $HTTP_USER_AGENT, $_SERVER;
  3. ?>

I can`t explane it.

  1. <?php
  2. preg_replace( '%UNION%', '', $akcja)
  3. ?>

AND
Kod
UNI/**/ON

OOPS tongue.gif

  1. <?php
  2.  
  3. foreach ($_GET as $k=>$v){
  4. $_GET[$k]=preg_replace($preg,"\\1",$v);
  5. }
  6. foreach ($_POST as $k=>$v){
  7. $_POST[$k]=preg_replace($preg,"\\1",$v);
  8. }
  9. foreach ($_COOKIE as $k=>$v){
  10. $_COOKIE[$k]=preg_replace($preg,"\\1",$v);
  11. }
  12. ?>

Have you ever here about $_REQUEST?questionmark.gif No?
kofaniutki_misio
hej vedeney. funkcja logs, jest przepisana. Global mozna wyrzucic. Ale czemu nie rozumiesz zastosowania tego kodu:

  1. <?php
  2. preg_replace( '%UNION%', '', $akcja);
  3. ?>


chcialem żeby nie mozna bylo użyć polecenia UNION.

  1. <?php
  2. http://mojastron.php?id=10 UNION SELECT TOP 1 TABLE_NAME FROM
  3. INFORMATION_SCHEMA.TABLES--
  4. ?>


wyciągania wszystkich tabel.
dr_bonzo
  1. <?php
  2. $age = $_GET[ 'age' ]; // pomiijam sprawdzanie czy to w ogole istnieje
  3. $name = $_GET['name' ];
  4.  
  5. $intAge = intval( $age )
  6. $strName = mysql_real_escape( $name ); // moglem pomylic nazwe funkcji
  7. $sql = "SELECT some_column FROM users WHERE age = " . $intAge . " AND name = '" . $strName . "'";
  8. ?>

i to tyle, zadne pregi, bo po co

gdy pod $age wstawisz "UNION .....blalba.... --"
$intAge == 0

gdy pod $name wstawisz "UNION .....blalba.... --"
sql wyglada tak
  1. SELECT some_column
  2. FROM users
  3. WHERE age = 0 AND name = 'UNION.... blalbba..--'


bylo to juz wspominane na poczatku (lub dalej tongue.gif) tego watka ale zginelo w masie postow probujacych to uzyskac.
vedeney
Ok! I`ve understand you, But your code didn`t prevent such hack as
Kod
http://mojastron.php?id=10 UN/**/ION SEL/**/ECT bla bla bla....

Which will be executed without any problems;
or
Kod
http://mojastron.php?id=BENCHMARK(1000000,MD5(NOW()))

or
Kod
http://mojastron.php?id=BENCHMARK(1000000,BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW()))))

It`s DOS through MySql-injection aaevil.gif
the_foe
Cytat(vedeney @ 2006-02-28 14:33:07)
  1. <?php
  2. foreach ($_GET as $k=>$v){
  3. $_GET[$k]=preg_replace($preg,"\\1",$v);
  4. }
  5. foreach ($_POST as $k=>$v){
  6. $_POST[$k]=preg_replace($preg,"\\1",$v);
  7. }
  8. foreach ($_COOKIE as $k=>$v){
  9. $_COOKIE[$k]=preg_replace($preg,"\\1",$v);
  10. }
  11. ?>

Have you ever here about  $_REQUEST?questionmark.gif No?

Yes, I've heard about $_REQUEST. But it's another stupid thing like register_globals on is. Let the manual speak:

Cytat
$_REQUEST
    Variables provided to the script via the GET, POST, and COOKIE input mechanisms, and which therefore cannot be trusted. The presence and order of variable inclusion in this array is defined according to the php variables_order configuration directive. This array has no direct analogue in versions of php prior to 4.1.0. See also import_request_variables().


Ain't simple?
if you use _REQUEST, as foreach source, you won't be able to set cookie, set GET, set POST with the same string name! You will be forced to remember about it all time.

Additionaly, here's no problem with my code, you can use _REQUEST in spite of. If you realy like it.
LamaMASTER
Cytat
zabezpieczenie w stylu:
  1. <?php
  2. $query = 'update `uzytkownicy` set `pole`="'.$dane.'" where `id`="'.$id.'";';
  3. ?>
to jak juz powiedziano zadne zabezpieczenie a pozatym zmnijsza wydajnosc zapytania, umieszczanie wartosci liczbowych w momiedzy " " powiduje iz MySQL mysli ze ma do czynienia ze znakami (stringami) i niepotzrebnie musi konwertowac typy.

Bzdura. Zapisz taki jest jak najbardziej szybszy, bo kod nie jest parsowany (bo jest w ' '), a zapisując zmienną w cudzysłowiach w kodzie ("coś tam $zmienna") powoduje parsowanie kodu i dłuższe sprawdzanie zmiennych. Nie wprowadzajcie ludzi w błąd.
Cytat
przyklad:
  1. <?php
  2.  
  3. $sql = mysql_query("SELECT * FROM news WHERE id=".$_GET['id']);
  4.  
  5. ?>


wywołanie normalne:
Kod
news.php?id=1
news.php?id=25
itd


wywołanie zmodyfikowane przez kogostam
np.
Kod
news.php?id=1;DROP%20TABLE%20news;

Ee tam, zonwu zonk, przecież mysql_query pozwala na wysłanie tylko jednego zapytania, więc to co pokazałeś nic nie da.

Więcej tematu czytać mi się nie chciało, ale mam nadzieję, że nie ma tam dalej więcej bzdur winksmiley.jpg
Pawel86
A takie rozwiazanie:
  1. <?php
  2.  
  3.  function ParseText(&$Text)
  4.    {
  5.       $Text=trim($Text);
  6.       if(get_magic_quotes_gpc())
  7.       {
  8.          $Text = stripslashes($Text);
  9.       }
  10.       $Text = htmlspecialchars($Text, ENT_QUOTES);
  11.       $Text = str_replace('\\0','\\\\0',$Text);
  12.       $Text = str_replace('\\t','\\\\t',$Text);
  13.       $Text = str_replace('\\n','\\\\n',$Text);
  14.       $Text = str_replace('\\r','\\\\r',$Text);
  15.       return $Text;
  16.    }
  17.  
  18.    function SecureSuperglobalsTables()
  19.    {
  20.       $this->SecureTable($_POST);
  21.       $this->SecureTable($_GET);
  22.       .....
  23.    }
  24.  
  25.    function SecureTable(&$Table)
  26.    {
  27.       if(!is_array($Table)) return false;
  28.       foreach($Table as $Id=>$Row)
  29.       {
  30.          if(is_array($Row))
  31.          {
  32.             $this->SecureTable($Table[$Id]);
  33.          }
  34.          else $this->ParseText($Table[$Id]);
  35.       }
  36.    }
  37.  
  38. ?>

XSS-y wykluczone, ' i " zamieniane na bezpieczne smile.gif da sie to obejsc?
Janek111
Mam taki problem:
Jesli uzyje mysql_real_escape_string i jesli jest wlaczone magic quotes to otrzymam przykladowo ze stringu jakis'wyraz, string jakis///'wyraz. Moglbym zrobic tak:
  1. <?php
  2.  
  3.    $string = mysql_real_escape_string($string);
  4.  
  5. ?>

tylko, że wtedy, jeśli jest wlaczone magic_quotes to stosowanie tej funkcji jest bezsensu - gdy uzyje addslashes wyjdzie na to samo.
jak mozna rozwiazac ten problem?? Moze poprostu zostac przy addslashes ? smile.gif
Jarod
Cytat(ktuvok @ 14.05.2005, 19:58 ) *
Dorzucę się do tego wątku i powiem, że moim zdaniem najlepszym zabezpieczeniem jest:

1. ustawienie w php.ini opcji get_magic_quotes_gpc na ON

2. stosowana równolegle z powyższym funkcja czyszcząca otrzymane dane - od razu uprzedzam, że wbrew nazwie nie dotyczy ona tylko danych przesyłanych metodą POST:
  1. <?php
  2.  
  3. function OczyscPost($Zmienna, $Rozmiar)
  4. {
  5. {
  6. $Zmienna = stripslashes($Zmienna);
  7. }
  8. $Zmienna = trim(strip_tags(str_replace(""", "", $Zmienna)));
  9. $Zmienna = substr(str_replace("'","", $Zmienna),0,$Rozmiar);
  10. $Zmienna = sprintf("%s",$Zmienna);
  11. return $Zmienna;
  12. }
  13.  
  14. ?>


3. Funkcja zapewniająca dodatkowe filtrowanie dla identyfikatorów, przekazywanych w URL'u:
  1. <?php
  2.  
  3. function DoCyfry($Zmienna)
  4. {
  5. $Zmienna = intval($Zmienna);
  6. if(is_int($Zmienna))
  7. {
  8. return $Zmienna;
  9. }
  10. else
  11. {
  12. return 0;
  13. }
  14. }
  15.  
  16. ?>


Zastosowanie:
  1. <?php
  2.  
  3. $Nazwisko = OczyscPost($_POST['Nazwisko'], 40);
  4. $ID = DoCyfry(OczyscPost($_GET['ID'], 10));
  5.  
  6. ?>


Jakieś uwagi?

Pozdrawiam,
K



Hmm.. Do czego jest właściwie to UNION? Może ktoś poda przykład? Bo ja się nie zetknąłem z takim zapytaniem
em1X
A szukac to nie potrafisz?

  1. SELECT * FROM text UNION
  2. SELECT * FROM news


czyli sklejanie dwoch zapytan do bazy
Jarod
Próbując podsumować dyskusję, możnaby powiedzieć, że aby zabezpieczyć się przed SQL Injection trzeba filtrować każdą zmienną przychodzącą, czyli:

1. Jeśli spodziewamy się liczby to każdą zmienną traktujemy
  1. <?php
  2. intval($zmienna);
  3. ?>


2. Jeśli spodziewamy się ciągu to stosujemy
  1. <?php
  2. addslashes($zmienna);
  3. ?>


Czy to wystarczy?


A co w takim przypadku. Mamy spis użytkowników w systemie, który załóżmy że wygląda tak.



Przy każdym użytkowniku jest link z opcją usunięcia konta. Z tym linkiem, przesyłany jest numer ID danego klienta, żeby wiedzieć, którego klienta usunąć z bazy (ID jest kluczem głównym).

Teraz ktoś może zmodyfikować URL, np zamiast usunąć konto 2 (http://jakasstrona/usun.php&id=2) może wpisać dowolny inny numer, np (http://jakasstrona/usun.php&id=1) i skasuje konto admina.

Jak się przed tym zabezpieczyć?

Stosuję w każdym skrypcie funkcję weryfikującą, któa sprawdza czy użytkownik jest zalogowany i czy ma odpowiednie prawa. Ale wiem, że to nie wystarczy.
Termit_
Wówczas zawsze należy robić dodatkowe confirmy - formularze typu "Czy na pewno chcesz.... [ TAK ] [ NIE ]"
Jarod
Cytat(Termit_ @ 3.06.2006, 18:58 ) *
Wówczas zawsze należy robić dodatkowe confirmy - formularze typu "Czy na pewno chcesz.... [ TAK ] [ NIE ]"



Stosuję..
thornag
Wedlug mnie mozesz jedynie sprawdzic czy Id nie jest elementem wyznaczonego przez Ciebie a niedozwolonego zbioru.

Zostaja jedynie confirmy, tutaj wszystko wydaje sie kwestia dostepu. Jesli dasz dostep do tego panelu, to po co meczyc sie ze zmiana URLa skoro wystarczy kliknac smile.gif No chyba ze kazdy uzytkownik ma inne prawa i innych uzytkownikow ktorych moze edytowac (taka relacja su/admin/sub-admin smile.gif wtedy wspommniany przezemnie zbior nalezalo by uzaleznic od uzytkowanika.
eai
@J4r0d Bardzo prosto się można zabezpieczyć

Zastosuj sume kontrolną. jakasstrona/usun.php&id=2&checksum=f3sxSdf32vx3sGx

Napisz własny wzór generowania sumy kontrolnej oraz jej sprawdzania.
Np.

  1. <?php
  2.  
  3. function checksum ($id) {
  4.  
  5. return substr(md5('aXq23' . $id), 1, 3); 
  6.  
  7. }
  8.  
  9. if (checksum ($id) == $_GET['checksum']) {
  10.  // .... Usuwamy itp...
  11.  
  12.  }
  13. ?>
Turgon
Zgadzam się z Eai. Ja stosuje sumy plus sesje oraz grupy uprawnień. Jeśli użytkownik nie ma odpowiedniego levela odrazu acces denied w głównym pliku administracyjnym. Nie pozwalam nawet dojść do uruchomienia reszty winksmiley.jpg .
Co do tego usuwania adminów to banał jest. Dodajemy do filtrowania requestów :
  1. <?php
  2. if($_GET['id'] == '1')
  3. {
  4. return false;
  5. }
  6. ?>


i gotowe smile.gif . Czyż nie trudne ?
Po za tym thornag używaj głównego pliku administracyjnego przez który jest jedyna możliwość użycia funkcji ACP etc. . To dodatkowe zabezpieczenie i trochę utrudnia życie, ale warto. Dodatkowa bariera dla włamywacza...
Jarod
Cytat(eai @ 1.08.2006, 23:19 ) *
@J4r0d Bardzo prosto się można zabezpieczyć

Zastosuj sume kontrolną. jakasstrona/usun.php&id=2&checksum=f3sxSdf32vx3sGx

Napisz własny wzór generowania sumy kontrolnej oraz jej sprawdzania.
Np.

  1. <?php
  2.  
  3. function checksum ($id) {
  4.  
  5. return substr(md5('aXq23' . $id), 1, 3); 
  6.  
  7. }
  8.  
  9. if (checksum ($id) == $_GET['checksum']) {
  10.  // .... Usuwamy itp...
  11.  
  12.  }
  13. ?>


Generujesz - ok. A w jaki sposób chcesz przetrzymywać tą sume i gdzie?
eai
@J4r0d Przecież to jest jeszcze prostsze smile.gif

Przykład:

checksum.php
  1. <?php
  2.  
  3. function checksum ($id) {
  4. return substr(md5('aXq23' . $id), 1, 3); 
  5. }
  6.  
  7. ?>


admin.php
  1. <?php
  2.  
  3. //...
  4.  
  5. include 'checksum.php';
  6.  
  7.  
  8. function foo () { //Jakas tam funkcja generujaca linki do panelu admina bla bla bla...
  9. $row = ...; //Tablica np. wynik z mysql
  10. echo 'strona.com?usun=' . $row['id'] . '&checksum=' . checksum($row['id'];
  11.  }
  12.  
  13.  
  14. function delete () {
  15. if(checksum ($_GET['id']) == $_GET['checksum']) {
  16.  
  17. // Usuwasz
  18.  
  19. }
  20. }
  21.  ?>


Prościej się wytłumaczyć nie da smile.gif
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.