Hi guys,

Ik vraag me af... hoe ver voeren jullie veiligheid door?

Stel je hebt een formulier waar een bezoeker zich kan inschrijven op jouw website.

Zo'n formulier bestaat uit een aantal velden, maar laten we ons heel simpel even focussen op het veld "voornaam".

Een bezoeker vult zijn voornaam in, en het formulier wordt verstuurd. Wat controleren jullie vervolgens?

Volgens mij is het gebruikelijk om te controleren of de naam minimaal x en maximaal y tekens heeft, en of het allemaal letters zijn en eventueel aparte tekens (bijv. een liggend streepje).

Maar... controleren jullie bijv. ook nog of er html-tags in voorkomen? Dus stel iemand vult niet "Jan" in maar "<script>I am an evil script!</script>"? Controleren jullie ook op dit soort dingen? Ik heb z'n vermoeden dat dit in de meeste gevallen niet gebeurt, maar ik ben toch wel benieuwd eigenlijk. En als er mensen zijn die hier wel op controleren, wat doe je dan als je bemerkt dat iemand de boel probeert te "hacken"?
Ik controleer vrijwel alles wat via een formulier binnenkomt. In geval van een naam bv. is het zo gebeurt om bv op alleen letters en een enkel accent of streepje te controleren. En ik hoop dat het in de meeste gevallen WEL gebeurt. Bovendien stuur ik alles naar de database met mysqli_real_escape_string.
Om spam van robots tegen te gaan gebruik ik een inputveld type="text" dat ik de style hidden meegeef. Vervolgens check ik of dat veld wel echt leeg is. Het schijnt dat robots zo´n veld automatisch wel invullen, maar ik weet niet echt zeker hoe effectief dit is.
Ik waarschuw vaker voor die "minimale lengte" controle die je noemt:
Er is vaak zat een situatie te bedenken waarbij jouw lengte niet voldoet:

Een voornaam van minimaal 3 letters? (heb ik nog geluk, maar Jo heeft pech).
Een postcode van 6 tekens? Helaas in België maar 4 cijfers en Duitland 5.
En zoals ik gisteren tegenkwam op een puur NL site: Aruba heeft geen postcodes. (en ja, Arubaanse studenten zoeken ook kamers in de stad waar ik de site voor maakte).

Verder zitten er genoeg vreemde tekens in namen, om er altijd een paar te kunnen missen.
De ' heb je niet veel last van als je maar je escaping in de query goed doet.

De < en > kunnen vervelend zijn. In principe ook prima te voorkomen als overal consequent htmlspecialchars gebruikt bij het echo-en.
Maar je zou die tekens inderdaad kunnen filteren, voor wat extra zekerheid. (filter_input() )

Thanks.

Maar controleren jullie bijv. of er html-tags worden gebruikt in een naam?

Je zou bijv. met strip_tags een vergelijking kunnen doen tussen het origineel en de gestripte versie. Als die van elkaar verschillen, dan loopt er dus iemand te klooien. Mocht die persoon zich dan alsnog inschrijven, zou je bijvoorbeeld kunnen registreren dat ie "suspicious" gedrag heeft vertoond. Of kun je daar eigenlijk niks mee?
Tortuga web op 26/06/2014 09:22:16
Vervolgens check ik of dat veld wel echt leeg is. Het schijnt dat robots zo´n veld automatisch wel invullen, maar ik weet niet echt zeker hoe effectief dit is.


Checkboxjes toepassen doet ook wonderen in de meeste gevallen.

Ivo P op 26/06/2014 09:25:26

Ik waarschuw vaker voor die "minimale lengte" controle die je noemt:
Er is vaak zat een situatie te bedenken waarbij jouw lengte niet voldoet:


Meestal als ik een veld voornaam en achternaam zie, dan meld ik in voornaam meestal maar 1 teken.
Net zoals Ivo P ( 3 + 1 ).

Ozzie PHP op 26/06/2014 09:30:37

Maar controleren jullie bijv. of er html-tags worden gebruikt in een naam?


Zoals Ivo al aangaf, doormiddel van filter_input, kom je ook al een heel eind, zie
php.net
dit pas ik trouwens wel toe.

Wat wil je daarmee bereiken? De verdachte achterhalen?
Als je consequent blijft in je escaping en htmlspecialchars gebruik, dan kan er toch eigenlijk niets mis, of zit ik hier fout? En waarom zou je überhaupt < en > toe willen laten in een naam?
Ligt een beetje aan het soort site dat je maakt.

In mijn toepassingen zijn het hoofdzakelijk gebruikers die medewerker zijn. Daar is het anders dan een publiek toegankelijke omgeving.
Ik kies er dan vaker voor om de foute tekens gewoon te strippen.

Maar ik moet zeggen dat het me ook wel eens overkomen is dat een < uit heel andere bron een probleem veroorzaakte:
een automatisch aangeleverde productnaam (xml feed met orders) die een "<" bevatte (iets met schoonmaak middel met minder dan x% alkohol of zo).
Dat ging fout bij het aanmaken van een pdf. Die was wit vanaf het punt waar dat teken stond.

Ik heb dat aangepast door voor toekomstige producten die tekens te vervangen door een "-".

Maar je moet nog onderscheid maken tussen
* is het html
* is het een < die daar hoort en moet blijven
* is het een < die er minder toe doet (op een picklist staat de naam van het product er maar ter extra info bij. HEt gaat daarom het artikelnummer
In een productnaam kan ik me er iets bij voorstellen dat daar rare tekens in kunnen zitten. Maar bij een persoonsnaam weet je dat er dan iets niet klopt. Ik ben nog nooit iemand tegengekomen die Piet <alert>dikke lul!</alert> heet bijvoorbeeld :)

De vraag is dus of je moet controleren of iemand platgezegd de boel loopt te f#cken.

>> Wat wil je daarmee bereiken? De verdachte achterhalen?

Nee, dat niet zozeer. Maar je zou wel specifieke actie kunnen ondernemen. Stel iemand gaat html invullen, dan zou je bijv. z'n IP kunnen blocken. Of stel die persoon schrijft zich na zijn "hack"-pogingen alsnog in, dan zou je kunnen loggen dat deze persoon een "hack"-poging heeft gedaan, zodat je bijvoorbeeld extra alert kunt zijn als deze persoon een product bestelt via de website.

Dus daarom vroeg ik me af of jullie op dat soort dingen controleren... en of dat überhaupt gebruikelijk is.
Ozzie PHP op 26/06/2014 09:30:37

Thanks.

Maar controleren jullie bijv. of er html-tags worden gebruikt in een naam?

Je zou bijv. met strip_tags een vergelijking kunnen doen tussen het origineel en de gestripte versie. Als die van elkaar verschillen, dan loopt er dus iemand te klooien. Mocht die persoon zich dan alsnog inschrijven, zou je bijvoorbeeld kunnen registreren dat ie "suspicious" gedrag heeft vertoond. Of kun je daar eigenlijk niks mee?

Zodra je iets anders bouwt dan een HTML-editor, zou ik sowieso altijd strip_tags() gebruiken. Maar op basis van karakters kwaadaardige input signaleren, is lastig. Bijvoorbeeld < en > zitten op het toetsenbord boven de komma en de punt, dus een invoerfout is zó gemaakt.

Wat ik zelf specifiek bij namen doe, is karakters zoals ' en " door hun gekrulde tegenhangers vervangen. Verder komt invoer geheel in kleine letters of hoofdletters veel meer voor sinds de opkomst van tablets, en kun je ook die fatsoeneren.
Maar hou je dan geen rekening met "suspicious behaviour"?

Dus stel iemand voert bij het invoerveld "voornaam" bijvoorbeeld "<php>dsaflj@#$sdf@#$#48745!:TRRE$#</php>" in. Zeg jij dan alleen "voornaam niet correct!" en moet men de voornaam opnieuw invullen, of leg je als die persoon zich uiteindelijk toch succesvol inschrijft vast dat hij raar gedrag heeft vertoond?
Je houdt er in zoverre rekening mee dat je op voorhand alle malversaties uitsluit.

Maar dat betekent niet dat je op voorhand een complete firewall met intrusion detection bouwt. Aanvallen signaleer je meestal door iets merkwaardigs dat je vervolgens als "incident" analyseert aan de hand van de opeenvolgende requests in je serverlogs.

Wil je zo'n analyse automatiseren, dan moet je aan kansrekening doen. En dat vraagt om complexe modellen en big data. Bijvoorbeeld de kans dat je een potentiële wanbetaler aan de haak hebt is groter bij een anoniem Hotmail-adres, maar dat maakt niet elke Hotmail-gebruiker direct verdacht.

Reageren