Reputation: 908
I'd like to stop people spamming using special characters used for mail injection in php. For example \n
and \r
are used to concatenate several headers and so that also with %0A
and %0D
. So I wrote a regex to match them. But I suspect that my regex is not so efficient... something brings me to think that I'm writing something of unusable... Any help is appreciated, thanks.
Here is a basic example of that I'd like to do...
if (!preg_match('/^[^\s]./', $_POST['name']) || (preg_match('/(%0A|%0D|\\n+|\\r+|;|mime-version:|content-type:|content-transfer-encoding:|subject:|to:|cc:|bcc:)/i', $_POST['name'])) || !(strpos($_POST['name'],'\r') === false) || !(strpos($_POST['name'],'\n') === false)) {
exit("Warning: your Name contains illegal characters! This mail will not be sent!");
} elseif (!preg_match('/^[^\s]./', $_POST['subject']) || (preg_match('/(%0A|%0D|\\n+|\\r+|;|mime-version:|content-type:|content-transfer-encoding:|subject:|to:|cc:|bcc:)/i', $_POST['subject'])) || !(strpos($_POST['subject'],'\r') === false) || !(strpos($_POST['subject'],'\n') === false)) {
exit("Warning: your Subject contains illegal characters! This mail will not be sent!");
} elseif (!preg_match('/^[a-zA-Z0-9]+([_\\.-][a-zA-Z0-9]+)*'.'@([a-zA-Z0-9]+([\.-][a-zA-Z0-9]+))+$/', $_POST['mail'])) {
exit("Warning: your Mail contains no valid email address! This mail will not be sent!");
} elseif (!preg_match('/^[^\s]./', $_POST['message'])) {
exit("Warning: your Message connot be empty! This mail will not be sent!");
} else {
$name = $_POST['name'];
$mail = $_POST['mail'];
$subject = $_POST['subject'];
$message = $_POST['message'];
mail($to, $subject, $message, $headers, "-f$mail") {
exit("Your Mail is sent! Thanks!");
}
In order to match \n
, \r
, %0A
and %0D
how should I write my regex?
And
!(strpos($_POST['subject'],'\r') === false)
!(strpos($_POST['subject'],'\n') === false)
are quite good?
Thanks.
Upvotes: 2
Views: 470
Reputation: 908
I did a test. The test result is a success! I tested the regex trying directly in localhost
with different methods:
<?php
$test = "the dog \n was \r sleeping on the floor";
if (preg_match_all('/(%0A|%0D|\\n+|\\r+|;|mime-version:|content-type:|content-transfer-encoding:|subject:|to:|cc:|bcc:)/i', $test, $tmp)) {
echo "I found this character: '";
print_r($tmp[1]);
echo "'";
} else {
echo "I cannot find any string searched";
}
?>
Result:
I found this character: 'Array ( [0] => [1] => ) '
Looking at source I can see the \n and the \r
I found this character: 'Array
(
[0] =>
[1] =>
)
'
So I think that the regex is well build.
Also other test I did with strpos()
:
if !(strpos($_POST['subject'],'\n') === false)) {
fails with single quotes while finds the \n with double quotes...
if !(strpos($_POST['subject'],"\n") === false)) {
Conclusions: regex is well formed and strpos()
needs "" to match \n or \r.
Upvotes: 2
Reputation: 154
I am not very thorough with regex, but I can help u by giving an alternate trick solution to your problem.
You ca use following code to solve your purpose.
<?php
function sanitize_strings($raw_string) {
return preg_replace("/[^0-9a-zA-Z_\-\\\%]+/", "", $raw_string);
}
if( $raw_string == sanitize_strings($raw_string) )
{
echo "No illegal characters found.";
}
else
{
echo "Illegal characters found.";
}
?>
Hope this works for you. :)
Upvotes: 0