PHP XSS validation not working - php

I have written a simple contact form script and am trying to add XSS validation to it using the method described on W3School. Unfortunately it doesn't work as if I enter a "<" in one of the fields and then submit, it comes out as "<" when I receive it via email.
Can anyone suggest what I'm doing wrong?
Data collection section
$name = $co = $email = $tel = $message = "";
if ($_SERVER["REQUEST_METHOD"] == "POST"){
$name = test_input($_REQUEST['name']);
$co = test_input($_REQUEST['company']);
$email = test_input($_REQUEST['email']);
$tel = test_input($_REQUEST['tel']);
$message = test_input($_REQUEST['message']);
}
Data testing function
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
Many Thanks

Maybe your email client is configured to show the email as HTML. htmlspecialchars will convert < to <
Try to display your email as plain text.

Related

PHP Form sends Email even if Email and Name are invalid

Hi everyone and thanks for your time!
Although it's the first time that I try PHP, I've been making a PHP Form and so far I've been able to make it validate the fields, and also that the form doesn't send anything if the fields are empty.
Now... The fields "Name" and "Email" have validation filters...
"Name" doesn't allow more than "letters and white spaces" and "Email" doesn't allow an "invalid Email format".
Example:
Name: Rob3rt... it has a number
Email: anything... isn't an Email address
Subject and Message have no validation filters...
The problem is, that if I fill up all fields, the form sends the Email, even if the information written on "Name" and "Email" doesn't agree with their validation filters...
Q: How can I hold the form from sending an Email, until all fields have the correct information inside?
Here's the code:
// This is the validation code //
<?php
// define variables and set to empty values
$nameErr = $emailErr = $commentErr = $subjectErr = "";
$name = $email = $comment = $subject = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["name"])) {
$nameErr = "<h5>Name is required</h5>";
} else {
$name = test_input($_POST["name"]);
// check if name only contains letters and whitespace
if (!preg_match("/^[a-zA-Z ]*$/",$name)) {
$nameErr = "<h5>Only letters and white space allowed</h5>";
}
}
if (empty($_POST["email"])) {
$emailErr = "<h5>Email is required</h5>";
} else {
$email = test_input($_POST["email"]);
// check if e-mail address is well-formed
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = "<h5>Invalid email format</h5>";
}
}
if (empty($_POST["comment"])) {
$commentErr = "<h5>Message is required</h5>";
} else {
$comment = test_input($_POST["comment"]);
}
if (empty($_POST["subject"])) {
$subjectErr = "<h5>Subject is required</h5>";
} else {
$subject = test_input($_POST["subject"]);
}
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
<form>
Form comes here
</form>
// This is the sending code... I think the problem is here... //
<?php
if($_POST['name']!="" && $_POST['email']!="" && $_POST['comment']!="" && $_POST['subject']!="") {
$to = "myemail#whatever.com";
$email = "From: " . $email . "\r\n";
$subject = "" . $subject . "\r\n";
$comment = "" . $comment . "\r\n";
mail($to,$subject,$comment,$email);
echo "good";
}
else {
"bad";
}
?>
It is not working, because you never check if an error occurred, you are only checking if the fields are not empty before you send the mail.
The simplest way to fix it is replacing
if($_POST['name']!="" && $_POST['email']!="" && $_POST['comment']!="" && $_POST['subject']!="") {
with
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $nameErr === '' && $emailErr === '' && $commentErr === '' && $subjectErr === '') {
There is no no need to check for empty fields again, you have already done it before, so you just need to check if you are POSTing the form and if all errors are empty.
Some advice on how to generally improve your code:
1) Do not handle the HTTP POST in two positions (once above the form and once below). Merge it together in one PHP code block.
2) At least make sure that the user can't re-submit a successful form by reloading the site. After a successful submit, redirect the page. Something like this:
mail($to,$subject,$comment,$email);
header('Location:' . $_SERVER['REQUEST_URI'] . '?status=ok');
exit();
3) separate your HTML from your PHP or you will end up with a huge file which gets hard to maintain. Put your HTML form in a separate file and include it.
Although imho the nicest solution for a form is to sanitize in in JavaScript, submit it via AJAX (with angular, react, jQuery, whatever), handle it (and sanitize the data again) in PHP, send a 4xx HTTP header on error and return the error messages as a JSON object, which you then use in JavaScript.

the order of application of Sanitization, Escaping and Validation in php

I’m a beginner and trying to create a user registration form in php. After so much searching and reading (mostly here in stack overflow-the search was so intense - twice they asked me if I’m a robot) I came to know that I have to go through at least three (as far as I know) procedures before inserting the data in to the data base.
1.Sanitization
2.Escaping
3.Validation
My question is, what is the order of application of these procedures – which comes first and which one comes second and third.
For example I found this code online.
<?php
$emailErr = "";
$email = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["email"])) {
$emailErr = "Email is required";
} else {
$email = test_input($_POST["email"]);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = "Invalid email format";
}
}
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
They trim, remove back slashes and then replacing the html special characters before validate it with filter_var().
But I think the filter_var() should be the first to apply, is that right or I’m a stupid who doesn’t get it right ?
(By the way – as far as I know the backslashes are allowed in an email, if we use stripslashes() wouldn’t that be a problem too?)

Sanitizing Data sent to Database

This is code from my user registration site where data is being sent to the database. My question is if this is the correct and proper way to sanitize the data that is being sent? Also, how can I test it?
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
$email = test_input($_POST['email']);
$firstname = test_input($_POST['firstname']);
$lastname = test_input($_POST['lastname']);
$user = test_input($_POST['user']);
$pass = test_input($_POST['pass']);
$passnew = md5($pass);
I guess This post answers all your questions. Moreover you'll get to know when to actually escape or sanitize user input.

Prefilled Textarea Duplicated after Validation - PHP

I have a message that I need to prepopulate for a textarea. This message can be edited by users.
If there is a form validation error, the message appears to be duplicated each time that an error occurs.
<textarea name="comments" rows="20" style="width:99%;"><?=$fields['comments']?>TEXT
HERE</textarea>
I don't believe that this is an error due to the validation, but rather the field saving the content and adding it to the existing prepopulated message.
Is there a way that I can load the message and have users edit it without duplication?
I can provide any code necessary. I am currently using this code for validation:
https://github.com/benkeen/php_validation
<?php
session_start();
$_SESSION['name'] = $_POST['name'];
$_SESSION['senders_email'] = $_POST['senders_email'];
$_SESSION['address'] = $_POST['address'];
$_SESSION['city'] = $_POST['city'];
$_SESSION['state'] = $_POST['state'];
$_SESSION['comments'] = $_POST['comments'];
//e-mail message text
$body=<<<_MSG_
Hello,
$comments
Sincerely,
$name
$address
$city
$state
_MSG_;
$text = strip_tags($body);
$errors = array();
$fields = array();
$success_message = "";
if (isset($_POST['submit']))
{
require_once("validation.php");
$rules = array(); // stores the validation rules
$rules[] = "required,name,Your <em>Name</em> is required.";
$rules[] = "required,senders_email,Your <em>E-mail</em> is required.";
$rules[] = "valid_email,senders_email,Please enter a valid e-mail address.";
$rules[] = "required,address,Your <em>Address</em> is required.";
$errors = validateFields($_POST, $rules);
if (!empty($errors))
{
$fields = $_POST;
}
// no errors! redirect the user to the thankyou page (or whatever)
else
{
mail($to,$subject,$text,$headers);
header( "Location: thanks.php" );
}
}
?>

queries regarding PHP mail() 'issues'

So I recently made a basic site for a family members small company. I included a mail form, for enquiries etc.
here is the code i use:
<?php
function check_input($data){ // SANITIZE USER STRING INPUT
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
$name = check_input($_POST['name']);
$surname = check_input($_POST['surname']);
$email = check_input($_POST['email']);
$telephone = check_input($_POST['telephone']);
$comments = check_input($_POST['message']);
$message = "From: $name $surname
Email: $email
Telephone: $telephone
--------------------------------------------------------------
Comments: $comments
";
mail("#############.com","Website Enquiry from www.#######.co.uk",$message,"From: webserver");
?>
now when I try it, it works absoloutely fine. However I have noticed sometimes it is realllllly slow and so we have been receiving blank emails through the form (the user input data is not present), so it appears someone has attempted to use it and given up perhaps because it is taking too long?
I am assuming this is to do with the mail server rather than php mail. But I wanted to see if anyone could highlight potential issues that I could take to the company hosting for her?
many thanks,
check if name and email fields are entered and then proceed with mail function..this reduces getting blank emails.
<?php
if (isset($_POST['name']) && isset($_POST['email'])) //check if name and email fields are entered and then proceed with mail function
{
//process the data and send mail.
}
else
{
echo "Error missing name or email field.please enter";
}
?>
Alternatively you can also use array_key_exists()
<?php
if (array_key_exists("name", $_POST) && $_POST["name"] != "" && array_key_exists("email", $_POST) && $_POST["email"] != "")
//check if name and email fields are entered and then proceed with mail function
{
//process the data and send mail.
}
else
{
echo "Error missing name or email field.please enter";
}
?>
Actually you are not checking if someone fill the form empty that's why you are getting blank fields
<?php
function check_input($data){ // SANITIZE USER STRING INPUT
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
if(!empty($data))
{
$name = check_input($_POST['name']);
$surname = check_input($_POST['surname']);
$email = check_input($_POST['email']);
$telephone = check_input($_POST['telephone']);
$comments = check_input($_POST['message']);
$message = "From: $name $surname
Email: $email
Telephone: $telephone
--------------------------------------------------------------
Comments: $comments
";
mail("#############.com","Website Enquiry from www.#######.co.uk",$message,"From: webserver");
}
?>

Categories