Zend Form security (basics)

Ook bij een “gesloten” applicatie kun je nooit teveel doen aan de beveiliging van je formulieren. Voor een “standaard” omgeving wil je in iedere geval basisbescherming opzetten tegen;

  • Formulier spam
  • Fake/overmatige form posts
  • Ongewenste gegevens

Met Zend Framework heb je op zich al best wat leuke mogelijkheden tot je beschikking voor het valideren en filteren van inputvelden en een stukje bescherming tegen CSRF.

Formulier spam

Voor een eenvoudige site zal een spammer niet veel moeite doen. Enige wat je wilt is een drempel die het voor “standaardscripts” onmogelijk maakt je systeem te vervuilen en tegelijkertijd niet teveel werk is om te implementeren. Een mogelijkheid is het toevoegen van een veld wat je met CSS (of JavaScript) verbergt voor normale gebruikers en wat “false” is als deze een waarde bevat. Een normale gebruiker die geen CSS en JavaScript heeft aan staan is zeldzaam maar mocht die toch voorkomen dan kun je die eventueel met een label nog informeren over het feit dat dit een veld is speciaal om spambots uit te sluiten.

Fake/overmatige form posts

Zend_Form_Element_Hash biedt hiervoor op zich in basis een goede bescherming tegen. Bij het aanmaken van je form neem je een veld op met het type “hash”. Dit veld kun je van parameters voorzien zoals een timeout etc. Bij het aanmaken van het form maakt Zend een session aan met deze hash erin. Bij de post van het form wordt deze gevalideerd tegen de hash. Als hij verlopen is geeft de form isValid false terug. Hier zit wel gelijk een “let op!” momentje in; als je in je structuur ergens de ongelukkige setup hebt waarbij het form meerdere keren gevalideerd wordt zal deze bij de 2e ronde false geven op deze hash.

Hieronder een simpele setup voor dit element in je form:

$this->addElement('hash', 'csrf_hash', array(
    'salt' => 'justSomeRandomSalt',
    'timeout' => 600,
));

ps. de documentatie op de Zend Framework website is niet erg diepgaand op dit vlak. Als je in de broncode van de Form/Element/Hash.php kijkt zie je dat er meer parameters zijn die je mee kunt geven.

  • setSalt($salt)
    String met salt. Geef je niets mee dan gebruikt hij standaard de string “salt”
  • setSession($session)
    Zend_Session_Namespace $session als je zelf een session wilt meegeven.
  • setTimeout($ttl)
    Int met timeout welke standaard op 300 staat.

Ongewenste gegevens

Hoe ver je hiermee gaat hangt een beetje van de aard van de data af, de plek waar het form zit (publiek of besloten) en of de data bijvoorbeeld naar een database gaat of alleen gemaild wordt naar een persoon. Tevens laat ik hierin de beveiliging van de opslag, verzending of wat dan ook van de data buiten wegen. Het gaat me nu even puur om de formulier-afhandeling.

Met Zend_Filter en Zend_Validator kun je krachtige combinaties maken welke de data strippen op alleen het nodige na en het resultaat hiervan valideren. Stel je hebt een select veld:


$this->addElement('select', 'is_lovingchocolate', array(
    'label' => 'Do you love chocolate?',
    'multiOptions' => array(
        1 => 'Yes',
        0 => 'No',
    ),
    'filters' => array('int'),
));

Wat je hiermee doet is in iedere geval gelijk de formulierwaarde die terugkomt met de POST typecasten naar INT.  Met de verschillende Zend_Filter classes kun je op die manier al heel veel ellende tegenhouden. Als je ingewikkeldere data-patronen hebt kun je ervoor kiezen met eenvoudige Zend_Filters alle ongewenste data eruit te halen om daarna met Zend_Validate_Regex de data tegen een hele strict patroon te matchen.

Een voorbeeld hiervan:


$this->addElement('text', 'zipcode', array(
'label' => 'Zipcode (Dutch notation)',
'required' => true,
'maxlength' => 7,
'validators' => array(
    array('NotEmpty', true),
    array(
        'regex', false, array('/^[0-9]{4} [A-Z]{2}$/',
        'messages' => array('regexNotMatch' => 'Incorrect zipcode notation. Should look like 2222 AA.'))
    ),
),
'filters' => array('StripTags', 'stringToUpper'),
));

Wat we doen met de filters is alles eruit halen wat we nu even niet willen en gelijk de letter naar hoofdletters converteren voor een uniforme dataopslag later. Na deze stap valideren we het resultaat met een reguliere expressie voor de postcode. Even los van het feit of deze expressie aansluit bij jouw idee van een goede postcode maar denk dat het idee wel helder is zo.

Geef een reactie

Jouw e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd met *