Walidacja imienia i nazwiska dla pola tekstowego

0

Cześć!

Tworzę w JS skrypt do walidacji danych wprowadzanych przez użytkownika. O ile walidacja pól formularza typu telefon jest oczywista, to zastanawiam się nad walidacją pól tekstowych na nazwisko czy nazwę ulicy.

Wymyśliłem takie wyrażenie regularne, które powinno skutecznie odsiewać zamiar użycia SQL injection oraz XSS.

const TextRegex = /^[a-zA-ZąĄćĆęĘóÓłŁśŚźŹżŻńŃ0-9.,/”“"'&() -"\n"]*$/;

Co o tym sądzicie? Coś dodać? Jest to w miarę skuteczne? Oczywiście walidacja po stronie backend też będzie.
Z tego co wiem, to najbardziej "niebezpieczne" są = oraz ;

3

SQL injection to nie zagadnienie po linii walidacji, bo nazwisko O'Hara jest w 100% legalne - tylko właściwe przygotowanie danych do operacji bazodanowej.

Dobrze, że stawiasz sobie takie pytania, ale implementacja mi się nie podoba.

0

Co jest złego w tym, że na etapie wprowadzania danych "przypominam" użytkownikowi, by numer telefonu wprowadził w formacie 123456789 albo żeby nie podawał nazwiska ko=wal;ski ?

2
MrocznyRycerz napisał(a):

Co jest złego w tym, że na etapie wprowadzania danych "przypominam" użytkownikowi, by numer telefonu wprowadził w formacie 123456789 albo żeby nie podawał nazwiska ko=wal;ski ?

Ale w tym momencie zmieniasz argumentację.

Czym innym jest nazwisko ogólnie "poprawne", majace szanse wystąpić w realu, a czym innym wszelkie injection.
To są odmienne zagadnienia, w odmienny sposób obsługiwane.

1

Czyli prawidłowo powinienem napisać, że zabezpieczenie przed SQL injection zaimplementuję po stronie backendu?

2
MrocznyRycerz napisał(a):

Czyli prawidłowo powinienem napisać, że zabezpieczenie przed SQL injection zaimplementuję po stronie backendu?

tak
Ale nawet tam, w zupełnie innej warstwie niż (backendowa) walidacja. To są odmienne sprawy.

MrocznyRycerz napisał(a):

Z tego co wiem, to najbardziej "niebezpieczne" są = oraz ;

Apostrofy chude i grube jak najbardziej, zalezy jaką głupote wymyślił programista lub "programista"
Niosące ryzyko w backendach C# są {} (w złośliwym scenariuszy w Javie też), w innych pewnie znajdzie złosliwy scenariusz na %, ja testuję sprawnosć programistów znaczkami &<> każdym oddzielnie.
Nie zawsze chodzi o injection dające przejecie maszyny, ale czasem zje...e userowi operacji.

Na jednym ze sklepów mój NIP sie "zaklinował" po głupiej walidacji (imię niewymagane na JS, ale wymagane na myswlu - nawiasem mówiać dostałem piekną strukturę tabeli w wyjatku), niby jest (widocznie sie dzieś zapisał) ale zarazem go nie ma. Nie będę juz ich klientem. kto stracił ?

Jest to TOTALNIE nie rozumiane, np masowe spisywanie przez PHPowców do bazy przez "zabezpieczenie" htmlentity
Pozór bezpieczeństwa jest gorszy niż jego brak.

0

Możesz podać przykład, kiedy apostrofy są szkodliwe?
Bo co jeżeli ktoś w formularzu wprowadzi taką nazwę firmy: Przedsiębiorstwo "ZrobięDobrzeSoftware".

1
MrocznyRycerz napisał(a):

Co o tym sądzicie? Coś dodać? Jest to w miarę skuteczne? Oczywiście walidacja po stronie backend też będzie.
Z tego co wiem, to najbardziej "niebezpieczne" są = oraz ;

Potencjalnie niebezpieczne są każde znaki specjalne w SQL'u, dlatego że one mogą zostać zinterpretowane inaczej niż plain text.

To co powinieneś zrobić, to:

  • Napisz swoją warstwę persystencji, tak żeby KAŻDY znak mógł być bezpiecznie dodany
  • Osobno, zrób sobie walidację formularza, jak chcesz
MrocznyRycerz napisał(a):

Możesz podać przykład, kiedy apostrofy są szkodliwe?
Bo co jeżeli ktoś w formularzu wprowadzi taką nazwę firmy: Przedsiębiorstwo "ZrobięDobrzeSoftware".

Np

const companyName = `Przedsiębiorstwo "ZrobięDobrzeSoftware"`;

const sql = `INSERT INTO table VALUES("${companyName}");`

@MrocznyRycerz: w skrócie, chodzi po prostu o to że SQL oraz plaintext to są inne wartości, które rządzą się innymi prawami, i nie możesz tak po prostu sobie dodać jednego do drugiego, musisz je w umiejętny sposób połączyć. Jednym z takich umiejętnych łączeń jest escape każdego znaku SQL'owego, tak żeby już nie był SQL'owym znakiem. Innym byłby np Prepared Statements.

2
MrocznyRycerz napisał(a):
const TextRegex = /^[a-zA-ZąĄćĆęĘóÓłŁśŚźŹżŻńŃ0-9.,/”“"'&() -"\n"]*$/;

Co do samej walidacji znaków. Jak apka jest tylko na rynek polski to nie ma problemu. Ale jak przyjdzie Niemiec z Ä to może byc problem. Często języki mają rozszeżenie do regexpów żeby łąpac wszystkie litery, a nie tylko A-Za-z. Dla JS (nie jestem programistą JSa) znalazłem na szybko tylko taki hak return char.toLowerCase() !== char.toUpperCase(); XD No, ale tu trzeba sprawdzać po literze

Update ktoś poroponuje A-Za-zÀ-ÿ https://stackoverflow.com/questions/30798522/regular-expression-not-working-for-at-least-one-european-character

5
MrocznyRycerz napisał(a):

Cześć!

Tworzę w JS skrypt do walidacji danych wprowadzanych przez użytkownika. O ile walidacja pól formularza typu telefon jest oczywista, to zastanawiam się nad walidacją pól tekstowych na nazwisko czy nazwę ulicy.

A masz potrzebę w ogóle to sprawdzać? Ja bym na Twoim miejscu sprawdził tylko czy to co user wprowadził to białe znaki i litery, czyli w regexpie to by było \s oraz \p{L}, i tyle - tylko po to żeby sprawdzić czy ktoś nie podał np cyfry albo znaków !@#$%.

Takimi rzeczami jak XSS i SQlInjection nie zajmuje się na etapie wprowadzania danych przez usera!! Przed XSS bronisz się budując odpowiednio widok, a przed SQL budująć odpowiednie query.

0

Czyli mam pozwolić na to, by user wprowadził do formularza (pole text) co tylko zechce?
Jak to ma się to pola z telefonem, gdzie chcę wymusić format 123-456-789? Albo kod pocztowy.

1
MrocznyRycerz napisał(a):

Czyli mam pozwolić na to, by user wprowadził do formularza (pole text) co tylko zechce?

No, w sumie tak.

Jedyne, czym się powinieneś kierować w takim polu z imieniem, to tym jakie dane chcesz mieć w aplikacji.

  • Czy chcesz żeby user mógł podać litery polskie: ą, ę, ś, ć
    • litery niemieckie
    • litery z innych języków?
  • Cyfry?
  • białe znaki
  • apostrofy?
  • cudzysłowy,

etc. To są dobre powody żeby dodać taką walidację. Ja Ci napisałem wyżej, ja dopuściłbym \s oraz \p{L}, czyli białe znaki i litery z dowolnego języka.

Ale Ty zacząłeś temat, pytając czy powinieneś je walidować po to żeby zabezpieczyć się przed SQL Injection - i na to pytanie, odpowiedź kategorycznie brzmi nie. Walidacja formularza to nie jest dobre miejsce na to.

Jak to ma się to pola z telefonem, gdzie chcę wymusić format 123-456-789? Albo kod pocztowy.

A musi się jakoś mieć?

3
MrocznyRycerz napisał(a):

Czyli mam pozwolić na to, by user wprowadził do formularza (pole text) co tylko zechce?
Jak to ma się to pola z telefonem, gdzie chcę wymusić format 123-456-789? Albo kod pocztowy.

To jest racjonalne.

Ale chodzi o sposób stawiania sobie zagadnienia: to nie ma nic do injection

(na marginesie: ostrożnie, coraz więcej ludzi się pod wzgledemm "narodowościowym" przemieszcza, sa obywatele polscy o nazwiskach rozmaitych, są przybysze), przy czym akurat naswiska ukrańskie transliterowane tak jak zdecydowali po angielsku nie są problemem: holenderskie, norweskie, szwedzkie, niemieckie)

0

No to co jeżeli w takie "bezbronne" pole tekstowe użytkownik wprowadzi jakiś złośliwy kod? Przecież jak ktoś ma bloga, to raczej nie pozwoli, by w polu komentarz ktoś wpisał dowolny tekst? Jeżeli dobrze rozumiem, to jest to właśnie XSS.

Przy okazji coś się nauczyłem. Aby wykryć znak minus, należ tak go wprowadzić:

\-
1
MrocznyRycerz napisał(a):

Przecież jak ktoś ma bloga, to raczej nie pozwoli, by w polu komentarz ktoś wpisał dowolny tekst? Jeżeli dobrze rozumiem, to jest to właśnie XSS.

Ależ oczywiście że czesto można wprowadzić dowolny tekst. Tak jak np tu. Tylko że trzeba go eskejpować.Eskejpować raz przy wprowadzaniu do bazy, ci zwyle robia frameworki bazodanowe, lub jest nawet w sam język wbudowane. Np w javie są od tego PreparedStatement. Po drugie eskejpować przy wyświetlaniu. Bo możemy komuś pozwolić napisać <b> i potem to zostanie wyświetlone jako <b>. Czy nawet:

<script type="text/javascript">
//<![CDATA[
Very danger code
//]]>
</script>
3
MrocznyRycerz napisał(a):

No to co jeżeli w takie "bezbronne" pole tekstowe użytkownik wprowadzi jakiś złośliwy kod? Przecież jak ktoś ma bloga, to raczej nie pozwoli, by w polu komentarz ktoś wpisał dowolny tekst?

Jeśli aplikacja jest napisana poprawnie, to nie ma czegoś takiego jak "złośliwy kod". Nawet jak wpiszesz najbardziej "złośliwe znaki" jakie się tylko da, do pola w komentarzu, to one powinny być poprawnie dodane do bazy oraz do widoku.

Weź na przykład edytor na 4programmers. Możemy tu wpisywać dowolne SQL'e i XSS jakie się nam tylko nie śniły, ale nie zobaczysz nigdy komunikatu "Nie możesz dodać znaku & w poście".

MrocznyRycerz napisał(a):

Jeżeli dobrze rozumiem, to jest to właśnie XSS.

Nie, to nie jest po to.

Sporo ludzi Ci tutaj opowiada o "escape'owaniu" złośliwych znaków - to jest z pewnością to jak praktycznie to należałoby to zrobić.

Ale ostatecznie, całość sprowadza się do bardzo prostego rozrachunku. Zadaj sobie pytanie - czy jest jakiś ciąg znaków/bajtów, które nie da się dodać do bazy? (np takiego z apostrofami, --, ==, etc.). Jeśli tak, to faktycznie musiałbyś odrzucić te dane w interfejsie użytkownika. Ale we wszystkich bazach jakie znam, dowolny ciąg znaków zawsze można do niego dodać - więc i każdy input usera można dodać do takiej bazy, nie ma więc powodu czemu również tych znaków które określiłbyś "złośliwymi" miałoby się nie dać dodać. To o czym Ty mówisz, podatność na SQL Injection, to jest właściwie tylko i wyłącznie to błąd programisty, który niepoprawnie połączył plain text (np treść komentarza) z językiem SQL, przez co jego query wymieszało się z potencjalnym query w komentarzu. To jest przyczyna tego błędu - niepoprawne łączenie tych dwóch formatów, nie "znaki" same w sobie.

Odpowiadająć na Twoje pytanie No to co jeżeli w takie "bezbronne" pole tekstowe użytkownik wprowadzi jakiś złośliwy kod? - jeśli użyjesz odpowiedniego budowania query i odpowiedniego budowania widoku - nic się nie stanie.

0

Co to znaczy "odpowiednia budowa widoku"?

2
MrocznyRycerz napisał(a):

Co to znaczy "odpowiednia budowa widoku"?

Chodzi o to, że jeśli user wpisze powiedzmy w pole w komentarzu "2+2 > 1+1", to nie możesz po prostu wziąć tego stringa "jak jest" i dokleić do HTML'a. Znak ">" w plain texcie (np w komentarzu) to po prostu znak większości. Ale w HTML'u znak > to już specjalny znak HTML zamykający tag. Nie możesz więc go tak po prostu wziąć i przekleić. Żeby poprawnie pokazać znak większości w HTML'u, musisz wpisać &gt;.

Czyli string plain text string "2+2 > 1+1" to jest w HTML'u 2+2 &gt; 1+1. To trochę jak tłumaczenie stringów z różnych języków. step po angielsku to coś innego niż step po polsku, i mimo że oba słowa brzmią i literują się tak samo, to nie są swoimi odpowiednikami w dwóch językach, podobnie jak < w plain text to nie jest odpowiednik < w HTML'u. Należy je odpowiednio przetłumaczyć, np właśnie > na &gt;.

Co ma oczywiście taką konsekwencję, że jesli ktoś nie przetłumaczy odpowiednio plaintext na HTML, to może się tak zdarzyć, że ktoś w komentarzu wpisze akurat taki tekst, który zinterpretowany jako dosłowny HTML' może nam zaszkodzić. Ale ponownie, to nie jest wina znaków samych w sobie, tylko nie poprawne zmapowania ich z jednego formatu na drugi. XSS i SQLInjection to jest tak na prawdę to samo, tylko że w różnych technologiach.

Przykład niepoprawnego i poprawnego tłumaczenia:

input output value dosłowne tłumaczenie poprawne tłumaczenie
angielski polski tea curve oh Ty ku*** herbata zakręt oho
plain text html > zamykający tag &gt;
plain text sql -- komentarz znaki "--"

Jak widzisz, często pomiędzy różnymi formatami występują konstrukcje które wyglądają tak samo, ale znaczą coś innego, i żeby zachować poprawność i ciągłość, należy je poprawnie zmapować.

0

Czyli ktoś wpisze jakieś SQL injection:

" or ""="

to z jednej strony nic się nie stanie stosując prepared statements, które to "wykastrują" przed wrzuceniem do bazy danych.

A z drugiej strony coś co widoczne będzie jako:

" or ""="

będzie tak naprawdę:

&quot; or &quot; &quot; &#61; &quot;
0
MrocznyRycerz napisał(a):

Czyli ktoś wpisze jakieś SQL injection:

" or ""="

to z jednej strony nic się nie stanie stosując prepared statements, które to "wykastrują" przed wrzuceniem do bazy danych.

A z drugiej strony coś co widoczne będzie jako:

" or ""="

będzie tak naprawdę:

&quot; or &quot; &quot; &#61; &quot;

W skrócie tak.

Przy czym nie wiem czy dobrze jest myśleć o tym w kontekście "wykastrują". Bo nie chodzi Ci o usuwanie informacji, albo usuwanie danych, albo o usuwanie czego kolwiek. Budując query, chcesz po prostu umieścić dane z jednego formatu (plain tekst, w którym każdy znak jest dosłowny), na inny format (SQL, gdzie część znaków jest dosłowna, a część jest znakami specjalnymi). I takie "umieszczenie" jest po prostu bardziej skomplikowane niż zwykła konkatenacja.

Wyobraź sobie dzieci w trzeciej klasie podstawówki które krzyczą cały czas "tea curve". Czy to znaczy że słowa "tea" oraz "curve" są w jakiś sposób "niebezpieczne" i trzeba je usunąć? Czy może chodzi o to że tymi konkretnymi słowami należy się posługiwać w odpowiednim kontekście.

0

Wykastrować, czyli do bazy danych zamiast:

"

trafi:

&quot;
0
MrocznyRycerz napisał(a):

Wykastrować, czyli do bazy danych zamiast:

"

trafi:

&quot;

No nie, nie do końca.

Jeśli masz string

"

to do bazy również powinien trafić znak

"

Ale to że do bazy ma trafić znak ", nie znaczy że w SQL query ma się pojawić znak ". W query powinien pojawić się wyescape'pwany, czyli \", i ponieważ w query będzie wyescape'owany, to do bazy trafi po prostu " tak jak powinien.

0

Dzięki, zaczynam już to rozumieć. Muszę przemyśleć w takim razie co będzie walidowane na moim formularzu.

3
MrocznyRycerz napisał(a):

Czyli ktoś wpisze jakieś SQL injection:

" or ""="

to z jednej strony nic się nie stanie stosując prepared statements, które to "wykastrują" przed wrzuceniem do bazy danych.

Nie wykasują tylko wyeskejpują (nie wiem jak to nazwać poprawnie po polsku). Chcesz wpisac do bazy stringa Ala ma kota ' piesa, ale nie możesz bo ' to znak początka/końca stringu w SQLu. No to jak zrobisz prepare statemant w rodzaju:

val statement = myCon.prepareStatement("INSERT INTO my_table VALUE (?)")
statement.setString("Ala ma kota ' piesa")

I sama Java (czy inny język co akurat używasz) zajmie się podmienianiem znaków na poprawne. Pewnie będzie gdzieś to równoważne kodowi:

val statement = myCon.statement("INSERT INTO my_table VALUE " + "'Ala ma kota \\' piesa'" + "" )

Ale gwarancji nie daję bo nie robiłem takich złych rzeczy od dawna :P

0
KamilAdam napisał(a):

Nie wykasują tylko wyeskejpują (nie wiem jak to nazwać poprawnie po polsku).

Zgadzam się w zupełności.

Chcesz wpisac do bazy stringa Ala ma kota ' piesa, ale nie możesz bo ' to znak początka/końca stringu w SQLu.

No, dokładniej mówiąc to możesz. Chcesz dodać do bazy string Ala ma kota ' piesa, to znaczy że wynikowo w bazie ma się pojawić Ala ma kota ' piesa. I żeby dodać taką wartość, to stworzone query musi wyglądać tak:

INSERT INTO my_table VALUE('Ala ma kota \' piesa')
0

A jak potraktować pola tylu numer telefonu albo numer NIP?

Bezwzględnie dopuszczać tylko cyfry? Bo zastanawiam się nad obróbką tego po stronie backendu. Czyli jak nie pozwolić, by do bazy trafił number telefonu 123dupa.

1
MrocznyRycerz napisał(a):

A jak potraktować pola tylu numer telefonu albo numer NIP?

Bezwzględnie dopuszczać tylko cyfry? Bo zastanawiam się nad obróbką tego po stronie backendu. Czyli jak nie pozwolić, by do bazy trafił number telefonu 123dupa.

Możesz pozwolić na dodanie takiego numeru, wtedy będziesz widział dokładnie co ktoś wpisał, i ewentualnie później zdecydować co zrobić z takim numerem. Albo możesz też nie dopuścić do dodania go. Z technicznego punktu widzenia nie ma różnicy pomiędzy tymi podejściami, wybierz to które Ci bardziej pasuje.

Tak na prawdę to się sprowadza do tego, że to Ty musisz zdecydować jak taka aplikacja ma działać.

0

Ja bym chciał, by user wprowadzał dane dokładnie tak, jak chcę. Czyli kod pocztowy jako 12-456, telefon jako 123456789, NIP jako 1234567890. A nad polami tekstowymi jeszcze pomyślę.

Mogę na frontend zablokować wprowadzanie numeru 123dupa, ale to można obejść. Pozostaje wtedy backend.

0
MrocznyRycerz napisał(a):

Ja bym chciał, by user wprowadzał dane dokładnie tak, jak chcę. Czyli kod pocztowy jako 12-456, telefon jako 123456789, NIP jako 1234567890. A nad polami tekstowymi jeszcze pomyślę.

No to zrób tak.

Tylko pamiętaj, że to nie ma żadnego związku z SQLinjection i XSS. To się ogarnia w innych miejscach.

MrocznyRycerz napisał(a):

Mogę na frontend zablokować wprowadzanie numeru 123dupa, ale to można obejść. Pozostaje wtedy backend.

Od backendu powinieneś zacząć, żeby backend nie wpuścił żadnych danych niepoprawnych.

Potem dodaj sprawdzajke na froncie, jako dobry UX, bo "zabezpieczenia" na froncie raczej nie istnieją.

1

Niby trywialny projekt, a ile można się nauczyć i na ile rzeczy trzeba zwracać uwagę. Fajnie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1