I'm sorry to resurrect an old thread. If that is bad karma, let me know and I'll not do it next time. However, this relates directly to the issues I addressed in this thread, so I thought I'd come back to this one.
Today I was updating my dodosmail script to move the hidden inputs to variables in the dodosmail.php script. (It seems silly to include the variables as hidden inputs in the form element, rather than just include them as variables at the top of the php file. It makes the form really messy, and is very obvious to anybody who reads your code, and announces the variables you're using. So I just included the information as php variables at the top of the dodosmail.php page.)
As I was reading the script, I became concerned that the script is, in fact, NOT completley protected against header injections. Now, I'm not a coding expert, but it looks like the code is only checking for header injections in the "your_email_address" variable, and THAT one is a variable you set yourself, so it doesn't make sense to check that variable for header injections. The email address it SHOULD be checking for header injection is the "email" variable. In addition, It should probably be checking the "name" field, since the default code takes the "name" and "email" variables and adds them to the header of the message as the FROM: part of the message that is sent back to the form author.
It looks to me like the person who updated the code to secure it from header injection didn't really know how to do it properly.
Here is the PHP code for the dodosmail script:
CODE
<?
$your_email_address="youraddress@******";
##############################################################################
# DodosMail Version 2.1 #
# Copyright 2001 Ying Zhang http://pure-essence.net/domain/contact.php #
# Created 09/04/01 Last Modified 12/02/05 #
# Regretless.com http://www.regretless.com/ #
##############################################################################
# COPYRIGHT NOTICE #
# Copyright 2001-2005 Ying Zhang. All Rights Reserved. #
# #
# DodosMail may be used and modified free of charge by anyone so long as #
# this copyright notice and the comments above remain intact. By using this #
# code you agree to indemnify Ying Zhang from any liability that #
# might arise from its use. #
# #
# Selling the code for this program without prior written consent is #
# expressly forbidden. In other words, please ask first before you try and #
# make money off of my program. #
# #
# Obtain permission before redistributing this software over the Internet or #
# in any other medium. In all cases copyright and header must remain intact.#
##############################################################################
if(empty($_GET) && empty($_POST)) {
die('Please do not access this file directly. Visit <a href="http://regretless.com/scripts/" target="_blank">dodo\'s scripts collection</a> for more information!');
}
// Emular register_globals on
if (!ini_get('register_globals')) {
$superglobales = array($_SERVER, $_ENV, $_FILES, $_COOKIE, $_POST, $_GET);
if (isset($_SESSION)) {
array_unshift($superglobales, $_SESSION);
}
foreach ($superglobales as $superglobal) {
extract($superglobal, EXTR_SKIP);
}
}
// to prevent header injection
if (eregi("\r",$_POST['your_email_address']) || eregi("\n",$_POST['your_email_address'])){
exit;
}
Note this line?? This is checking the 'your_email_address' variable from header injection. Yet, per the installation instructions, you include the <input type="hidden" value="myaddress@****" name="your_email_address"> as part of the Form data. So, this header injection isn't even checking the email address that the web user submits to the form.
I don't know what this if test is designed to check, but I don't think it is checking the right fields.
CODE
// kick anyone whoever tried to inject a header in the form
foreach( $_POST as $value ){
if( strpos($value,'Content-Type:') !== FALSE ){
exit;
}
}
$fields = array_keys($_POST);
function headfunction($url) {
header ("Location: $url");
}
// protect the variable $reserved_vars
if(isset($reserved_vars)) {
unset($reserved_vars);
}
$reserved_vars = array("css_file", "background_color", "background_image", "text_color", "link_color", "visited_link_color", "active_link_color", "font_name", "font_size", "highlight_color", "required_fields", "after_url", "check_email_address", "subject", "your_email_address", "env_report", "owner_name", "autoresponse", "response_subject", "response_mail", "dodosmail_header_file", "dodosmail_footer_file");
function include_dodosmail_header($dodosmail_header_file) {
global $reserved_vars;
foreach($reserved_vars as $reserved_var) {
global $$reserved_var;
}
if(is_file($dodosmail_header_file)) {
include_once($dodosmail_header_file);
return;
} else {
echo "<html>\n";
echo "<head>\n";
echo "<title>\n";
echo "DodosMail\n";
echo "</title>\n";
if($css_file != "")
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"$css_file\">\n";
echo "</head>\n";
echo "<body bgcolor=\"$background_color\" background=\"$background_image\" text=\"$text_color\" link=\"$link_color\" vlink=\"$visited_link_color\" alink=\"$active_link_color\">\n";
echo "<font face=\"$font_name\" size=\"$font_size\">\n";
}
}
function include_dodosmail_footer($dodosmail_footer_file) {
global $reserved_vars;
foreach($reserved_vars as $reserved_var) {
global $$reserved_var;
}
if(is_file($dodosmail_footer_file)) {
include_once($dodosmail_footer_file);
return;
} else {
echo "</font>\n</body>\n</html>";
}
}
function dodosmail_error_handle($msg) {
global $highlight_color;
if(isset($highlight_color)) {
$extra_begin = "<font color=\"".$highlight_color."\">";
$extra_end = "</font>";
} else {
$extra_begin = "<span class=\"DodosMailErrorHighLight\">";
$extra_end = "</span>";
}
return $extra_begin.$msg.$extra_end;
}
// checking required fields
// in case they used comma and space, replace
if(strstr($required_fields, ", ")) {
$required_fields = str_replace(", ", ",", $required_fields);
} else {
$required_fields = $required_fields;
}
$required_fields = explode(",", $required_fields);
for($i = 0; $i < count($required_fields); $i++) {
$required_var_name = $required_fields[$i];
if(empty($$required_var_name)) {
include_dodosmail_header($dodosmail_header_file);
echo "<p class=\"DodosMailError\">DodosMail Error - the required field ".dodosmail_error_handle($required_var_name)." is not filled.\n";
echo "<br /><br /><a href=\"java script:history.back(1)\">Back</a>\n";
echo "</p>\n";
include_dodosmail_footer($dodosmail_footer_file);
exit;
}
}
if($check_email_address == "yes" && !empty($email)) {
if(!check_email($email)) {
include_dodosmail_header($dodosmail_header_file);
echo "<p class=\"DodosMailError\">DodosMail Error - the email ".dodosmail_error_handle($email)." is not valid.\n";
echo "<br /><br /><a href=\"java script:history.back(1)\">Back</a>\n";
echo "</p>\n";
include_dodosmail_footer($dodosmail_footer_file);
exit;
}
}
for($i = 0; $i < count($fields); $i++) {
$actual_var = $fields[$i];
if(in_array($actual_var, $reserved_vars)) {
$inside_mail = $inside_mail;
} else {
if(is_array($$actual_var)) {
$inside_mail.= "$actual_var: ";
foreach($$actual_var as $actual_val) {
$inside_mail.= "$actual_val ";
}
$inside_mail.= "\n";
} else {
$actual_val = stripslashes($$actual_var);
$inside_mail.= "$actual_var: $actual_val\n";
}
}
}
// getting other information from the form
$cname = gethostbyaddr($_SERVER[REMOTE_ADDR]);
$inside_mail.=
"
-----------------------------------------------------------------------
SENDER INFO:
IP: $_SERVER[REMOTE_ADDR]
Computer Name: $cname
Browser Type: $_SERVER[HTTP_USER_AGENT]
Page Referer: $_SERVER[HTTP_REFERER]
-----------------------------------------------------------------------
Powered by DodosMail 2.0
http://regretless.com/scripts
";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "X-Priority: 3\r\n";
$headers .= "X-MSMail-Priority: Normal\r\n";
$headers .= "X-Mailer: DodosMail 2.0 http://regretless.com/scripts/\r\n";
$headers .= "Content-type: text/plain; charset=\"iso-8859-1\"\r\n";
//$headers .= "Date: ".date("R")."\r\n";
$headers .= "From: $name <$email>\r\n";
I've got a problem with this line as well. Not that the header is modified to include the $name data from the form, as well as the $email data from the form.
Isn't this a security hole if the the $name and $email variables aren't being checked for header injection as well?
CODE
$success = mail($your_email_address, $subject, $inside_mail, $headers);
if($success) {
if($autoresponse == "yes") {
$response_subject = stripslashes($response_subject);
$response_mail = stripslashes($response_mail);
mail($email, $response_subject, $response_mail, "From: $owner_name <$your_email_address>");
}
if($after_url == "") {
// out put send info
include_dodosmail_header($dodosmail_header_file);
echo "<p>\n";
echo "The following email has been sent successfully!</p><ul>";
for($i = 0; $i < count($fields); $i++) {
$actual_var = $fields[$i];
if(in_array($actual_var, $reserved_vars))
echo "";
else {
if(is_array($$actual_var)) {
echo "<li>$actual_var: ";
foreach($$actual_var as $actual_val) {
echo "$actual_val ";
}
echo "</li>\n";
} else {
$actual_val = stripslashes($$actual_var);
echo "<li>$actual_var: $actual_val</li>\n";
}
}
}
echo "</ul>\n<p><a href=\"http://regretless.com/scripts/\">DodosMail</a> v2.0</p>";
include_dodosmail_footer($dodosmail_footer_file);
exit;
} else {
headfunction($after_url);
}
} else {
include_dodosmail_header($dodosmail_header_file);
echo "<p class=\"DodosMailError\">DodosMail Error - the owner the php server is experiencing techinical difficulties. Please email use ".dodosmail_error_handle($your_email_address)." to send your email.\n";
echo "<br /><br /><a href=\"java script:history.back(1)\">Back</a>\n";
echo "</p>\n";
include_dodosmail_footer($dodosmail_footer_file);
exit;
}
function check_email($email) {
if( (preg_match('/(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/', $email)) ||
(preg_match('/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/',$email)) ) {
return true;
}
return false;
}
?>
Anyway, if I'm wrong, somebody please let me know. However, if what I'm thinking is right, then this version of dodosmail MAY NOT be secure from header injections. If somebody else can confirm that what I see as holes are valid concerns, then I'd encourage you who are using dodosmail to find a different form script.
Does anybody else know of a
free form mailer that is secure from header injection? Other form mailers suggested in recent days are no longer free...