如何使用php函数报告表单滥用

时间:2010-07-03 17:18:54

标签: php forms spam-prevention email-validation code-injection

我的网站上有一个联系表格,一切都像魅力一样。我正在使用反注入验证脚本,我怀疑应该在有人试图使用标头注入时发送通知。我已经测试了这个问题,并且无法确定为什么它不会在滥用事件时通知我。脚本如下。

<?php
/* Set e-mail recipient */
$myemail              = "email@gmail.com";

/* Check all form inputs using check_input function */
$subject              = check_input($_POST['subject'], "Please enter your name");
$email                = check_input($_POST['email'], "Please enter your email");
$form                 = check_input($_POST['form'], "Please write your message");
function logbad($value)
{

// Start of validation; this is where the problem is
$report_to = "email@gmail.com";
$name = "Matt";
$mail = "$email";

// replace this with your own get_ip function... 
$ip = (empty($_SERVER['REMOTE_ADDR'])) ? 'empty' 
: $_SERVER['REMOTE_ADDR']; 
$rf = (empty($_SERVER['HTTP_REFERER'])) ? 'empty' 
: $_SERVER['HTTP_REFERER']; 
$ua = (empty($_SERVER['HTTP_USER_AGENT'])) ? 'empty' 
: $_SERVER['HTTP_USER_AGENT']; 
$ru = (empty($_SERVER['REQUEST_URI'])) ? 'empty' 
: $_SERVER['REQUEST_URI']; 
$rm = (empty($_SERVER['REQUEST_METHOD'])) ? 'empty' 
: $_SERVER['REQUEST_METHOD']; 

$headers = "MIME-Version: 1.0\n"; 
$headers .= "Content-type: text/plain; charset=iso-8859-1\n"; 
$headers .= "X-Priority: 1\n"; 
$headers .= "X-MSMail-Priority: Normal\n"; 
$headers .= "X-Mailer: php\n"; 
$headers .= "From: \"".$nama."\" <".$mail.">\r\n\r\n";

@mail 
( 
$report_to 
,"[ABUSE] mailinjection @ " . 
$_SERVER['HTTP_HOST'] . " by " . $ip 
,"Stopped possible mail-injection @ " . 
$_SERVER['HTTP_HOST'] . " by " . $ip . 
" (" . date('d/m/Y H:i:s') . ")\r\n\r\n" . 
"*** IP/HOST\r\n" . $ip . "\r\n\r\n" . 
"*** USER AGENT\r\n" . $ua . "\r\n\r\n" . 
"*** REFERER\r\n" . $rf . "\r\n\r\n" . 
"*** REQUEST URI\r\n" . $ru . "\r\n\r\n" . 
"*** REQUEST METHOD\r\n" . $rm . "\r\n\r\n" . 
"*** SUSPECT\r\n--\r\n" . $value . "\r\n--"
,$headers
); 

}

// Check 1 
//First, make sure the form was posted from a browser. 
// For basic web-forms, we don't care about anything 
// other than requests from a browser: 
if(!isset($_SERVER['HTTP_USER_AGENT']))
{
die('Forbidden - You are not authorized to view this page (0)');
exit;
}

// Cek 2 

// Make sure the form was indeed POST'ed: 
// (requires your html form to use: action="post") 
if(!$_SERVER['REQUEST_METHOD'] == "POST") 
{
die('Forbidden - You are not authorized to view this page (1)'); 
exit; 
}

// Host names from where the form is authorized 
// to be posted from: 
$authHosts = array("cover.com");

// Where have we been posted from? 
$fromArray = parse_url(strtolower($_SERVER['HTTP_REFERER']));

// Test to see if the $fromArray used www to get here. 
$wwwUsed = strpos($fromArray['host'], "www.");

// Make sure the form was posted from an approved host name. 
if(!in_array(($wwwUsed === false ? $fromArray['host'] : substr(stristr($fromArray['host'], '.'), 1)), $authHosts)) 
{ 
logbad("Form was not posted from an approved host name"); 
die(' Forbidden - You are not authorized to view this page (2)'); 
exit; 
}

// Attempt to defend against header injections: 
$badStrings = array("content-type:",
"mime-version:",
"content-transfer-encoding:",
"multipart/mixed",
"charset=",
"bcc:",
"cc:");

// Loop through each POST'ed value and test if it contains 
// one of the $badStrings: 
foreach($_POST as $k => $v) 
{ 

foreach($badStrings as $v2)
{ 

if(strpos(strtolower($v), $v2) !== false)
{ 

logbad($v); 
die('<strong>Form processing cancelled:<br /></strong> string 
(`'.$v.'`)<strong> contains text portions that 
are potentially harmful to this server. <br />Your input 
has not been sent! <br />Please use your browser\'s 
`back`-button to return to the previous page and try 
rephrasing your input.</strong>'); 
exit; 
} 

} 

} 

// Made it past spammer test, free up some memory 
// and continuing the rest of script: 
unset($k, $v, $v2, $badStrings, $authHosts, $fromArray, $wwwUsed);

/* If e-mail is not valid show error message */
$addr_spec = '([^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c'.
            '\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+|\\x22([^\\x0d'.
            '\\x22\\x5c\\x80-\\xff]|\\x5c[\\x00-\\x7f])*\\x22)'.
            '(\\x2e([^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e'.
            '\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+|'.
            '\\x22([^\\x0d\\x22\\x5c\\x80-\\xff]|\\x5c\\x00'.
            '-\\x7f)*\\x22))*\\x40([^\\x00-\\x20\\x22\\x28'.
            '\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d'.
            '\\x7f-\\xff]+|\\x5b([^\\x0d\\x5b-\\x5d\\x80-\\xff'.
            ']|\\x5c[\\x00-\\x7f])*\\x5d)(\\x2e([^\\x00-\\x20'.
            '\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40'.
            '\\x5b-\\x5d\\x7f-\\xff]+|\\x5b([^\\x0d\\x5b-'.
            '\\x5d\\x80-\\xff]|\\x5c[\\x00-\\x7f])*\\x5d))*';

if (!preg_match("!^$addr_spec$!", $email))
{
    show_error("E-mail address not valid");
}
if (strtolower($_POST['code']) != 'rowingcover') {die('The following error occured: <br />Wrong anti-spam code. <br />
    <a href="javascript:history.go(-1)">Go back</a>');}
/* Let's prepare the message for the e-mail */
$message = "Cover.com Contact Form

From:
 $subject
 $email

Message
 $form

";

/* Send the message using mail() function */
mail($myemail, $subject, $message, "From: $email");

/* Redirect visitor to the thank you page */
header('Location: contact_received.html');
exit();

/* Functions we used */
function check_input($data, $problem='')
{
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    if ($problem && strlen($data) == 0)
    {
        show_error($problem);
    }
    return $data;
}

function show_error($myError)
{
?>
    <html>
    <body>

    <b>Please correct the following error:</b><br />
    <?php echo $myError; ?><br />
    <a href="javascript:history.go(-1)">Go back</a>

    </body>
    </html>
<?php
exit();
}
?>

我对php比较新,所以任何帮助都会非常感激。

谢谢, 马特

4 个答案:

答案 0 :(得分:1)

我发现了一些可能有助于此的事情。

<强> 1)

$mail = "$email";

$ email未定义(您在函数内部),并且没有理由在变量周围加上引号。这意味着$mail = "";

<强> 2)

$headers .= "From: \"".$nama."\" <".$mail.">\r\n\r\n";

您说$nama而不是$name,这意味着该行实际上是:

$headers .= "From:  <>\r\n\r\n";

看到原因有点困难。尝试在邮件功能之前定义主题和消息(使其更容易阅读)。

不要使用“@mail”,因为它不会告诉您遇到的任何错误。在调试时,您肯定需要错误消息。

尝试在发送HTML错误之前发送普通文本电子邮件(在该函数中),这可能有助于简化操作。然后慢慢实现HTML,看看它在哪里。

答案 1 :(得分:1)

您的问题可能是您在变量中使用带双引号: 应该是:$report_to = 'email@gmail.com';$report_to = "email\@gmail.com";

只是在我的评论中发布了答案,因为你已经解决了这个问题。

事情是在变量中使用数组而不对其进行scaping会导致在你的情况下出现一个空数组,这会给你一个错误的电子邮件。

您欢迎:)

答案 2 :(得分:0)

以下行看起来不对。

$ mail =“$ email”;应该是$ mail = $ email;

@mail(应该只是邮件(这可能是防止邮件被发送的行!

邮件($ myemail,$ subject,$ message,“来自:$ email”);应该是

邮件($ myemail,$ subject,$ message,“From:”。$ email);

希望有所帮助。

答案 3 :(得分:0)

感谢Prix在评论中回答了我的问题:

  

$ report_to =“email@gmail.com”;或   使用单引号或scape @   $ report_to ='email@gmail.com';要么   $ report_to =“email \ @ gmail.com”;以来   @被视为一个数组   不读为email@gmail.com   双引号。 - Prix 4分钟前