gebruik SANITIZE FLAGS met UTF-8 characterset

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Hans De Ridder

Hans De Ridder

29/11/2017 17:00:28
Quote Anchor link
Ik loop mijn beveiligingen na.
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="
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php echo $_SERVER['PHP_SELF']; ?>
"

in verleden zette je daar dan voor:

action="
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php echo htmlentities($_SERVER['PHP_SELF']); ?>
"

Is dat nog veranderd?

Ik heb ook nog bij wachtwoord vergeten staan:

value="
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<? echo $_GET['code']; ?>
"

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)
PHP script in nieuw venster Selecteer het PHP script
1
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

}
}
 
PHP hulp

PHP hulp

20/04/2024 06:14:54
 
- Ariën  -
Beheerder

- Ariën -

29/11/2017 17:14:16
Quote Anchor link
Die waarde van action kan je ook leeglaten, omdat je toch op dezelfde pagina zit waar je formulierafhandeling wordt uitgevoerd: action=""

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.
 
Hans De Ridder

Hans De Ridder

29/11/2017 17:43:32
Quote Anchor link
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?
 
Ward van der Put
Moderator

Ward van der Put

29/11/2017 17:47:26
Quote Anchor link
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.
 
- Ariën  -
Beheerder

- Ariën -

29/11/2017 18:32:49
Quote Anchor link
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?

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.
 
Frank Nietbelangrijk

Frank Nietbelangrijk

29/11/2017 21:10:13
Quote Anchor link
Valideren (denk aan de Engelse term Valid) betekent niets meer dan dat je data goedkeurt of afkeurt. Indien je de data afkeurt sla je deze HELEMAAL NIET OP. In plaats daarvan geef je een nette duidelijke foutmelding en geef je de gebruiker zo gebruiksvriendelijk mogelijk de kans om de gegevens aan te passen en opnieuw aan te leveren. Uiteraard hoort een hier een nette (fout)melding bij.

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)
PHP script in nieuw venster Selecteer het PHP script
1
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");
}

?>
Gewijzigd op 29/11/2017 21:15:32 door Frank Nietbelangrijk
 
Hans De Ridder

Hans De Ridder

29/11/2017 23:54:43
Quote Anchor link
Bedankt Frank voor je reactie.
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?
 
Thomas van den Heuvel

Thomas van den Heuvel

30/11/2017 19:52:12
Quote Anchor link
Filteren is niet hetzelfde als 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.
 
Hans De Ridder

Hans De Ridder

30/11/2017 20:08:41
Quote Anchor link
Bedankt voor de toelichting Thomas..

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?
 
Thomas van den Heuvel

Thomas van den Heuvel

30/11/2017 20:41:14
Quote Anchor link
Persoonlijk ben ik geen voorstander van sanitizen. Dit is in zekere zin recht proberen te maken wat eigenlijk al krom was. Als je ergens een getal verwacht dan is alleen een getal goed, maar als een sanitize-functie of typecast van "aap" toch het cijfer 0 maakt, is dat dan echt de bedoeling?

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 betekenis werking van je query veranderd kan worden (dit heet ook wel SQL-injectie). Hiertoe pas je dus escaping-regels toe (escape output), wat dus neer zou komen op een real_escape_sting() passage in combinatie met quotes (of je moet prepared statements gebruiken). Deze escaping zorgt enkel voor een juist gebruik in een bepaalde context en vertaalt specifieke controle-karakters zodat die niet als zodanig worden geïnterpreteerd binnen die context. In wezen is daarmee dus de invoer onveranderd.

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
 
Frank Nietbelangrijk

Frank Nietbelangrijk

30/11/2017 21:12:18
Quote Anchor link
hmm laten we er eens een ander lichtje op laten schijnen.

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:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
$message
->setUser($user);
?>


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)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$title
= '</h1></body>';
?>

<body>
    <h1><?php echo $title; ?></h1>
    <p>Some content</p>
</body>


Daarnaast mag HTML ook JAVASCRIPT bevatten. Gewoon een script dus! Kan je bezoekers mooi naar malware toesturen ;-)

Escapen dus die variabelen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$title
= '</h1></body>';
?>

<body>
    <h1><?php echo htmlspecialchars($title); ?></h1>
    <p>Some content</p>
</body>
 
Ward van der Put
Moderator

Ward van der Put

01/12/2017 13:33:48
Quote Anchor link
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:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
$message
->setUser($user);
?>


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? ;-)
 
Frank Nietbelangrijk

Frank Nietbelangrijk

01/12/2017 16:37:22
Quote Anchor link
Ward, Natuurlijk is er meer tussen hemel en aarde. Exceptions gebruiken we wel degelijk maar dat is weer wat anders als validatie.
 
Hans De Ridder

Hans De Ridder

01/12/2017 16:41:56
Quote Anchor link
Kan iemand me vertellen wat verschil is?
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)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php $field1 = htmlspecialchars($_POST['WerkA']); if (isset($field1)){ echo "checked='checked'";} ?>

<?php if (isset($_POST['WerkA'])){ echo "checked='checked'";} ?>
Gewijzigd op 01/12/2017 16:47:36 door Hans De Ridder
 
Ben van Velzen

Ben van Velzen

01/12/2017 16:51:10
Quote Anchor link
Voor dit soort gevallen ga je 2 dingen niet doen:
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
 
Hans De Ridder

Hans De Ridder

01/12/2017 17:01:47
Quote Anchor link
Bedank Ben...
Werd hiervoor door Frank als reactie geschreven:
Verkeerd begrepen ?
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$title
= '</h1></body>';
?>

<body>
    <h1><?php echo htmlspecialchars($title); ?></h1>
    <p>Some content</p>
</body>
 
Frank Nietbelangrijk

Frank Nietbelangrijk

01/12/2017 17:04:40
Quote Anchor link
Regel 1:

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)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$agree
= false;

if($_SERVER['REQUEST_METHOD'] == 'POST') {
    if(isset($_POST['agree'])) {
        $agree = true;
    }
}

?>

<form method="post">
    <label>
        <input type="checkbox" name="agree" <?php if($agree) echo ' checked="checked"'; ?>> Gaat u akkoord?
    </label>
</form>



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 ?
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$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...
 
Thomas van den Heuvel

Thomas van den Heuvel

01/12/2017 17:11:43
Quote Anchor link
Je creëert zelf een variabele, en kijkt dan of deze variabele bestaat. Laat dit even bezinken :).

Gotcha: isset() kijkt of een variabele bestaat en of de waarde verschilt van null.

Doe je dus het volgende:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$test
= null;
// isset($test) levert nu FALSE op
?>


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):
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<input type="text" name="test" value="<?php echo $test ?>">

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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<input type="text" name="test" value="<?php echo htmlspecialchars($test) ?>">


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
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.