Każde pole w tabeli MySQL ma określony typ. Dla varchar możemy zdefiniować maksymalną długość przechowywanego tekstu. Ale co w przypadku, gdy użytkownik prześle dłuższy ciąg? #od0dopentestera
W przypadku konstrukcji INSERT dane zostaną automatycznie przycięte do maksymalnej długości danego pola. To nic odkrywczego, ale mało kto wie, że standardowo baza ignoruje spacje na końcu wyrazu:
SELECT * FROM users WHERE login = "admin "
Dostaniemy takie same wyniki jak dla zapytania bez białych znaków na końcu. Te dwie ciekawostki połączone razem mogą doprowadzić do błędu SQL Truncation. Chociażby podczas logowania użytkowników.
Załóżmy, że maksymalna długość pola login to 10 znaków. Podczas tworzenia nowego użytkownika najpierw sprawdzamy, czy osoba o takich danych już nie istnieje w bazie. Jeżeli nie - tworzymy nowy rekord.
Nie możemy użyć wartości admin ze spacjami, ponieważ są one ignorowane w konstrukcji SELECT. A taki użytkownik już istnieje. A co gdyby spróbować dłuższy rekord? Taki, którego pierwsze 10 znaków kończy się spacjami a reszta to nieistotne dane? Chociażby **admindalszy_ciąg**? Wspomniany wyżej SELECT nie zwróci żadnego rekordu dla takiego loginu. Podczas dodawania wpisu natomiast zostanie on przycięty do 10 znaków.
Tym samym pojawią się dwa rekordy admin - jeden z białymi znakami drugi bez. Jeżeli teraz aplikacja sprawdza uprawnienia użytkowników na podstawie loginu - istnieje spora szansa, że również ignoruje spacje. Możemy zatem zalogować się jako administrator używając swojego hasła.
Jak można rozwiązać ten problem? Używać indeksu UNIQUE, który zapewnia brak duplikatów.
@diogene: a tak szczerze, to czemu zastępować to PHP? mam wrażenie, że przez łatwy poziom wejścia każdy mocno śmieszkuje "HEHE php to guwno", natomiast trzeba sprawiedliwie przyznać, że backend napisany w php porządnie, a nie na #!$%@? przez "studęta", jest zwyczajnie w porządku, albo takie Symfony 4 ( ͡°͜ʖ͡°) ale nie neguje pythona/ruby/go/innych
@LegoCiemnyLas: yyy, albo nie zrozumiałem pytania, albo jednak tak nie jest.
Stworzyłem testową tabelę - typy danych varchar i char, wprowadziłem w jednym wierszu dane ze spacją, w drugim bez (wiem, że nie o to chodziło, ale to już dodatkowe). Przy insercie oczywiście przycięło, co widać po length.
Potem robię odpytkę raz dla obu kolumn ze spacjami, raz bez - w obu przypadkach te same wyniki. Ustawienia standardowe, collate LATIN wiadomo
@pharmaz0ne: Zależy jak jest zaprojektowana baza. Na filmie podaje nieco zmieniony przykład. Tam uprawnienia przetrzymywane są w osobnej tabeli, ale ponownie wykorzystuje się tam login jako klucz główny a nie id z innej tabeli (tak tak, wiem że to naciągane – to tylko przykład).
@Lehu31: Coś mi nie pasuje w tym Twoim teście. W insercie masz dwa razy id podane jako 2, a w selecie zwraca Ci 1 i 2. Wyjaśnisz dlaczego tak się dzieje?
@DrwalPuchacz: Wiesz co, najpierw wrzuciłem pierwszy wiersz, potem pomyślałem, aby wrzucić ten drugi, także nie wykonywałem dokładnie takiego inserta jak na screenie, ale pomyślałem, że na potrzeby przedstawienia tematu na wykopie posklejam wszystko w jedno, aby było widać każdy krok, który wykonałem - no i zrobiłem literówkę, a właściwie liczbówkę ;).
Poprawnie więc powinno być tak:
create table testowatabela (id int, tekst char(10), testowavar varchar(10))
Zrobiłem swój test na MSSQL i o ile nie ma dla niego znaczenia czy wyszykujemy: SELECT * FROM Table WHERE Login = 'admin' czy SELECT * FROM Table WHERE Login = 'admin ' i zwróci te same wyniki. To już przy próbie inserta 'admin 123' gdy pole ma ograniczenie 10 znaków zwróci errora przy domyślnych ustawieniach.
@DrwalPuchacz: No tak, to było oczywiste, że odrzuci (MySQL mnie nie obchodzi jak coś, bo to syf) - w zasadzie jakby tak nie było, to nie miałoby to sensu ;). Wszak to też jest pewien constraint ;).
Dla
varcharmożemy zdefiniować maksymalną długość przechowywanego tekstu.Ale co w przypadku, gdy użytkownik prześle dłuższy ciąg? #od0dopentestera
W przypadku konstrukcji
INSERTdane zostaną automatycznie przycięte do maksymalnej długości danego pola.To nic odkrywczego, ale mało kto wie, że standardowo baza ignoruje spacje na końcu wyrazu:
SELECT * FROM users WHERE login = "admin "
Dostaniemy takie same wyniki jak dla zapytania bez białych znaków na końcu.
Te dwie ciekawostki połączone razem mogą doprowadzić do błędu SQL Truncation.
Chociażby podczas logowania użytkowników.
Załóżmy, że maksymalna długość pola
loginto 10 znaków.Podczas tworzenia nowego użytkownika najpierw sprawdzamy, czy osoba o takich danych już nie istnieje w bazie.
Jeżeli nie - tworzymy nowy rekord.
Nie możemy użyć wartości
adminze spacjami, ponieważ są one ignorowane w konstrukcjiSELECT.A taki użytkownik już istnieje. A co gdyby spróbować dłuższy rekord?
Taki, którego pierwsze 10 znaków kończy się spacjami a reszta to nieistotne dane?
Chociażby **admindalszy_ciąg**?
Wspomniany wyżej SELECT nie zwróci żadnego rekordu dla takiego loginu.
Podczas dodawania wpisu natomiast zostanie on przycięty do 10 znaków.
Tym samym pojawią się dwa rekordy
admin- jeden z białymi znakami drugi bez.Jeżeli teraz aplikacja sprawdza uprawnienia użytkowników na podstawie loginu - istnieje spora szansa, że również ignoruje spacje.
Możemy zatem zalogować się jako administrator używając swojego hasła.
Jak można rozwiązać ten problem?
Używać indeksu
UNIQUE, który zapewnia brak duplikatów.Interesujesz się bezpieczeństwem? Posłuchaj podcastu na Google i Apple Podcasts oraz Spotify i Anchor.
Subskrybuj kanał na YouTube
Masz pytanie na temat security? Zadaj je na grupie od 0 do pentestera na Facebooku.
Jeżeli chcesz być wołany do podobnych wpisów na Mirko dodaj się do Mirkolisty.
#bezpieczenstwo #programowanie #informatyka #it #nauka #technologia #ciekawostki #podcast #swiat #gruparatowaniapoziomu #biznes #security
ale nie neguje pythona/ruby/go/innych
dzieki :)
Stworzyłem testową tabelę - typy danych varchar i char, wprowadziłem w jednym wierszu dane ze spacją, w drugim bez (wiem, że nie o to chodziło, ale to już dodatkowe). Przy insercie oczywiście przycięło, co widać po length.
Potem robię odpytkę raz dla obu kolumn ze spacjami, raz bez - w obu przypadkach te same wyniki. Ustawienia standardowe, collate LATIN wiadomo
@noelo_cohelo: Bo to tylko przykład a nie prawdziwa aplikacja.
Chociaż ten błąd występował w przeszłości chociażby w WordPress
@dybligliniaczek: Tak, to udokumentowane zachowanie. Więcej tutaj.
@matkakrawcowaojciecstefan: Dzięki za miłe słowa.
@Noct: Podatność stara, ale rzadko opisywana.
Tam uprawnienia przetrzymywane są w osobnej tabeli, ale ponownie wykorzystuje się tam login jako klucz główny a nie id z innej tabeli (tak tak, wiem że to naciągane – to tylko przykład).
@Lehu31: A robisz to na MySQL? Bo po interfejsie wygląda mi na SSMS, więc MS SQL Server?
SELECT * FROM users WHERE login = 'admin ';
nie zwróci wyników"
Poprawnie więc powinno być tak:
create table testowatabela (id int, tekst char(10), testowavar varchar(10))
insert into testowatabela
values
SELECT * FROM Table WHERE Login = 'admin'
czy
SELECT * FROM Table WHERE Login = 'admin '
i zwróci te same wyniki. To już przy próbie inserta 'admin 123' gdy pole ma ograniczenie 10 znaków zwróci errora przy domyślnych ustawieniach.