Secure all inputs in PHP form - php

My form has several types of inputs including text, checkbox and radio. I'd like to make sure the form is secure. I used the Prestashop functions isGenericname and isCleanHTML to check the text and comment fields by ensuring the fields are valid.
Prestashop Validate.php
public static function isGenericName($name)
{
return empty($name) || preg_match('/^[^<>={}]*$/u', $name);
}
public static function isCleanHtml($html, $allow_iframe = false)
{
$events = 'onmousedown|onmousemove|onmmouseup|onmouseover|onmouseout|onload|onunload|onfocus|onblur|onchange';
if (preg_match('/<[\s]*script/ims', $html) || preg_match('/('.$events.')[\s]*=/ims', $html) || preg_match('/.*script\:/ims', $html))
return false;
if (!$allow_iframe && preg_match('/<[\s]*(i?frame|form|input|embed|object)/ims', $html))
return false;
return true;
}
This is how the function is called in the form PHP file.
if (!Validate::isCleanHtml($message))
$this->errors[] = Tools::displayError('Invalid message');
elseif (!Validate::isGenericName($fname))
$this->errors[] = Tools::displayError('Invalid First Name.');
So my question are. Is it ok to not produce an error message for inputs such as check boxes and radio box that are not valid? The only reason they'd be invalid was if someone hacked he code before sending. Or is there a better way to strip and secure the inputs?
$checkbox = Tools::getValue('checkbox ');
if (!Validate::isGenericName($checkbox ))
$validCheckbox = $checkbox;
I have 68 inputs I want to make sure are secure. Is there a good PHP function that can strip out and stop any sort of SQL injection? Prestashop documents state "getValue() does not protect your code from hacking attempts (SQL injections, XSS flaws and CRSF breaches). You still have to secure your data yourself." I'm thinking I'll need to scrub it all through trim(), stripslashes(), htmlspecialchars() but I didn't know of the most efficient way.

To prevent first order SQL injection you can use PDO with mysql prepared statement.
And when you want to display it to the html page use
htmlspecialchars(trim($value), ENT_QUOTES, "UTF-8")`
Make sure you set the appropriate character encoding in your response header correctly and use the meta tag to indicate character encoding of your HTML.
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
If you ever need to update back the html output into the database. Use
htmlspecialchars_decode(trim($value))
This should give you some protection.

Related

HTML Purifier and preg_match/$_GET/$_POST/FILTER_VALIDATE_EMAIL - is needed?

I want to ask if i need to use html purifier to avoid XSS atacks if:
already used preg_ match for example:
$userid = $_POST["userid"]; if(!preg_match("/^[a-zA-Z0-9]{3,15}$/", $userid)){
alerts('INVALID')
alerts is function with switch case to show in url alert like ...?alert=invalidid
filter_var($email, FILTER_VALIDATE_EMAIL
i'm using window.location.href.indexOf('alert') != -1) need it filter somehow values for alert?
I have also function with $_GET['alert'] to compare which alert is actually in url to echo bootstrap div class="alert-danger".
Do I need to use html purifier? Thanks for answers. In case 3, i woudn't know how to do it.
Using preg_match validation like that is a good safety measure, but your preceding line $userid = $_POST["userid"] is in itself vulnerable. Always make sure to check that the value is both set and not null:
$userid = isset($_POST["userid"] && $POST_["userid"] !== null)
Regarding your "alerts is function with switch case to show in url alert like ...?alert=invalidid", it depends on exactly what you mean by 'show', but note that displaying information entered by a user back to the user is the primary vector for XSS. If you're 'showing' it in HTML content, HTML attributes, or JavaScript data values, it's unsafe, all you will want to encode the following:
& --> &
< --> <
> --> >
" --> "
' --> ' &apos; not recommended because its not in the HTML spec (See: section 24.4.1) &apos; is in the XML and XHTML specs.
/ --> / forward slash is included as it helps end an HTML entity
This depends on the version of PHP you're using. Assuming you're above PHP 5.2.1 (which you certainly should be, as they're no longer supported), FILTER_VALIDATE_EMAIL is good validation for email addresses. If you're on PHP 5.2.1 or lower, you're vulnerable.
I'm not sure why . alert is by no means the only JavaScript method for XSS. Take,
for example, console.log.
$_GET['alert'] is vulnerable to XSS when echoed back to the page, but with the six transformations listed above, this will no longer be possible.
Using something like HTML Purifier is always a good idea. Even if you're already fully hardened against XSS, you're preventing yourself against potential future XSS vulnerabilities.
I'd also recommend reading the official OWASP guide on preventing XSS.
I'd set a flag for each validation before attempting to commit those values to a table ~ I'm presuming you're going to commit the values :)
Use a php activated popup and allow the user to close the popup window using jquery js. If someone disables js and tries to mess around it simply won't insert or update but the window telling them what they did wrong will still be there, they just won't be able to close it.
<?php
$userid = "";
if (isset($_POST['userid'])) {
$userid = $_POST["userid"];
if (!preg_match("/^[a-zA-Z0-9]{3,15}$/", $userid)) {
$flag = "user id error";
echo "
<div id='user-id-alert'>$flag
<input type='button' value='X' onclick='closePopup()' class='button-close' />
</div>
";
}
}
echo "
<script>
function closePopup() {
var elem = document.getElementById('#user-id-alert');
$('#user-id-alert').hide(200);
return false;
}
</script>
";
?>
I added an id to the alert window and a class to the close button but didn't provide css as it's out of the scope of your request.

Checking unsanitized POST values

I am just starting PHP and have a form where users can submit data. Before I display or send the data, it is sanitized and validated (trim, stripslashes, and htmlspecialchars) and saved as new variables which are then used instead of the directly submitted values.
My question is, is it safe to do anything at all with the unsanitized values? Do the security implications only become apparent when the values are displayed?
Specifically, would there be any problems with doing code such as
if(empty($_POST["theirname"]){code;}
if they tried some kind of attack or placed code into that box while submitting?
Currently I sanitize all input before checking if they are empty, but I want to avoid errors/warnings in this case if a user submits a blank box for example (as the sanitizing function could be called on POST values that don't exist)
PHP's filter_* functions. They're functions that do sanitizing for every variable you have, be it server variables (like $_SERVER, $_GET, $_POST, $_REQUEST) or your own variables.
Since you want to sanitize $_POST, here's what you should use:
$theirname = filter_input(INPUT_POST, "theirname");
if (!$theirname) {
echo "theirname is invalid!";
} else {
// your code
}
filter_input can check if the variable exists, if it's empty, and if it has anything that can make your code/website vulnerable (HTML tag injection, JS code injection, PHP code injection by evaluation, etc.). It's way better than checking it by yourself.
Of course, you can always just check it by yourself if you decide not to trust the filter_* functions, in that case you need to:
Check if the variable exists by using is_null and/or checking against NULL;
Check if the variable is empty;
Check if the variable has special characters (and escape them properly);
Check if the variable has HTML or XML tags (and escape/delete them);
Check if the variable has JS code or script tags (and escape/delete them);
Check if the variable has PHP code and if it's trying to execute it via eval;
As you can see, it's an extensive list, and if you don't want to rely on PHP's built-in functions, that's what you need to do.
Sources:
PHP: Filter Functions - Official PHP docs
PHP 5 Filter functions - W3Schools
always check for undefined variables first.
if(!is_null($_POST["theirname"])){
if(empty($_POST["theirname"]){code;}
}
It is absolutely required to check for existence for any variable.
$bingo = isset($variable);
Normally you want to first check if a variable is defined at all. You can do this by if(!is_null($_POST["theirname"]))
If it is defined, then you maybe want to check if it is empty, and if not, do some stuff. (for example sanitizing and / or validating)
if(!is_null($_POST["theirname"])){
if(!empty($_POST["theirname"])
{
//Do some stuff here
}
else
{
//send notification that the user didn't input any data
}
}
The error in your example is you have missing ) in your if judgment.
//Your code
if ( empty($_POST["theirname"]) { code; }
^^
//Code updated
if (empty($_POST["theirname"])) { code; }
Before checking if your inputs are empty, you could check if your form is defined and is not NULL.
Example:
//Reset.
$msg = $theirname = NULL;
//Check if the form is defined.
if (isset($_POST)) {
//Check input empty.
if(empty($_POST['theirname'])) {
$msg = 'Inputs are required';
} else {
$theirname = data_filter($_POST['theirname']);
}
//check $theirname.
if ($theirname) {
//Do something with $theirname...
}
}
//Filter function.
function data_filter($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
//Message.
echo $msg;
Checkout filter_var and filter_input.

XSS Protection on Yii

I need to protect my web application against xss attacks via URL.
what is the best way to do this?
the application is huge, so I can not edit each of the actions, need something general.
Examples:
http://example.com/[anyproductpage.html]?source=alert('Xss')
http://example.com/catalog/?baseUrl=alert('Xss')&q=1
http://example.com/catalog/productimagezoom?index=alert('Xss')
If you aim to manipulate your actions before handle them you can use beforeAction in your controller/component, with something like this:
protected function beforeAction($action) {
#check a preg_match on a url sanitization pattern, like "[^-A-Za-z0-9+&##/%?=~_|!:,.;\(\)]", for instance
return parent::beforeAction($action);
}
This articles shows how you can make your application secure with SQL Injections, XSS Attacks and CSRF.
Hope it helps you.
Firstly, you can use regular expressions to validate your inputs, you can generalize your inputs in some regular expresions, something like this:
$num = $_GET["index"];
if (preg_match("^\d{2}$", $num)) {
//allowed
} else {
//not allowed
}
Also you can create a white list or black list, if your inputs can be grouped into what is allowed in your application, use a white list, otherwise use a black list. This lists can be sotored in your database or files, something you can easily upgrade without affecting your application. You just have to compare your inputs with that list before proccesing your inputs.
My last recommendation is encoding, you should encode your inputs and outputs, because your data from database can contain malicious code, maybe someone put it by mistake or mischief, always think in all possibilities. For this case, I remember the functions htmlspecialchars and utf8_encode, I think you should the first function, also you can analyze your inputs and build your own encoding function.
I share the following links:
http://php.net/manual/es/function.preg-match.php
http://php.net/manual/es/function.utf8-encode.php
http://php.net/manual/es/function.htmlspecialchars.php
https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
I hope this information helps you.
Good Luck.
for all actions in same just add a event handle to onBeginRequest:
$this->attachEventHandler('onBeginRequest', [$this, 'purifyParams']);
public function purifyParams($event)
{
$userAgent = $this->getRequest()->getUserAgent();
$isIE = preg_match('/(msie)[ \/]([\w.]+)/i', $userAgent, $version);
if (!empty($isIE) && (int) $version[2] < 11) {
$purifier = new CHtmlPurifier();
$_GET = array_map(function ($param) use ($purifier) {
return $purifier->purify($param);
}, $_GET);
}
}

I need to validate my form without using JavaScript

How can I validate my form without using JavaScript? I have used the required HTML 5 attribute but as IE doesn't support IE (ANNOYING) is there a way around this with using PHP which will take time.
Thanks
You should always validate on the server side (e.g., with PHP). There are probably a lot of libraries that will make this easier and save you some time, but the principle's pretty simple:
if (isset($_POST['submit'])) {
$name = isset($_POST['name']) ? $_POST['name'] : null;
}
$errors = '';
if (!$name or strlen($name) < 5) {
$errors .= 'Name must not be empty and at least five characters';
}
if ($errors) {
echo $errors;
}
else {
//Store data from the form or whatever you want to do.
}
I would also recommend using Post/Redirect/Get
You can use PHP to validate using the server:
http://thinkvitamin.com/code/php-form-validation/
Only server side validation (ie in PHP) or using javascript. Although, I'd go for the server side part - it is the safest, since a bad user could forge bad data from the client side

Processing with lot of fields

Basically I have several big forms (lot of fields submitted) that need to be processed, which are very similar but may differ by one or two fields. Firstly all fields get escaped and assigned to a variable of their original name (thus $_POST['f_name'] will be $f_name).
Then I need to validate the data, things like certain obligatory fields must be present, certain fields much match (confirming password/email), certain fields must pass regex check. I do this via a long if/else statement, where each failure has it's own error message.
Now of course I would like to avoid this repetition of the clumsy code, and replace it with some looping function, which will be easier to edit and maintain.
However this poses a bit of a problem, especially performing the checks and assigning individual error messages.
I would be keen to hear suggestions as how would you approach developing such validation/error reporting function.
Here is a short version of what the code looks like:
$name = mysqli_real_escape_string($mysqli, $_POST['name']);
$password = mysqli_real_escape_string($mysqli, $_POST['password']);
$password_re = mysqli_real_escape_string($mysqli, $_POST['password_re']);
if ($name == '') :
$data = "Please enter name";
elseif ($password != $password_re) :
$data = "Passwords don't match";
endif;
First off I would make a function to clean your post array.
$clean_post = sanitize($_POST);
function sanitize($input) {
if (is_array($input)) {
foreach($input as $var=>$val) {
$output[$var] = sanitize($val);
}
}
else {
if (get_magic_quotes_gpc()) {
$input = stripslashes($input);
}
$input = cleanInput($input);
$output = mysql_real_escape_string($input);
}
return $output;
}
Next I would add divs with the same name as the field and set error variable within the $data array and remove the ifs in between them, personally I hate being spoon fed my form errors.
if ($name == '')
$data['name'] = "Please enter name";
if ($password != $password_re)
$data['password] = "Passwords don't match";
Finally, I would set the content of the divs to the $data array value.
<div><?=$data[name];?></div>
<input type="text" name="name" value="<?=$clean_post[name];?>">
<div><?=$data[password];?></div>
<input type="password" name="password" value="<?=$clean_post[password];?>">
<input type="password" name="password_re" value="<?=$clean_post[password_re];?>">
Hope this helps
I'm not sure that there's one cut-and-dried approach to this problem. Here's how my company has addressed this problem:
1) Front side validation. Yes, can be bypassed. However, if you're only using it as the first line of defense it's a great solution (and acceptable to some of my biggest clients including an international banking group) I love the simplicity of Cedric Dugas' inline validation script because it's basically just a few extra characters per field. Another HUGE benefit to the inline validation--it allows us to use one centralized alert area for server-side validation errors along with a simple alert trigger via css on individual elements, while the majority are caught inline and alerted which is FAR more user friendly.
2) A class that deals with "stuff" We refer to it as the "garbage in, garbage out" It takes an array of post data, sets fields based on element names, and deals accordingly. This includes data sanitizing, validations, etc. The problem with validations is that unless you have generic types data to validate, you can get into a lot of specifics which can really gum up code in a hurry. Also, this can make you actually have to do MORE work on the front end because your field names have to line up accordingly. In our case, we deal with external webform responses from clients a lot who don't necessarily appreciate the need for standardized naming of fields, and that can get to be a headache.
3) "Chunking" sections. On huge form scenarios, we've resorted to "chunking" submits in phases via Ajax to minimize the damage to the server done in one big submit. So, user updates profile information, submit happens. User does background info section, update happens...etc. It's not right for all situations, but is some it can work well...and it allows progressive validation as you move from start to finish. I certainly wouldn't ever recommend this approach for each individual question, though.
4) "Forced Sanitation" Sounds evil, huh? In cases such as zip codes, addresses, etc you can simply fix information for the client. Rather than barking about a missing Zip Code, you can get it automatically, correct 100% of the time. That's the beauty of Google and the USPS--they're free and smarter than the average user.
I'd say it's better to do this on the client side using a javascript form validator, before anything gets submitted. Do a search for javascript form validation. It'll save you a page load and force your users to correct errors before even submitting. Here's a simple example of one way, taken from the first google hit for "javascript form validation":
<form name="myForm" action="demo_form.asp" onsubmit="return validateForm()" method="post">
First name: <input type="text" name="fname">
<input type="submit" value="Submit">
</form>
<script language="javascript">
function validateForm()
{
var x=document.forms["myForm"]["fname"].value
if (x==null || x=="")
{
alert("First name must be filled out");
return false;
}
}
</script>

Categories