Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Polskie znaki w loginie/haśle - testy przeprowadzone
Forum PHP.pl > Forum > PHP
Apocalyptiq
Jakie są ewentualne niebezpieczeństwa w związku z daniem możliwości używania polskich znaków w loginie i haśle? I mailu (chociaż nie wiem, czy w adresach e-mail mogą występować polskie znaki?). Narazie wprowadzany login i hasło tak sprawdzam:
Kod
preg_match('|[^0-9a-zA-Z_-]+|',$_POST['pwd']))

I czy może odblokowanie wszystich znaków - razem z !@$#@%~!~` i spacją (w loginie i haśle) nie spowoduje jakichś niezgodności z bazą?
Proszę o Wasze opinie.
Virti
W bazie hasła zapisuj zahashowane, np md5, sha1 to nie powinieneś mieć problemów od strony bazy.

W sumie to sam jestem ciekaw dlaczego z reguły nie zezwala się na używanie polskich znaków w loginach, więc częściowo dołączam się do pytania. winksmiley.jpg
Apocalyptiq
Przeprowadziłem małe testy - wywaliłem preg_match'owanie logina oraz hasła i testowałem różne znaki - czy po ich wpisaniu w login/hasło nie będzie problemów z rejestracją, czy będzie można się później zalogować i czy login będzie dobrze wyświetlany na stronie. Hasło przed zapisaniem do bazy jest hashowane. Kodowanie w bazie: utf8_unicode_ci, na stronie - utf-8. Oto wyniki testów:
Cytat
`~!@#$%^&*/()
rejestracja: OK
logowanie: OK
wyświetlanie na stronie: OK

-=_+[] {};:,.?<>|*
(tam w środku jest też spacja)
rejestracja: OK
logowanie: OK
wyświetlanie na stronie: OK

'"\
rejestracja: przez strlen interpetowane jako 6 znaków - \'\"\\ (przynajmniej u mnie, to zależy chyba od tego, czy magic_quotes'owanie są włączane)
logowanie: OK
wyświetlanie na stronie: wyświetlane jako \'\"\\ - wystarczy dać wyświetlanie w stripslashes (wywala slashe) i będzie się dobrze wyświetlać (no i przy sprawdzaniu długości ciągu, poprzez strlen, sprawdzać tak: strlen(stripslashes($_POST['login'])). Ale dając stripslashes do bazy (wyczyszczenie ze slashy) musimy być pewni, że mamy dobrze zabezpieczoną komunikację z bazą - bindowanie zmiennych używanych w zapytaniach SQL (np. przy pomocy PDO), które może przesłać użytkownik. Można zapisywać do bazy bez wywalania slashy (chociaż stosując bindowanie rozsądniej jest wywalać slashe), a tylko przy wyświetlaniu na stronie te slashe wywalać, bo jak już zaznaczyłem - z logowaniem nie ma kłopotów. Ale z drugiej strony, jeżeli mamy w bazie limit znaków na np. login, to jeżeli w loginie będzie w sumie 20 znaków (przy limicie 20) i w tym np. jeden znak cudzysłowia, skrypt będzie chciał zapisać do bazy ciąg z 21 znakami, więc prawdopodobnie zapisze pierwszych 20, co z kolei przełoży się na niemożność zalogowania się. Co do hasła - jeżeli jest hashowane, nie ma problemu - wywalamy slashe, hashujemy hasło i zapisujemy do bazy. Co do limitu zero kłopotu - nie wiem nawet jaki, i czy jest limit ciągu, który można shashować np. w md5, ale zapewniam że tego limitu (jeżeli istnieje) przy takim czymś nie przekroczymy biggrin.gif

łńćżźąśóęĘÓĄŚŁŻŹĆŃ
rejestracja: Każdy z tych znaków przez funkcję strlen interpretowany jest jako 2 znaki - i poprawnie, bo w utf-8 zapisywane one są jako dwa znaki. Mam blokadę na długość loginu/hasła w php, więc zarejestrowanie nie powiodło się - wywaliło komunikat o tym, że login/hasło za długie. Ale istnieje nieco rozszerzona funkcja strlen - mb_strlen. Przyjmuje dwa argumenty - ciąg to sprawdzenia i kodowanie. Jeżeli mamy stronę i bazę na utf-8, podajemy jako drugi argument "utf-8" i już ładnie polskie znaki interpetowane są jako pojedyncze znaki smile.gif Ale wtedy w bazie trzebaby powiększyć aktualny limit 2x - gdyby ktoś wpisał 20 polskich znaków (lub ',",\), w bazie potrzebaby miejsca na 40 znaków. A jeżeli chcielibyśmy udostępnić znaki więcej niż 2 bitowe (np. chińskie) - najlepiej dać limit na $naszlimit*8 (w UTF-8 - jak sama nazwa mówi, mogą w nim być max. 8-bitowe znaki), np. w moim przypadku - 160.
logowanie: OK
wyświetlanie na stronie: OK


Wnioski:
Problemy są tylko z polskimi znakami i znakami ['\"], lecz tak jak to opisałem powyżej - wszystko to można obejść, pamiętając jednocześnie o ustawieniu dobrego limitu znaków w bazie. Można też po prostu zdjąć limity - ustawić pole login na TEXT, a nie VARCHAR albo CHAR z określonym limitem. Co do różnic między tymi trzema rodzajami troche poczytałem w necie, no i prawdopodobnie wyszukiwanie w bazie przy pomocy LIKE dla VARCHAR'a i pewnie CHAR'a jest szybsze niż w przypadku TEXT (choć nie jestem pewien). No i pola TEXT nie można zindeksować, w przeciwieństwie do VARCHAR i CHAR.

Testami tymi dowiodłem, że nie trzeba walidować ani hasła, ani loginu, jeżeli się wszystkiego dopilnuje smile.gif

Komentarze mile widziane winksmiley.jpg


Jeszcze mam pytanie co do bezpieczeństwa - czy używając PDO i bindując dane, na które ma wpływ użytkownik, można już do bazy wprowadzać dane po stripslash'owaniu (po wywaleniu slashów)? PDO ma chyba jakieś zabezpieczenia od tego.
dr_bonzo
Jak bindujesz dane w PDO to "cie-wszystko-wali", slashe wywalasz TYLKO jesli cos (magic-quotes) niepotrzebnie ci je dodalo.
Apocalyptiq
Dzięki bonzo, potrzebowałem potwierdzenia biggrin.gif
Ale z tego co widzę, PDO automatycznie dodaje te slashe w bazie (jeżeli dodajemy jakieś ciągi znaków do bazy z '"\). Czy po prostu musi tak robić, żeby było bezpiecznie?
dr_bonzo
PDO nie dodaje slashy w bazie - nie robi sie tego.
Slasha sie dodaje zeby zapytanie SQL bylo poprawne:

  1. <?php
  2. $name = "aaaaaa'aaaaa";
  3. $sql = "SELECT * FROM costam WHERE name LIKE '%" . $name . "%' "
  4.  
  5. da name:
  6. $sql == "SELECT * FROM costam WHERE name LIKE '%aaaaaa'aaaaa%' "
  7. ?>


czyli bledne zapytanie.

Dlatego uzywajac mysql_* (tzn nie korzystajac z prepared statements) dodajesz slashe.
PDO zrobi to sam, wiec podajesz mu dane normalnie
Apocalyptiq
No tak, pomyliłem się smile.gif

Poszperałem w necie, i znalazłem na tym forum napisaną przez kogoś funkcję usuwającą slashe, jeżeli magic_quotes_gpc są włączone (no bo jeżeli nie są włączone, to np. z "haha :\')" zostanie usunięty slash). A czasami nie mamy możliwości wyłączenia magic_quotes_gpc (uprawnienia).
Kod
function delSlashes($string){
     return ini_get('magic_quotes_gpc')?trim(stripslashes($string)):trim($string);
}

(przy okazji wywala niepotrzebne spacje smile.gif )

Dzięki bonzo za pomoc winksmiley.jpg
dr_bonzo
A co jak ktos ma haslo zawierajace spacje na poczatku/koncu?
Apocalyptiq
Hm, jako hasło faktycznie takie coś działa - ustawiłem hasło jako 3 spacje, i logując się tylko 3 spacje działają smile.gif
Ale co do loginu - wtedy istniałaby możliwość ustawienia sobie loginu jako trzech spacji (oczywiście zależne od naszego minimalnego limitu), a to jest trochę bez sensu smile.gif Ale nawet przy tych trzech spacjach logowanie działa! biggrin.gif Myślę że rozsądnie byłoby trim'ować login, a hasło - nie (spacja też jakiś znak winksmiley.jpg ). No i należałoby też trimować mail - i tak spacje z tyłu/przodu w mailach nie występują.

Dzięki bonzo za uwage smile.gif


A co sądzicie o dokładnej walidacji już po stronie klienta (JS) a nie serwera (PHP)? W JS aktualnie sprawdzam tylko, czy wszystkie pola wypełnione, i czy ilość znaków nie przekracza limitów. Preg_matchowanie robię dopiero po stronie serwera, w php. Ale z tego co czytałem, w js istnieje funkcja match. Warto też w JS przewalidować dokładnie formularz?
Np. u mnie w formularzu rejestracji wkurzające jest troche to, że jak się zrobi jakiś błąd - pojawia się komunikat o błędzie i czysty formularz - wszystko trzeba wypełniać od nowa... Wiecie może jak temu zapobiec? Może właśnie w JS dokładnie sprawdzać? Albo w cookiesach/sessionie przechowywać dane wprowadzane do formularzy?
erix
Cytat
A co sądzicie o dokładnej walidacji już po stronie klienta (JS) a nie serwera (PHP)? W JS aktualnie sprawdzam tylko, czy wszystkie pola wypełnione, i czy ilość znaków nie przekracza limitów.

Pewnie, że warto. Większość użytkowników ma włączony JavaScript, to nie dość, że zmniejszysz obciążenie serwera, bo w większości przypadków przerzucisz problem walidacji na przeglądarkę usera, zmniejszysz transfer (bo nie będzie trzeba ściągac stron z komunikatami o błędach) i nie będzie właśnie problemu pustych pól.
Apocalyptiq
Hm, ewentualnych skrajnych spacji w loginie/mailu nie trzeba nawet wywalać, jeżeli mamy w inpucie ustawiony maxlength (bo chyba nie istnieje w JS funcja trim, chociaż można ją sobie łatwo napisać). Ale należałoby kasować użytkownikowi spacje, jeżeli od nich chce rozpocząć login/mail - wtedy nie będzie kłopotów z limitem. No i muszę poczytać o funkcji match() w JS smile.gif Narazie tylko tak na szybko próbowałem - skopiowałem ciąg walidacji adresu e-mail ze skryptu php do js, no i nie działał - czyli php'owski preg_match i js'owski match różnią się interpetacją tego ciągu szukania?
qbatoja
laickie rozumowanie panowie.

walidacja serwerowa jest glowna walidacja i nigdy nie moze byc opuszczana. js moze byc jedynie dodatkiem.

a co jesli ktos podrobi formularz?
a co jesli ktos wylaczy js?

w wiekszosci frameworkow jest cos takiego jak flash messages. czyli zapisujesz dane do sesji i po jednym hopie sa kasowane, polecam wykorzystanie tego
Apocalyptiq
qbatoja -> my mówimy tylko o dodatkowej walidacji, chociażby po to, aby gdy użytkownik coś nie tak wpisze, nie czyściło mu formularza, tylko aby wyskoczył mu komunikat z JS, że coś nie tak - jasne, że walidacja po stronie serwera to podstawa.
ucho
Osobiście proponowałbym wycinać spacje i inne białe znaki - jeśli hasło przychodzi mailem (np. wygenerowane przez automat gdy ktoś swojego zapomniał) to często zdarza się skopiować jedną czy dwie spacje z którejś strony, a później człowiek się zastanawia dlaczego nowe hasło nie działa smile.gif
Virti
trim-owanie hasła przed wysłaniem do bazy (czy to zapis czy to sprawdzenie) w sumie załatwi sprawę. Nawet jeżeli specjalnie na początku/końcu hasła były spacje, zostaną one wycięte, co w sumie nie robi różnicy, dopóki nie zmienia się mechanizmu, który te hasła sprawdza.
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.