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="<?php echo $_SERVER['PHP_SELF']; ?>"

in verleden zette je daar dan voor:

action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>"

Is dat nog veranderd?

Ik heb ook nog bij wachtwoord vergeten staan:

value="<? 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?


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

}
}
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.
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?
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?


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.

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).

[size=xsmall]Toevoeging op 29/11/2017 21:34:34:[/size]

Email valideren doe je bij voorkeur met de functie filter_var.

<?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");
}
?>
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?
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.
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?


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


[hr]

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:

<?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.

[hr]

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:


<?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:


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

Reageren