HTML php form validation and security - php

I have decided to remove my email address (an image) from my buisiness website and use a HTML form with reCAPTCHA to keep out the bots, so i have been learning some php.
The more i learn the less certain i am about the way forward.
I have two scenarios at the moment:
1 - I use somthing simple like:
<?PHP
$email_to_me = "my email address";
$name =$_POST['name'];
$email =$_POST['email'];
$comment =$_POST['comment'];
mail($email_to_me, $name, $comment, "from: .$email");
header("Location: contact.html");
?>
which will email me the message, redirect the user back to where they were but will not give the user a message sent confirmation.
2 - I use somthing like:
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = test_input($_POST["name"]);
$email = test_input($_POST["email"]);
$comment = test_input($_POST["comment"]);
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
Plus some field validation/error messages in the form.
Hopefully this will keep me on my HTML contact page and allow feedback to users of errors filling in fields and a confirmation can be message sent.
Is the second method safe against Cross-site scripting and other hacking methods?
I am getting my info from the www3schools.com.
I just want rid of the spam and virus attacks an email address on a website causes.
Any comments, thoughts, sites with relevent info, alternatives appreciated.
Thanks Uncoded

PHP do not allow site scriptings. Look for offsite domains in your javascript. Protect your data (which you store in db) with escape string and so on. If you need to solve some problem add your code in a question.

Related

Restrict particular characters in HTML form

I'm sure this is a simple question, that you'll be annoyed at and answer with a simple link.
My issue is that I can't find what I'm looking for, because I don't understand enough about PHP/MySQL/HTML forms to come up with a particularly Google-able query.
I want to restrict the character set for an email field in a manner like:
*#*.tld
or
*#domain.tld
if that makes sense?
Thanks in advance,
If you want to check domain in your email you can try with this one
$arr = explode('#', $email_address);
if ($arr[1] == 'domain.tld')
{ // Then it's correct }
Or if you want to validate email address, You can validate your email address after form submission with filter_var() in server side
<?php
$email_a = 'joe#example.com';
$email_b = 'bogus';
if (filter_var($email_a, FILTER_VALIDATE_EMAIL)) {
echo "This ($email_a) email address is considered valid.";
}
if (filter_var($email_b, FILTER_VALIDATE_EMAIL)) {
echo "This ($email_b) email address is considered valid.";
}
?>
Have a look here for details:
http://php.net/manual/en/filter.examples.validation.php

Have three separate session for quiz submission in html/php

I have a quiz which has two part. The first part is the form and the second part is the confirmation of the quiz.
The Form: The Form
I am using the POST method. So if the user submits the form and goes to the congratulation page and refreshes it, it will keep sending email out. I am trying to prevent it.
The Relevant PHP:
I am trying to change something in the following code:
if($fname <> "" and $lname <> "" and $ydept <> "") {
mail ($myEmail, $mailSubject, $msgBody, $header);
mail ($userEmail, $sentMailSubject, $sentMailBody, $sentHeader);
to something like this:
if($fname <> "" and $lname <> "" and $ydept <> "") {
mail ($myEmail, $mailSubject, $msgBody, $header);
mail ($userEmail, $sentMailSubject, $sentMailBody, $sentHeader);
header ("redirect me to another php page with the $fname included to be used as a variable");
}
else {
display not complete exam page and redirect me to the form;
}
I would like $fname or any other variable to carry over to the congratulation.php page, so rather than the email be sent out on the same page as the congratulation page, it will be a different page so no matter how many times the user refreshes, nothing happens.
In order to prevent the user from refreshing the page and having an email sent again, what you need to do is redirect to another page as you have it. However in the redirected page, you will be using GET instead of POST.
$name = urlencode($name);
$email = urlencode($email);
header("Location: well_done_chap.php?var1=$name&var2=$email");
Then in well_done_chap.php (or whatever you call it), just do:
if (isset($_GET['var1']) && isset($_GET['var2'])) {
$name = $_GET['var1'];
$email = $_GET['var2'];
// Do your other stuff here
} else {
echo "Invalid access";
}
From your comment, "I would like $fname or any other variable to carry over to the congratulation.php page" I would recommend simply passing the $_POST array to a session variable, or, perform your calculations and save the necessary data to a separate array, and pass that array as a session variable. Does that make sense?
Ref. http://www.phpriot.com/articles/intro-php-sessions/7

Is this form safe?

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

PHP: Email validation and accepting email address from a certain domain

I am currently working with AJAX/JS to have form without a button click or page refresh. The inquiry I have is in regards of email validation. Right now the PHP code checks if an email address is valid or not. I would like to only have it accept emails from a certain domain. How can I achieve through php to accept only email address from gmail? Example
PHP for validation of email:
if($_POST) {
$email = $_POST['email'];
if (preg_match('|^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$|i', $email)) {
echo ('<div id="email_input"><span id="resultval">'.$email.'</span></div>');
}
else {
echo ('<div id="email_input"><span id="resultval">Include a valid email address.</span></div>');
}
}
Php has an easy function to help you with checking if an email address is valid:
$isValid = filter_var($email, FILTER_VALIDATE_EMAIL);
To check if the email adress is a gmail address, the following would do the trick:
list ($user, $domain) = explode('#', $email);
$isGmail = ($domain == 'gmail.com');
Be careful with your regex, it won't validate all actual email addresses.
You have a built-in PHP function to check if an email is valid :
$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
If this returns true, then you just have to check if the string ends with #gmail.com. Note that there may be some strange issues with this function, because email validation standards can be surprising.
If you really want a regex which validates all email addresses, here it is :
(?:[a-z0-9!#$%&'*+/=?^_{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")#(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
You should change you're regular expression to this
'|^[A-Z0-9._%+-]+#gmail\.com$|i'

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