gebruik SANITIZE FLAGS met UTF-8 characterset
Mijn specifieke wensen mbt validate worden netjes uitgevoerd.
Maar ik mis wat specifieke zaken bij de $_POST en $_GET.
Ik gebruik UTF-8 characterset.
Daar heeft de IPTC geen problemen mee.
De SANITIZE gaat standaard toch uit van andere characterset toch?
Ook dat geeft nog geen problemen.
Maar ik kan nauwelijks enige verfijning met FLAGS aanbrengen.
Ook het invoeren van specifiek verboden characters lukt niet.
Zo zijn latlon coordinaten. Met punten, en gescheiden door een komma.
Daarnaast gebruik ik op de meeste pagina's waarbij men ingelogd moet zijn:
action=""
in verleden zette je daar dan voor:
action=""
Is dat nog veranderd?
Ik heb ook nog bij wachtwoord vergeten staan:
value=""
Moet dat nog beveiligd worden?
Lees op forums daar verschillende meningen over.
Wanneer ik toch gedeeltes in database onderbreng,
geeft dit dan nog problemen met de characterset?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function Register($post, $process) {
$wijzig = '0';
if(isset($process)) {
$pass = filter_var($_POST['pass1'], FILTER_SANITIZE_STRING);
$pass2 = filter_var($_POST['pass2'], FILTER_SANITIZE_STRING);
$user_name = filter_var($_POST['username'], FILTER_SANITIZE_STRING);
$email = filter_var($_POST['email_address'], FILTER_SANITIZE_EMAIL);
$birth = filter_var($_POST['birth'], FILTER_SANITIZE_NUMBER_INT);
$name = filter_var($_POST['first_name'], FILTER_SANITIZE_STRING);
$website = filter_var($_POST['website'], FILTER_SANITIZE_URL); // optie
$facebook = filter_var($_POST['facebook'], FILTER_SANITIZE_URL); // optie
$youtube = filter_var($_POST['youtube'], FILTER_SANITIZE_URL); // optie
$address = filter_var($_POST['zip_postal'], FILTER_SANITIZE_STRING); // optie adres
$latlon = filter_var($_POST['latlon'], FILTER_SANITIZE_STRING); // optie coordinaten
$country_code = filter_var($_POST['country'], FILTER_SANITIZE_STRING); // optie landcode
$post_all = filter_var($_POST['postall'], FILTER_SANITIZE_STRING); // optie postcode
$wijzig = filter_var ($_POST['wijzig'], FILTER_SANITIZE_NUMBER_INT); // kan alleen 1 zijn
}
}
$wijzig = '0';
if(isset($process)) {
$pass = filter_var($_POST['pass1'], FILTER_SANITIZE_STRING);
$pass2 = filter_var($_POST['pass2'], FILTER_SANITIZE_STRING);
$user_name = filter_var($_POST['username'], FILTER_SANITIZE_STRING);
$email = filter_var($_POST['email_address'], FILTER_SANITIZE_EMAIL);
$birth = filter_var($_POST['birth'], FILTER_SANITIZE_NUMBER_INT);
$name = filter_var($_POST['first_name'], FILTER_SANITIZE_STRING);
$website = filter_var($_POST['website'], FILTER_SANITIZE_URL); // optie
$facebook = filter_var($_POST['facebook'], FILTER_SANITIZE_URL); // optie
$youtube = filter_var($_POST['youtube'], FILTER_SANITIZE_URL); // optie
$address = filter_var($_POST['zip_postal'], FILTER_SANITIZE_STRING); // optie adres
$latlon = filter_var($_POST['latlon'], FILTER_SANITIZE_STRING); // optie coordinaten
$country_code = filter_var($_POST['country'], FILTER_SANITIZE_STRING); // optie landcode
$post_all = filter_var($_POST['postall'], FILTER_SANITIZE_STRING); // optie postcode
$wijzig = filter_var ($_POST['wijzig'], FILTER_SANITIZE_NUMBER_INT); // kan alleen 1 zijn
}
}
Verder is het zinvol om htmlentities() te gebruiken bij je $_GET-waarde, want als iemand HTML kan uitvoeren is er XXS mogelijk.
En verder moet je juist niet je data die je in de database gaat zitten vooraf sanitizen. Dat doe je uitsluitend bij het uitlezen.
Als je pas bij uitlezen gaat sanitizen, haal je dan niet veel rotzooi in je database?
Of ondervang je dat bij de validatie?
Voordat je een e-mailadres of URL in je database opslaat, wil je natuurlijk wel weten of het inderdaad een e-mailadres of URL is. Niet sanitizen misschien, maar wel valideren.
Hans De Ridder op 29/11/2017 17:43:32:
Bedankt voor je snelle reactie Arien.
Als je pas bij uitlezen gaat sanitizen, haal je dan niet veel rotzooi in je database?
Of ondervang je dat bij de validatie?
Als je pas bij uitlezen gaat sanitizen, haal je dan niet veel rotzooi in je database?
Of ondervang je dat bij de validatie?
Wat noem jij rotzooi? Wat Ward zegt, je moet wel de input valideren om te voorkomen dat er misvormde data in de database staat.
Maar als je bijvoorbeeld een lap tekst in de database op wilt slaan, dan gebruik je GEEN htmlentities of htmlspecialchars om de boel onschadelijk te maken bij de invoer. Enkel bij de uitvoer. Je wilt je data niet verminken namelijk.
Behalve dat een mailadres geldig moet zijn (dus een apenstaart en een punt ergens) mag je jezelf ook vragen of een mailadres verplicht ingegeven moet worden ja of nee. Indien verplicht dan keur je een lege string $email dus ook af.
Tijdens de validatie verander je data zelf niet. Dat doe je waar nodig daarna wanneer de validatie geslaagd is.
(Met javascript doe je soms wel veranderingen voor de validatie maar ik heb het hier over server-side).
Toevoeging op 29/11/2017 21:34:34:
Email valideren doe je bij voorkeur met de functie filter_var.
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
$email = "[email protected]";
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo("$email is a valid email address");
} else {
echo("$email is not a valid email address");
}
?>
$email = "[email protected]";
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo("$email is a valid email address");
} else {
echo("$email is not a valid email address");
}
?>
Gewijzigd op 29/11/2017 21:15:32 door Frank Nietbelangrijk
Valideren heb ik wel voor elkaar bij de inputs.
Moest ook valideren omdat er specifiek velden zijn voor facebook, website, of youtube input .
Maar dat is ook allemaal goed verlopen.
Had daar allen ook sanitize bij gedacht.
Maar dat kan ik beter doen bij het uitlezen blijkbaar.
Dus dat moet ik nog aanpassen.
Is het trouwens nodig bij het ophalen/gebruiken van wachtwoord en gebruikersnaam ook nog te sanitizen?
Filteren kijkt of invoer voldoet aan patronen.
Sanitizen past mogelijk invoer aan zodat het daarna voldoet aan een patroon.
Als je een wachtwoord sanitized, verander je mogelijk de oorspronkelijke invoer.
Dat lijkt mij nooit de bedoeling.
In zijn algemeenheid: het is onwenselijk om de oorspronkelijke invoer aan te passen. Stel dat jij ergens A invult in een formulier, dan snijdt het toch geen hout dat je deze zelfde informatie later terugleest als B? Dat is simpelweg niet wat jij hebt ingevuld. Plus hier zit een interpretatiestap bij, waarbij het systeem vindt dat A equivalent is aan B, of B wellicht beter is, terwijl jij toch echt A bedoelt en B mogelijk fout is.
Wel is het zaak dat je op de juiste manier omgaat met user input. Dit doe je door van tevoren te controleren of het (in zijn ONGEWIJZIGDE VORM) voldoet aan mogelijke regels (filter input), en dat je er vervolgens voor zorgt dat wanneer je deze data gaat gebruiken in een bepaalde context (HTML, SQL) dat deze data van enige speciale betekenis binnen die context ontdaan wordt (escape output) tenzij dat expliciet niet de bedoeling is. Merk hierbij op dat in géén van deze situaties de oorspronkelijke invoer wordt gewijzigd.
Bij mij is 'set' het opslaan.
en 'get' het ophalen.
Die 'get' waarde gebruik ik om te laten zien (bijv. tekst).
Maar kunnen ook dienen om een resultaat te berekenen bij vergelijkingen.
Begrijp ik het dan goed, dat ik bij het 'setten' het bedoelde patroon opsla (valideren);
Geldt dat dan ook voor het resultaat dat je zelf berekent (denk bijv. bij input adres opgeven en de de coordinaten berekenen voor googlemaps)
En dan bij de 'get' een sanitize doen.
Dat moet dan bij elke 'get' neem ik aan?
De validatie gebeurt ook echt voor het opslaan lijkt mij. Toegepast op het bovengenoemde voorbeeld: het sanitizen heeft dan mogelijk wel het effect dat de invoer syntactisch correct is, maar dit kan nog steeds resulteren in een onzinnige query. Dat is dan toch een beetje verspilde moeite dat je een query gaat uitvoeren terwijl je al weet dat de informatie niet klopt toch?
Anyhow, onthoud gewoon het adagium "filter input, escape output". Vervolgens is het zaak dat je begrijpt wat INPUT is en wat OUTPUT, zodat je weet wat er moet gebeuren.
Stel dat je een zoekfunctie hebt op een of andere pagina blaat.php, bijvoorbeeld als volgt:
blaat.php?q=henk
Wanneer blaat.php wordt uitgevoerd moet de pagina weten of er een zoekopdracht is ingegeven om vervolgens informatie te gaan zoeken. In dit geval kunnen we niet echt filteren omdat we simpelweg niet weten welke regels we aan de zoekregel zouden kunnen opleggen (vorm staat op voorhand niet vast / is niet echt klassificeerbaar / te vangen in regels). Dit wordt anders wanneer je in een zekere categorie wilt zoeken:
blaat.php?q=henk&cat=2
Identificatie van een categorie geschiedt via het id en je zou nog verder kunnen gaan door bij te houden welke categorieën bestaan en/of toegankelijk zijn voor deze gebruiker. In dat geval zou je dus het id kunnen filteren: is deze numeriek en betreft het een geldige/zinnige opgegeven categorie. Vervolgens zou je kunnen besluiten om of de hele zoekopdracht af te blazen of de categorie simpelweg te negeren wanneer die -om wat voor reden dan ook- ongeldig was.
Vervolgens stop je deze informatie in een query en ga je deze dus gebruiken in een context. De INPUT is dus nu tevens OUTPUT geworden. Dan is het dus zaak om je zoekopdracht zo te formatteren zodat deze geen speciale betekenis heeft binnen je query omdat dan mogelijk de
In principe sla je dus alle informatie "rauw" op. Dat lijkt mij ook het makkelijkste, want op die manier kun je filter-input-escape-output altijd consequent toepassen, ook op informatie in de database die mogelijk weer als invoer van queries wordt gebruikt. Een bijkomend voordeel daarvan is ook dat queries reproduceerbaar zijn zonder allerlei extra vertalingen heen en weer maar simpelweg de aanpak die je al volgde om een duidelijk scheiding tussen SQL en DATA in stand te houden in queries. Dit is dus ook simpel en vergroot het bewustzijn over wat INPUT (en OUTPUT) is, en hoe je hier mee om moet gaan.
Gewijzigd op 30/11/2017 20:48:22 door Thomas van den Heuvel
a)
Er is jouw applicatie die jij gemaakt hebt, waarvan je weet hoe deze werkt
EN
er is de grote boze buitenwereld waar je geen invloed op hebt en waar de gekste dingen gebeuren.
b)
Je wilt de data van je applicatie schoon en veilig houden
c) Hoe doe je dat?
1) Door beveiligers en detectiepoortjes te plaatsen op alle plaatsen waar data van de grote boze buitenwereld naar binnen komt in jouw applicatie.
2) Door de beveiligers opdracht te geven om alles wat verdacht is of niet aan de regels voldoet niet toe te laten.
Het heeft niet zo zeer met get of set te maken. Stel je hebt een class User en een class Message. Als je een nieuw bericht aanmaakt dan wil je waarschijnlijk in het bericht de username laten zien. je zou dan zo iets krijgen:
Dit is allemaal binnen je (o zo veilige) eigen applicatie. Er is geen reden om te valideren en al helemaal niet om te sanitizen.
ANDERSOM:
Nu komt de username echter uit een formulier, uit de grote boze buitenwereld dus.
Nu moet je dus direct na de submit van het formulier VALIDEREN. Je gaat de data bij voorkeur HELEMAAL NIET WIJZIGEN. Enkel data weigeren wanneer deze niet aan de spelregels voldoet.
Output escaping
Waar Thomas zegt filter input en escape output wil ik nog opmerken dat deze twee dingen totaal verschillend zijn en maar weinig met elkaar te maken hebben. Ik bedoel te zeggen dat je deze twee zaken uit elkaar moet trekken en één voor één zult moeten onderzoeken en gaan begrijpen.
Als je output bijvoorbeeld HTML is (dat is het meestal) dan kan de juistheid/geldigheid van je HTML gebroken worden.
Bijvoorbeeld:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
Daarnaast mag HTML ook JAVASCRIPT bevatten. Gewoon een script dus! Kan je bezoekers mooi naar malware toesturen ;-)
Escapen dus die variabelen:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$title = '</h1></body>';
?>
<body>
<h1><?php echo htmlspecialchars($title); ?></h1>
<p>Some content</p>
</body>
$title = '</h1></body>';
?>
<body>
<h1><?php echo htmlspecialchars($title); ?></h1>
<p>Some content</p>
</body>
Frank Nietbelangrijk op 30/11/2017 21:12:18:
Het heeft niet zo zeer met get of set te maken. Stel je hebt een class User en een class Message. Als je een nieuw bericht aanmaakt dan wil je waarschijnlijk in het bericht de username laten zien. je zou dan zo iets krijgen:
Dit is allemaal binnen je (o zo veilige) eigen applicatie. Er is geen reden om te valideren en al helemaal niet om te sanitizen.
Dit is allemaal binnen je (o zo veilige) eigen applicatie. Er is geen reden om te valideren en al helemaal niet om te sanitizen.
Dan heb je ook geen LogicException meer nodig, zoals in dit voorbeeld een InvalidArgumentException als $user geen geldige gebruiker is? ;-)
Ward, Natuurlijk is er meer tussen hemel en aarde. Exceptions gebruiken we wel degelijk maar dat is weer wat anders als validatie.
Gaat om checkboxen.
De eerste toont alles 'checked'.
De tweede toont alles 'unchecked'.
Probleem is opgelost door een !isset te doen.
Maar ben verrast dat de check van de checkbox ander wordt.
Code (php)
Gewijzigd op 01/12/2017 16:47:36 door Hans De Ridder
1. De variabele kopieren naar een andere variabele
2. htmlspecialchars() gebruiken.
Gebruik gewoon if (isset($_POST['WerkA'])), anders zijn de resultaten mogelijk niet wat je verwacht. Het verrassende is hier dat je nog steeds escaping toepast op input, iets dat al vaak genoeg gezegd is niet te doen.
Gewijzigd op 01/12/2017 16:52:05 door Ben van Velzen
Werd hiervoor door Frank als reactie geschreven:
Verkeerd begrepen ?
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$title = '</h1></body>';
?>
<body>
<h1><?php echo htmlspecialchars($title); ?></h1>
<p>Some content</p>
</body>
$title = '</h1></body>';
?>
<body>
<h1><?php echo htmlspecialchars($title); ?></h1>
<p>Some content</p>
</body>
In het eerste deel maak je een nieuwe variabele aan en kent er een waarde aan.
In het tweede deel test je of $field1 bestaat wat dus altijd het geval is.
Regel 2:
Hier doe je het goed. Jammer dat je geen HTML laat zien.
Dit is hoe het zit:
Een checkbox gebruik je met een boolean. Deze is true of false.
Code (php)
Toevoeging op 01/12/2017 17:09:41:
Hans De Ridder op 01/12/2017 17:01:47:
Bedank Ben...
Werd hiervoor door Frank als reactie geschreven:
Verkeerd begrepen ?
Werd hiervoor door Frank als reactie geschreven:
Verkeerd begrepen ?
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$title = '</h1></body>';
?>
<body>
<h1><?php echo htmlspecialchars($title); ?></h1>
<p>Some content</p>
</body>
$title = '</h1></body>';
?>
<body>
<h1><?php echo htmlspecialchars($title); ?></h1>
<p>Some content</p>
</body>
Dat gaat over OUTPUT escapen en niet over INPUT filteren. Dacht dat ik daar toch redelijk duidelijk over was...
Gotcha: isset() kijkt of een variabele bestaat en of de waarde verschilt van null.
Doe je dus het volgende:
Verdergaand op wat @Ben zei: escapen doe je doorgaans pas op het laatste moment, dus wanneer je het gaat gebruiken in HTML, SQL et cetera. Dit komt ook weer terug op de consequente werkhouding.
Stel dat we een veld $test uit jouw voorbeeld gaan gebruiken in HTML (checkbox is ff geen geslaagd voorbeeld dus een tekstveld):
Hoe kun je direct in dit voorbeeld zien of $test al ge-escaped is? Niet, je moet dan terug gaan zoeken in code. En als er geen escaping was, was dit dan bewust of per ongeluk vergeten? Als je afwijkt van de norm moet er altijd een annotatie gemaakt worden die je keuze onderbouwt en rechtvaardigt. Maar anders escape je op het laatste moment, zodat je direct kunt zien dat dit gebeurt:
Tevens: htmlspecialchars($_POST['WerkA') -met als doel dit weer terug te plakken in een formulier- is sowieso ongewenst! Dit betekent immers dat je in hetzelfde stuk code een formulier aan het weergeven EN aan het verwerken bent. Dit zou voor de goede orde gescheiden moeten worden in compleet van elkaar geisoleerde acties/routines...
Gewijzigd op 01/12/2017 17:13:39 door Thomas van den Heuvel