Tutorials

Spam vrije contact formulieren

Uitleg over hoe spam scripts en kwaadwilligen misbruik kunnen maken van contact formulieren.

Pagina 1

Waarom deze tutorial?

Steeds meer spammers misbruiken formulieren op bestaande websites om hun spam te versturen.
Dit heeft 3 grote voordelen:
  • [item]1: De mensen achter de spamberichten zijn veel moeilijker te achterhalen.[/item][item]2: Spamfilters kunnen niet 'simpelweg' meer IP's blokkeren, omdat deze IP's immers slechts zeer tijdelijk gebruikt worden door de spammer.[/item][item]3: De 'mail-traffic' is op kosten van de eigenaar van de gehackte server. Het wordt dus 'nog goedkoper' voor de spammers om mails te verzenden.[/item]

Ik persoonlijk heb een hekel aan spam, en daarom wil ik de minder ervaren op dit gebied tips geven hun formulieren te beveiligen tegen spammers.
Pagina 2

Input controle (hoe moet het niet)

Zoals je misschien wel weet is JavaScript op de meeste browsers met 2 klikken uit te schakelen. Dus controle met alleen JavaScript is uit den boze. De controle MOET dan ook altijd plaats vinden binnen PHP.

Wat ook vaak gebeurt is dat er formulieren 'gekloond' worden. Men slaat dan het formulier op de pc op, en past het formulier zo aan dat het nogsteeds 'gePOST' wordt naar de oorspronkelijke locatie. Op deze manier kunnen formuliervelden verwijder/toegevoegd worden, en/of 'verborgen velden' worden aangepast. Gevolg: Deze velden zijn onbetrouwbaar.

Een oplossing voor dit probleem dacht ik te vinden via de $_SERVER["HTTP_REFERER"] variabele. Deze variabele toont aan waar je vandaan komt. Deze wilde ik vergelijken met de URL adres van het formulier, zodat het uit te sluiten is dat het formulier gekloond is. Ik kwam er echter al snel achter dat door een textfield op te nemen in het formulier met de naam 'HTTP_REFERER', je deze waarde volledig naar eigen inzicht manupuleren. Daarnast blijkt dat niet elke browser deze 'HTTP_REFERER' ondersteunt. Dit zou je website onnodig minder compatible maken voor verschillende browsers.
Pagina 3

Waar gaat het mis?

Bij het verzenden van een email kun je 'headers' opgeven voor het bericht. Binnen deze headers geef je o.a. de afzender op. Wat je hier echter ook kunt opgeven zijn de opties 'cc' en 'bcc'.

De standaard mail functie van php ziet er als volgt uit:

<?
mail(string $to, string $subject, $string message [, string $additional_headers [, string $additional_parameters]])
?>

Stel dat je de afzender wilt opnemen in de header, dan kun je de header hiervoor bijvoorbeeld als volgt instellen:

<?
$header = "From: \"" . $_POST["name"] . "\" <" . $_POST["email"] . ">";
?>

Dit resulteert bijvoorbeeld in:

<?
$header = "From: \"Mijn Naam\" <[email protected]>";
?>

Wat gebeurt er als de 'spammer' in plaats van netjes zijn naam, de volgende regel invult in het textfield 'name':
"Zijn Naam\" <[email protected]>[enter]Bcc: \"Haar Naam\" <[email protected]>, Mijn Naam"

Je raad het vast al; er worden extra headers toegevoegd. Het resulteert in:

<?
$header = "From: \"Zijn Naam\" <[email protected]>[enter]Bcc: \"Haar Naam\" <[email protected]>,\"Mijn Naam\" <[email protected]>";
?>

Gevolg is dat er in plaats van 1 email er nu 3 worden verzonden.. En het spammen is begonnen. Spammers doen het echter niet met 3, maar met honderden extra adressen tegelijk.
Pagina 4

Input controle (hoe moet het wel)

Gebruik bij het verwerken van het formulier binnen php de onderstaande functies voor ALLE velden die in de header worden opgenomen.

<?
$name = stripslashes($_POST["name"]);
$email = stripslashes($_POST["email"]);

if(isEmail($email)) // Merk op dat een 'goed' emailadres zowiezo nooit een [enter] of quote kan bevatten
{
$header = "From: \"" . protectMailHeaders($name) . "\" <" . $email . ">";
}
else // Fout afhandelen
{
exit("Ongeldig emailadres");
}

function protectMailHeaders($string)
{
$string = str_replace("\n", "", $string); // Verwijder \n
$string = str_replace("\r", "", $string); // Verwijder \r
$string = str_replace("\"", "\\\"", str_replace("\\", "\\\\", $string)); // Slashes van quotes

return $string;
}

function isEmail($string)
{
$result = false;

if($string != "")
{
$expr = "/^([a-zA-Z0-9]){1,}(([a-zA-Z0-9\-_])|(([\.]){1,1}
-opmaakbreak-
([a-zA-Z0-9]){1,})){0,}([@]){1,1}([a-zA-Z0-9]){1,}
-opmaakbreak-
(([a-zA-Z0-9\-_])|(([\.]){1,1}([a-zA-Z0-9]){1,})){0,}
-opmaakbreak-
([\.]){1,1}([a-zA-Z0-9]){2,4}$/";
if(preg_match($expr, $string)) // voldoet aan expressie
{
$result = true;
}
}

return $result;
}

?>

Merk op: Spammers proberen een formulier op tientalle manieren uit voor ze de strijd opgeven. Wat hier mooi zou zijn, is dat je eerst detecteert of een spammer probeert je formulier te hacken (door de waarden van velden te doorzoeken op headers als 'cc:' en 'bcc:'. Indien deze worden gevonden, zou je ze direct moeten attenderen dat jou formulier 'spamvrij' is (iets voor een keurmerk? :P), hierdoor geven ze eerder op, want uiteindelijk voor iedereen beter is. Ik kom hier nog op terug, want ik ben voor m'n werk al met iets dergelijks bezig (:

Iemand nog toevoegingen?
Pagina 5

Hoe kun je dit voorkomen?

Het antwoord is simpel. De input controleren en valideren!

Je hoeft 'alleen maar' de velden te controleren die in de HEADERS worden opgenomen. Op de achtergrond worden de variabelen '$to', en '$subject' echter ook in de header opgenomen! Dit betekend concreet dat je (m.b.t. dit probleem) alle velden op de variabele '$message' na moet controleren.

Waar moet je op controleren: Zorg dat er geen [enter] is de variabele staat (\r of \n). En zorg dat quotes voorafgaan met een slash. Bijvoorbeeld met de functie 'protectMailHeaders()' (is onderaan uitgewerkt).

Reacties

0
Nog geen reacties.