I use a php code on my server to send messages to my clients. The programming tool I use (Game Maker) allows me to send messages via php by executing a shell so that the link appears in a browser.
Example is here ...
with all the other stuff added. So in effect, the message I'm sending and all the stuff I'm sending are seen in the browser. I use the php get method. everything works perfectly now, except that it may not be secured. Someone suggested php post method, but when I replaced get in my php cod on my server to post, and pasted the same thing in the browser, my code didn't work. It's hard to explain, but here's the php code on my server:
<?php
// Some checks on $_SERVER['HTTP_X_REFERRER'] and similar headers
// might be in order
// The input form has an hidden field called email. Most spambot will
// fall for the trap and try filling it. And if ever their lord and master checks the bot logs,
// why not make him think we're morons that misspelled 'smtp'?
if (!isset($_GET['email']))
die("Missing recipient address");
if ('' != $_GET['email'])
{
// A bot, are you?
sleep(2);
die('DNS error: cannot resolve smpt.gmail.com');
// Yes, this IS security through obscurity, but it's only an added layer which comes almost for free.
}
$newline = $_GET['message'];
$newline = str_replace("[N]","\n","$newline");
$newline = str_replace("[n]","\n","$newline");
// Add some last-ditch info
$newline .= <<<DIAGNOSTIC_INFO
---
Mail sent from $_SERVER[REMOTE_ADDR]:$_SERVER[REMOTE_PORT]
DIAGNOSTIC_INFO;
mail('info#site.com','missing Password Report',$newline,"From: ".$_GET['from']);
header( 'Location: http://site.com/report.html' ) ;
?>
I then call this php code on my site. so that in the end, the whole thing ends up in the browser address bar. I hope this makes sense. How do I make things more secured by using post so that at least the sent information cannot be seen in users history and all that.
If you replace to POST in your form you need to replace the request to POST too:
<?php
// Some checks on $_SERVER['HTTP_X_REFERRER'] and similar headers
// might be in order
// The input form has an hidden field called email. Most spambot will
// fall for the trap and try filling it. And if ever their lord and master checks the bot logs,
// why not make him think we're morons that misspelled 'smtp'?
if (!isset($_POST['email']))
die("Missing recipient address");
if ('' != $_POST['email'])
{ // A bot, are you?
sleep(2);
die('DNS error: cannot resolve smpt.gmail.com');
// Yes, this IS security through obscurity, but it's only an added layer which comes almost for free.
}
$newline = $_POST['message'];
$newline = str_replace("[N]","\n","$newline");
$newline = str_replace("[n]","\n","$newline");
// Add some last-ditch info
$newline .= <<<DIAGNOSTIC_INFO
---
Mail sent from $_SERVER[REMOTE_ADDR]:$_SERVER[REMOTE_PORT]
DIAGNOSTIC_INFO;
mail('info#site.com','missing Password Report',$newline,"From: ".$_POST['from']);
header( 'Location: http://site.com/report.html' ) ;
?>
Unless you are sending it with real GET parameters like http://www.mysite.com/send.php?email=etc; in this case you do need to set it to GET to retrieve the variables.
Related
I have a form and this bit of code to send it:
if($feedback != $errorMessage){
$emailTo = 'me#mywebsite.com';
$emailFrom = 'submissions#mywebsite.com';
$subject = 'Submission';
$body = filter_var("$contactName made a submission.
Contact Information:
Contact Name:\t$contactName
blah:\t$blah
Address:\t$address
Telephone:\t$telephone
Mobile:\t$mobile
E-mail Address:\t$userEmail
Website:\t$website
Vacancy Information:
field1:\t$field1
field2 Benefits:\t$field2
field3:\t$field3
field4:\t$field4
field5:\t$field5
field6:\t$field6
field7:\t$field7
field8:\t$field8
field9:\t$field9", FILTER_SANITIZE_STRING);
mail($emailTo, $subject, $body, "From: ".$emailFrom);
}
From what I understand from reading other threads this should be enough. I tried emailing just a single dot on a line in one of the textareas and it did turn it into 2 dots. Just running one function on it seems far too simple though.
Is this secure enough? I've read things online that seem inconsistent like that I don't even have to sanitize the body. The email body is the only thing that takes user input here.
Thanks.
Not entirely sure what you mean by secure here. Your script is just sending an email. The content of the fields will be what the user filled in. It could be link to virus, crap, spam or real content. Not easy to say, really. Not much to do with it either.
Sanitizing is much more important once databases are in use.
What else is needed to:
make this php script send an auto-response back?
sanitize and check the phone number and email that is not junk as my current formmail from dbmasters I get junk like dasawewdjz89)$%&*_sasa779%7fmsdls in almost every field including the input areas.
It is mentioned to take out the bcc and cc code, yet, I had code to sent to a different recipient based on the state, so is there a way to keep the bcc and cc fields too without compromising security?
Maybe this is 3 questions in 1, but this is essentially building upon the answer here
Replacing deprecated eregi() with stristr(). Is this php mail script secure from header injections? since it is a deprecated form and I get error logs each day now.
I believe I only need validation on input fields NOT select or radio fields, right?
I am an html/css guy so would this actual code go into the php page or as a separate contact.php page.
EDIT: The script I cannot post for some reason here with the code given (like in other forums). so I made a link to it in BOLD
..Validate without Javascript
To answer your questions:
Question 1: Don't quite understand what you mean here. Once you are in your script you can send output to the screen, generate and email, etc. This question is very vague.
Question 2: You can use regular expressions to validate various pieces of information. For example this will check a phone number in the format of XXX-XXX-XXXX and tell you if it is valid.
function validatePhone($number)
{
$test = "/^\d{3}-\d{3}-\d{4}$/";
return (preg_match($test, $number) != 0) ? true : false;
}
var_dump(validatePhone("815-555-1234"));
var_dump(validatePhone("8158791359"));
var_dump(validatePhone("blah blah 209#&$#)(##1;llkajsdf"));
This will produce:
bool(true)
bool(false)
bool(false)
Keep in mind this function is far from robust. Valid phone numbers in different formats will fail (e.g. 815 555-8846), so you will need to adjust the regexp or craft multiple regexps to meet your needs. But that should be enough to illustrate the process.
Question 3: For email, I don't really see how the BCC and CC fields are going to compromise security. What you need to focus on in that area is preventing email header injections.
Spammers have recently been using mail header injection to send spam e-mail from contact forms that have in the past viewed as secure.
If you are a webmaster you can edit your forums to ensure they are secure and safe from spammers
Anyway, I have several websites that all use a common contact form. Every contact form posts to the same script.
This is how I defend against header injections. (I typically use this script as an include file)
This script requires your html form to use action="post". Make sure this is only used on the script that the html form will be posted to. If you use this script on a regular page request, it will die().
More error checking should be done when testing posted values for bad strings. Possibly a regular expression.
<?php
// 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");
exit;
}
// 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");
exit;
}
// Host names from where the form is authorized
// to be posted from:
$authHosts = array("domain.com", "domain2.com", "domain3.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)){
logBadRequest();
header("HTTP/1.0 403 Forbidden");
exit;
}
// Attempt to defend against header injections:
$badStrings = array("Content-Type:",
"MIME-Version:",
"Content-Transfer-Encoding:",
"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($v, $v2) !== false){
logBadRequest();
header("HTTP/1.0 403 Forbidden");
exit;
}
}
}
// Made it past spammer test, free up some memory
// and continue rest of script:
unset($k, $v, $v2, $badStrings, $authHosts, $fromArray, $wwwUsed);
?>
Scenario: I have a number of Codeigniter applications that I am improving the email delivery system to use a database queue. So my application logs all emails that need to be sent into the database. I run a cron job every minute to check this database queue and send out any pending emails (throttled to my server limits as needed).
It is all working fantastically and has dramatically improved our applications.
Part of the feature is it will record when emails are not sent, and will retry again later. As part of the process I update the database to include any error messages during the send attempts, for debugging later. I do this with $this->email->print_debugger().
Once again all working ok (normally).
The problem is if an attachment was included in the email, the attachment 'data' is dumped as part of the print_debugger() - so my database gets smashed with large text dumps of attachment data.
What I tried: So I went looking in the Email.php class of codeigniter, thinking I could extend the library to just not include the attachment data in the print_debugger() function - but it seems that the error that is returned from the function is actually from the SMTP server itself in another function. I cant see a way to stop the attachment data coming through on the error.
Question/Challenge: Can anyone see a way where I can capture an SMTP error, and the email headers - but not the attachment data? I'm happy to settle for not capturing any of the email body either (since I know what that is anyway in my database queue).
I believe that you can just extend the library. This is the current function:
public function print_debugger()
{
$msg = '';
if (count($this->_debug_msg) > 0)
{
foreach ($this->_debug_msg as $val)
{
$msg .= $val;
}
}
$msg .= "<pre>".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'</pre>';
return $msg;
}
There are four main parts to what is returned:
_debug_msg - The debug messages
_header_str - The email's headers
_subject - The email's subject
_finalbody - The body of the message and the attachment data
Implementing a similar function, without _finalbody should give you the desired output but without the body and attachment data.
Here's an example solution, (with the class 'MY_Email' located here at: application/libraries/MY_Email.php):
class MY_Email extends CI_Email
{
public function my_print_debugger()
{
$msg = '';
if (count($this->_debug_msg) > 0)
{
foreach ($this->_debug_msg as $val)
{
$msg .= $val;
}
}
$msg .= "<pre>".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".'</pre>';
return $msg;
}
}
Looking through the code for the class, I think that $_body may contain the body data without the attachment data, so it could be worth trying to append $this->_body, rather than $this->_finalbody to the function. I've haven't tested this, so I'm not certain.
Hopefully this helps!
I need a little help with sending a message to my e-mail via php. Here's the code I've got so far:
<?php
$newline = $_GET['message'];
$newline = str_replace("[N]","\n"
,"$newline");
$newline = str_replace("[n]","\n"
,"$newline");
mail($_GET['to'],$_GET[
'subject'],$newline,"From: ".$_GET['from']);
echo "<FONT FACE=\"Verdana\" SIZE=\"2\">".$_GET[
'thanks']."</FONT>";?>
I uplaoded this php code to my sever, then use the execute_shell() function to send the message to my e-mail by then defining the various variables. Here's that code:
msg_to="linera#low.com";
msg_from="celebraces#gmail.com";
msg_subject="Hey, what's up?";
msg_message="This is a test email :D";
msg_thanks="Your message has been sent :D";
execute_shell("http://yourserver.com.au/
yourgame/sendmail.php?to="+msg_to+"&from="
+msg_from+"&subject="+msg_subject+"&
message="+msg_message+"&thanks="+msg_thanks,"");
The problem is that, when the message is done, it just shows msg_thanks, which I defined as a variable. I'm new to php and dont know much. All I want to do is to remove this and rather, redirect the user to a particular thank you webpage when the message is done. How do I do this?
Try header():
header("location:../thankyou.php");
I have a client whose domain seems to be getting hit pretty hard by what appears to be a DDoS. In the logs it's normal looking user agents with random IPs but they're flipping through pages too fast to be human. They also don't appear to be requesting any images. I can't seem to find any pattern and my suspicion is it's a fleet of Windows Zombies.
The clients had issues in the past with SPAM attacks--even had to point MX at Postini to get the 6.7 GB/day of junk to stop server-side.
I want to setup a BOT trap in a directory disallowed by robots.txt... just never attempted anything like this before, hoping someone out there has a creative ideas for trapping BOTs!
EDIT: I already have plenty of ideas for catching one.. it's what to do to it when lands in the trap.
You can set up a PHP script whose URL is explicitly forbidden by robots.txt. In that script, you can pull the source IP of the suspected bot hitting you (via $_SERVER['REMOTE_ADDR']), and then add that IP to a database blacklist table.
Then, in your main app, you can check the source IP, do a lookup for that IP in your blacklist table, and if you find it, throw a 403 page instead. (Perhaps with a message like, "We've detected abuse coming from your IP, if you feel this is in error, contact us at ...")
On the upside, you get automatic blacklisting of bad bots. On the downside, it's not terribly efficient, and it can be dangerous. (One person innocently checking that page out of curiosity can result in the ban of a large swath of users.)
Edit: Alternatively (or additionally, I suppose) you can fairly simply add a GeoIP check to your app, and reject hits based on country of origin.
What you can do is get another box (a kind of sacrificial lamb) not on the same pipe as your main host then have that host a page which redirects to itself (but with a randomized page name in the url). this could get the bot stuck in a infinite loop tieing up the cpu and bandwith on your sacrificial lamb but not on your main box.
I tend to think this is a problem better solved with network security more so than coding, but I see the logic in your approach/question.
There are a number of questions and discussions about this on server fault which may be worthy of investigating.
https://serverfault.com/search?q=block+bots
Well I must say, kinda disappointed--I was hoping for some creative ideas. I did find the ideal solutions here.. http://www.kloth.net/internet/bottrap.php
<html>
<head><title> </title></head>
<body>
<p>There is nothing here to see. So what are you doing here ?</p>
<p>Go home.</p>
<?php
/* whitelist: end processing end exit */
if (preg_match("/10\.22\.33\.44/",$_SERVER['REMOTE_ADDR'])) { exit; }
if (preg_match("Super Tool",$_SERVER['HTTP_USER_AGENT'])) { exit; }
/* end of whitelist */
$badbot = 0;
/* scan the blacklist.dat file for addresses of SPAM robots
to prevent filling it up with duplicates */
$filename = "../blacklist.dat";
$fp = fopen($filename, "r") or die ("Error opening file ... <br>\n");
while ($line = fgets($fp,255)) {
$u = explode(" ",$line);
$u0 = $u[0];
if (preg_match("/$u0/",$_SERVER['REMOTE_ADDR'])) {$badbot++;}
}
fclose($fp);
if ($badbot == 0) { /* we just see a new bad bot not yet listed ! */
/* send a mail to hostmaster */
$tmestamp = time();
$datum = date("Y-m-d (D) H:i:s",$tmestamp);
$from = "badbot-watch#domain.tld";
$to = "hostmaster#domain.tld";
$subject = "domain-tld alert: bad robot";
$msg = "A bad robot hit $_SERVER['REQUEST_URI'] $datum \n";
$msg .= "address is $_SERVER['REMOTE_ADDR'], agent is $_SERVER['HTTP_USER_AGENT']\n";
mail($to, $subject, $msg, "From: $from");
/* append bad bot address data to blacklist log file: */
$fp = fopen($filename,'a+');
fwrite($fp,"$_SERVER['REMOTE_ADDR'] - - [$datum] \"$_SERVER['REQUEST_METHOD'] $_SERVER['REQUEST_URI'] $_SERVER['SERVER_PROTOCOL']\" $_SERVER['HTTP_REFERER'] $_SERVER['HTTP_USER_AGENT']\n");
fclose($fp);
}
?>
</body>
</html>
Then to protect pages throw <?php include($DOCUMENT_ROOT . "/blacklist.php"); ?> on the first line of every page.. blacklist.php contains:
<?php
$badbot = 0;
/* look for the IP address in the blacklist file */
$filename = "../blacklist.dat";
$fp = fopen($filename, "r") or die ("Error opening file ... <br>\n");
while ($line = fgets($fp,255)) {
$u = explode(" ",$line);
$u0 = $u[0];
if (preg_match("/$u0/",$_SERVER['REMOTE_ADDR'])) {$badbot++;}
}
fclose($fp);
if ($badbot > 0) { /* this is a bad bot, reject it */
sleep(12);
print ("<html><head>\n");
print ("<title>Site unavailable, sorry</title>\n");
print ("</head><body>\n");
print ("<center><h1>Welcome ...</h1></center>\n");
print ("<p><center>Unfortunately, due to abuse, this site is temporarily not available ...</center></p>\n");
print ("<p><center>If you feel this in error, send a mail to the hostmaster at this site,<br>
if you are an anti-social ill-behaving SPAM-bot, then just go away.</center></p>\n");
print ("</body></html>\n");
exit;
}
?>
I plan to take Scott Chamberlain's advice and to be safe I plan to implement Captcha on the script. If user answers correctly then it'll just die or redirect back to site root. Just for fun I'm throwing the trap in a directory named /admin/ and of coursed adding Disallow: /admin/ to robots.txt.
EDIT: In addition I am redirecting the bot ignoring the rules to this page: http://www.seastory.us/bot_this.htm
You could first take a look at where the ip's are coming from. My guess is that they are all coming from one country like china or Nigeria, in which case you could set up something in htaccess to disallow all ip's from those two countries, as for creating a trap for bots, i havent the slightest idea