Is this form safe? - php

I have this form by which a user sends me an email. I don't know if it is secured, or if issues with security appear only if sql is involved...
html:
<form id="form4" action="send_mic.php" name="form4" method="post" >
<textarea name="message4" cols="4" rows="4" id="message4" ></textarea><br />
<input type="text" id="name4" name="name4" value="" /><br />
<input type="text" id="email4" name="email4" value="" /><br />
<input type="submit" value="" id="submit" />
</form>
jquery:
<script type="text/javascript">
$(document).ready(function () {
$('#form4').ajaxForm({
beforeSubmit: validate
});
function validate(formData, jqForm, options) {
var name = $('input[name=name4]').fieldValue();
var email = $('input[name=email4]').fieldValue();
var message = $('textarea[name=message4]').fieldValue();
if (!name[0]) {
alert('Please enter a value for name');
return false;
}
if (!email[0]) {
alert('Please enter a value for email');
return false;
}
if (!message[0]) {
alert('Please enter a value for message');
return false;
}
else {
$("#content").fadeOut(1000, function () {
$(this).html("<img src='images/postauto3.png'/>").fadeIn(2000);
});
var message = $('textarea[name=message4]').val('');
var name = $('input[name=name4]').val('');
var email = $('input[name=email4]').val('');
}
}
});
</script>
php:
<?php
if($_POST){
$email = $_POST['email4'];
$name = $_POST ['name4'];
$message = $_POST ['message4'];
// response hash
$ajaxresponse = array('type'=>'', 'message4'=>'');
try {
// do some sort of data validations, very simple example below
$all_fields = array('name4', 'email4', 'message4');
foreach($all_fields as $field){
if(empty($_POST[$field])){
throw new Exception('Required field "'.ucfirst($field).'" missing input.');
}
}
// ok, if field validations are ok
// now Send Email, ect.
// let's assume everything is ok, setup successful response
$subject = "New Contact";
//get todays date
$todayis = date("l, F j, Y, g:i a") ;
$message = " $todayis \n
Attention: \n\n
Please see the message below: \n\n
Email Address: $email \n\n
Message: $message \n\n
";
$from = "From: $email\r\n";
//put your email address here
mail("contact#....ro", $subject, $message, $from);
//prep json response
$ajaxresponse['type'] = 'success';
$ajaxresponse['message'] = 'Thank You! Will be in touch soon';
} catch(Exception $e){
$ajaxresponse['type'] = 'error';
$ajaxresponse['message'] = $e->getMessage();
}
// now we are ready to turn this hash into JSON
print json_encode($ajaxresponse);
exit;
}
?>
So, are there any security problems when using forms to send emails? Is this ok?
Thanks!

In general, rule of the thumb should always be: NEVER trust user provided data. And no, your code is not bullet proof. Since you do not verify nor sanitize user input and you use mail() at the same time you are vulnerable. User can easily feed you with crafted value for email4 filed. Since you use form data directly, then email4 can be used to inject additional mail headers to your outgoing mail. It these headers would be BCC: or CC: or even TO: then then you would be simply acting as spam relay. For example if I post this
some#address.com
CC: spamvictim1#foo.com, spamvictim2#foo.com, spamvictim3#foo.com,
X-Spam-Owned: Whoa
as your email4 then your header would end looking like this:
To: some#address.com
CC: spamvictim1#foo.com, spamvictim2#foo.com, spamvictim3#foo.com,
X-Spam-Owned: Whoa
to post multiline data you simply glue texts with CRLFs.
To avoid security holes like this you should consider dropping mail() and use something more clever that would take care of something like this too (not that mail() is bad, but you need to know what you are doing as it is rather low than high level function). I suggest using PHPMailer or similar package. You should always verify user provided data (especially ensure that single-line fields, like subject are really single line - stripping CRLFs suffice). Add captcha as you are open to automated form submission.

You could add a captcha to prevent spam.
You could protect against email injections by using:
filter_var($email, FILTER_VALIDATE_EMAIL)

I think this form is safe, mean that no one can really h#ck your website throught this form.
But you need to add somethings for better result:
1. You should also check the post variable in php server side, mean that you should check if email / name / message is valid of not
2. You should add some captcha to prevent spam

You can additionally wrap your server side code with
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
/* special ajax here */
die($content);
}
This will ensure the ajax request is coming on the server.
And please mind your ID that you are using in one of your jQuery selector in your question.

Even if you are not working with database, there could be security problems in email sending. Of course you can't be hacked by this form, but the problems will occure when the user will input something like this in EMail field:
email-address1#example.com // there is a new line here
CC:email-address2#example.com,email-addresses3#example.com,.............................email-addressesn#example.com
so the best you can do is sanitizing all the input fields for mail function, to prevent such spam delivery. And as #WebnetMobile.com has already sad, never trust user inputs

I don't see a security issue in there, since you are not modifying anything on your server side. Might be an issue with spam though. Add some captcha to it. The rest looks ok.

You should add captcha , client side and server side validation in form

Related

Validating number and email fields before form is sent

I am new to PHP so sorry if my question seems a bit noobish. I am creating a contact form which is working great but I need to validate two fields; the phone number and the email address, I need it to check that the phone number field has only numbers and is 11 digits long. The email field needs to be "something"#"something"."something".
If possible I would prefer to do it using only html or php (whichever is easiest), I guess that if there is a way to put the validation into the field properties, that would be the easiest way? eg: in here:
<input type="text" name="email" id="email" class="text" form="contact_form" required/>
If that is not possible then maybe in my PHP file which looks like so:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Submitting...</title>
</head>
<body>
<?php
$Name = $_POST ['full_name'];
$Email = $_POST['email'];
$Number = $_POST['phone_number'];
$Company = $_POST['company_name'];
$Message = $_POST['message'];
$formcontent="Name: $Name
\n Email: $Email
\n Number: $Number
\n Company: $Company
\n Message: $Message";
$recipient = "info#vicarage-support.com";
$subject = "Contact";
$mailheader = "From: $Email \r\n";
ini_set("sendmail_from","info#vicarage-support.com");
mail($recipient, $subject, $formcontent, $mailheader) or die("Please try again.");
echo("Form Submitted.");
?>
<script type="text/JavaScript">
<!--
setTimeout("location.href = 'http://www.vicarage-support.com/contact_us.html';",3000);
-->
</script>
</body>
</html>
Thank you in advance.
There are two ways to check form data before submission, i.e. client-side: using JavaScript, and using new (HTML5) HTML attributes for the input element. They can be used together if desired. Neither of them guarantees valid data; client-side checking should be regarded as convenience to the user, not as a way of ensuring data validity (which you need to check server-side, in this case in PHP code).
The HTML way can be exemplified this way:
<input type="email" name="email" id="email" class="text" form="contact_form"
required>
<input type="tel" name="tel" id="tel" class="text" form="contact_form"
required pattern="\d{11}" label="11 digits">
Using type="email" means that conforming browsers will check the email address format. This is a nontrivial task. Using type="tel" does not impose format restrictions (and the format varies by country and authority), but it may make browsers use a better user interface (such as a numeric keypad in touchscreen devices). The restriction is imposed by the pattern attribute. The value \d{11} means exactly 11 digits. (This is bad usability. I think you should allow spaces, and possibly parentheses and other characters as well, and strip them on the server. It is just too difficult to input an 11-digit number without any grouping. And 11 digits sounds arbitrary.)
There are several approaches to implementing the same in JavaScript. The pattern check is simple, whereas email format checks are very tough, and there are different library routines for it. In general, the check should be fairly permissive, basically just checking that there is an “#” character.
If you want to validate this form before it is submitted, that will have to be done with javascript. However, you should still check in your server side code, as javascript could be disabled, which would render javascript validation useless.
I've used this in the past, worked well for my needs.
http://validval.frebsite.nl/
Try adding three variables. First add a $pattern variable, then add two variables and use the switch function.
Sort of like...
<?php
$what = what you are checking (phone, email, etc)
$data = the string you want to check
function isValid( $what, $data ) {
switch( $what ) {
case 'Number':
$pattern = "/^([1]-)?[0-9]{3}-[0-9]{3}-[0-9]{4}$/i";
break;
//Change to a valid pattern, or configure it the way you want.
case 'Email':
$pattern = "/^[_a-z0-9-]+(.[_a-z0-9-]+)*#[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$/i";
break;
default:
return false;
break;
This shows you what you want. Now try to validate it like...
}
return preg_match($pattern, $data) ? true : false;
}
$errors = array();
if( isset($_POST['btn_submit']) ) {
if( !isValid( 'phone', $_POST['Number'] ) ) {
$errors[] = 'Please enter a valid phone number';
}
if( !isValid( 'email', $_POST['Email'] ) ) {
$errors[] = 'Please enter a valid email address';
}
}
if( !empty($errors) ) {
foreach( $errors as $e ) echo "$e <br />";
}
?>
As you can see, this will validate your form. You may have to configure it so the $pattern is set ti what you want it to be. This may not be the best way to do so, and I reccomend Javascript, but this is how you could do it with PHP and HTML.

Multiple the same forms and POST method?

I have multiple instances of the same form (name / email / message fields) on one page. They all share one class ('.contact-form') and different (dynamically generated IDs).
I validate them using jQuery Tools Validator (it's not relevant though as I have no problems with this at all):
$(".contact-form").validator();
The problem lies in my sendmail.php file I suppose, that's how I get all POST values & validate them:
//grab the fields
$address = trim($_POST['address']);
$title = trim($_POST['title']);
$message = $_POST['message'];
//check if empty
if(empty($name) || empty($title) || empty($message)) {
$wrong = true;
}
if($wrong) {
http_response_code(400);
} else {
// do stuff
http_response_code(200);
}
Now, the issues I'm facing are:
I can't send any other forms excepting the very first on the page, for the rest (even if they're properly filled) I'm getting this error:
Notice: Undefined index: address in mysitesaddress on line 3
after I send the first form - the other forms doesn't act like expected - they are getting through even if all fields are left empty (validator displays errors on front end but then fires "success" after a second because sendmail.php returns "200 OK".
Any ideas how to fix it / check every form instead of just the first one / clear POST data after sending? I'm sure there's an easy way to do that in PHP, I'm not that familiar with that language (mostly a front-end guy) so any help would be much appreciated.
Thank you!
(I've been Googling for an answer for a while now, but looks like "POST" is a tricky name and I'm getting Wordpress/blogs/forums related stuff mostly...)
[update]
Here's the HTML code of each form:
<div class="wrapper">
<form class="contact-form" action="sendmail.php" method="post" novalidate="novalidate">
<input name="title" type="text" required="required" />
<input name="address" type="email" required="required" />
<textarea name="message" required="required" ></textarea>
<input type="Submit" value="Submit" />
</form>
<div class="sucess">
Success message that replaces form ^.
</div>
</div>
The notice implies the 'address' key does not exist.
You should check if the indexes in the $_POST variables are set/exist, e.g. using the PHP isset() function.
This could be caused because you aren't sending the address in every form, just in the first or something like that.
Sample code on how you could use isset to check:
if ( isset($_POST['address']) ) {
//only set $address to the $_POST value if it is set
$address = trim($_POST['address']);
}
I can't see your HTML form code, but I'm guessing your form tag looks like this
<form action="sendmail.php" method="post">
This will take all the fields from the form that was submitted and send them via $_POST to your sendmail.php. After you process the data (edwardmp gave a great tip for making sure the data was there before trying to assign the variables), you would then redirect the page to some type of success landing or back to the original form page. The method I've been using to do this is:
if($wrong) {
$error = "Please check your entry and try again.";
header("Location: http://example.com/formpage.html?error=" . htmlencode($error),true,303);
exit();
} else {
// do stuff
$msg = "Your form was successfully submitted.";
header("Location: http://example.com/formpage.html?msg=" . htmlencode($msg),true,303);
exit();
}
This design makes it so the $_POST data is cleared by reloading the page, and allows you to send messages back to the originating page which you would display through $_GET['msg'], or $_GET['error']. This should stop the forms from submitting erroneously.

How to check if a text area 'contains' a certain phrase with javascript / php?

I'm trying to work out how to go about checking a text area to see if it contains a certain phrase.
I believe I could maybe use .indexOf?
It's just I have a validation script to check the contents of a contact form. Lately I have been receiving a fair bit of spam through. I have noticed that all these spam messages contain the phrase [url= and I thought, if I could perhaps add a small script to check if the text area contained such a phrase and, if so, stop the message being sent.
At present I have this simple snippet of javascript to check whether the text area is blank:
if (message.val()=='') {
message.addClass('highlight');
message.focus();
return false;
} else message.removeClass('highlight');
Any good ways to add something to check if the message field contains [url=
I also have a similar php validation script:
if (!$message) $errors[count($errors)] = 'Please click back and enter your message.';
Any ideas how I could add a similar validation script to check if message contains [url= in php too?
Any help would be greatly appreciated! :o)
It's unlikely that you'll stop spam by checking the contents of your textarea at the client side:- the spammer is more than likely POSTing directly to your server side script, so you'll need to do your filtering there. Also checking for a particular pattern will only work until the pattern changes and then you'll have to update your script.
A common solution to this problem is the use of a One-Time Form Token.
When you serve the form you generate a random string of characters and place that token in a hidden field in the form. You also store the token on the server in a session or in a database. When the form is submitted you match the stored and submitted tokens. This way you can be more sure that the form itself was filled in and submitted and that you aren't receiving data from a bot.
For extra security you can only allow each token to be used once only, guarding against multiple submissions.
UPDATE
A very simple, one page example
<?php
session_start();
/**
* Process the form if we have a token that we recognise
* otherwise just present the form again, you probably want to handle this a bit better
*/
if( isset( $_POST['token'] ) && isset( $_SESSION['token'] )
&& $_POST['token'] === $_SESSION['token'] ) {
// no more submissions using this token
unset( $_SESSION['token'] );
$name = clean( $_POST['name'] );
$comment = clean( $_POST['comment'] );
// process the input and redirect to a confirmation
// just echoing data for example
echo "$name said $comment";
die();
} else {
$token = uniqid();
$_SESSION['token'] = $token;
}
/**
* Stub function that cleans user input
* #param String $str
*/
function clean( $str ) {
return $str;
}
?>
<html>
<head>
<title>Form token example</title>
</head>
<body>
<form method="post">
<label>
Name<br/>
<input type="text" name="name"/>
</label>
<br/>
<label>
Comment<br/>
<textarea name="comment"></textarea>
</label>
<br/>
<label>
<input type="submit"/>
</label>
<br/>
<br/>
The token field would normally be hidden, it's displayed here so that the user can change it for testing<br/>
<input type="text" name="token" value="<?php echo $token ?>"/><br/>
</form>
</body>
</html>
check out the javascript search method and javascript match method. I prefer search becuase if you only care if it does exist then you do something like this.
var stringToSearch = "stackoverflow";
if (stringToSearch.search("over") >= 0){
//exists
}
By the way your question didn't do something right. I don't know php so i can't help you there
message.val().match('your phrase here')

How to implement a Contact Us form in my HTML site?

I am looking for a means of implementing a "Contact Us" routine/page that I can apply to my site that is purely a HTML website only.
I am assuming this will need to be a PHP process to send emails from a Contact Us form, but I am unsure how to do it.
Since you're pure HTML now, I'm assuming you're trying to keep this simple?
Use a service.
As you said you were interested in looking into PHP, you could do this with one script (say, for example, Contact.php). In your Contact.php file you would put a simple HTML form with room for name, email address, short message, etc. This form can just submit the form data to the same page, process the data, and send out an email with PHP's mail() function. Doing it this way avoids the need to display your email address to the world.
Something simple like the following should get you started, although you are going to want to check any and all user input before mailing it to yourself!
<html>
<body>
<?php
// if the form was filled out and submitted, mail it
if ( isset($_REQUEST['subButton']) )
{
$email = $_REQUEST['email'] ;
$subject = "Contact Us request from site";
$message = $_REQUEST['message'] ;
mail( "secretEmailAddress#email.com", "Subject: $subject", $message, "From: $email" );
header("location: contact.html");
}
else
{
echo "<form method='post' action='Contact.php'>
Email: <input name='email' type='text'/><br/>
Message:<br/>
<textarea name='message' rows='10' cols='30'>
</textarea><br/>
<input type='submit' name='subButton' value='Contact Us'/>
</form>";
}
?>
</body>
</html>
The easiest way is to just use a mailto: link.
Contact Us
Mailto links are very insecure. expect to get spam up the wazoo.
Instead use javascript to simply mask it.
Put this where you want the link to be setup
var mailE1 = "contact";
var mailE2 = "yoursite.com";
var linktext = "Email Us";
document.write("" + linktext + "")

How to sanitze user input in PHP before mailing?

I have a simple PHP mailer script that takes values from a form submitted via POST and mails them to me:
<?php
$to = "me#example.com";
$name = $_POST['name'];
$message = $_POST['message'];
$email = $_POST['email'];
$body = "Person $name submitted a message: $message";
$subject = "A message has been submitted";
$headers = 'From: ' . $email;
mail($to, $subject, $body, $headers);
header("Location: http://example.com/thanks");
?>
How can I sanitize the input?
Sanitize the post variable with filter_var().
Example here. Like:
echo filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
Since you're not building an SQL query or anything here, the only relevant validation that I can see for those inputs is an email validation for $_POST["email"], and maybe an alphanumeric filter on the other fields if you really want to limit the scope of what the message can contain.
To filter the email address, simply use filter_var:
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
As per Frank Farmer's suggestion, you can also filter out newlines in the email subject:
$subject = str_replace(array("\r","\n"),array(" "," "),$subject);
As others have noted, filter_var is great. If it's not available, add this to your toolchest.
The $headers variable is particularly bad security-wise. It can be appended to and cause spoofed headers to be added. This post called Email Injection discusses it pretty well.
filter_var is great, but another way to assure that something is an email address and not something bad is to use an isMail() function. Here's one:
function isEmail($email) {
return preg_match('|^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]{2,})+$|i', $email);
};
So to use this, you could do:
if (isset($_POST['email']) && isEmail($_POST['email'])) {
$email = $_POST['email'] ;
} else {
// you could halt execution here, set $email to a default email address
// display an error, redirect, or some combination here,
}
In terms of manual validation, limiting the length using substr(), running strip_tags() and otherwise limiting what can be put in.
You need to remove any newlines from input provided by users in $headers, which gets passed to mail() ($email in your case)! See Email injection.
PHP should take care of sanitizing $to and $subject, but there are versions of PHP with bugs (Affected are PHP 4 <= 4.4.6 and PHP 5 <= 5.2.1, see MOPB-34-2007).
You can use the code from artlung's answer above to validate email..
I use this kind of code to prevent header injection ..
// define some mail() header's parts and commonly used spam code to filter using preg_match
$match = "/(from\:|to\:|bcc\:|cc\:|content\-type\:|mime\-version\:|subject\:|x\-mailer\:|reply\-to\:|\%0a|\%0b)/i";
// check if any field's value containing the one or more of the code above
if (preg_match($match, $name) || preg_match( $match, $message) || preg_match( $match, $email)) {
// I use ajax, so I call the string below and send it to js file to check whether the email is failed to send or not
echo "failed";
// If you are not using ajax, then you can redirect it with php header function i.e: header("Location: http://example.com/anypage/");
// stop the script before it reach or executing the mail function
die();
}
The mail()'s header filtering above is too strict, since some users may be using the filtered strings in their message without any intention to hijack your email form, so redirect it to a page that is explaining what kind of strings that is not allowed in the form or explain it on your form page.

Categories