DEV Community

Discussion on: PHP Validating a form using PHP

Collapse
lawrencejohnson profile image
Lawrence

None of the methods you pose, including a quick glance at the source of your library (I might've overlooked it), actually prevent malicious user data.

If you want to make sure you are dealing with sanitized user input, you should always use some type of filtration method for retrieving http header data. PHP provides this in a very easy use to fashion that while it does not cover error messaging, can easily handle most other things.

$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
if ($name === null) {
   // Key not supplied in HTTP Post headers
} else if ($name === false) {
   // Value could not be sanitized, could be from malicious input
} else if (strlen($name) === 0) {
   // Did not meet required parameter
}

$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ($email === null) {
   // key not supplied
} else if ($email === false) {
   // email is invalid
}

$product_id = filter_input(INPUT_POST, 'prodid', FILTER_SANITIZE_NUMBER_INT);
// etc, etc. There are many more options.

As noted previously, I'm not saying it's a bad idea to use a library. What is bad is that the article is presented as a "how to", but is not teaching anything about fundamentally important rules for capturing form data. It would be like having an article on how to encrypt passwords but only pointing to a library that handles everything for you. What happens when the developer needs to work in an environment that doesn't use this library?

Back to the point of this library, I would be curious to know if anyone has even checked to see if it does anything to clean malicious user input. Which would mean on top of not teaching developers the proper methods for secure form functionality, the author would also be pointing devs to blindly use a library that has security holes.

Thread Thread
jorgecc profile image
Jorge Castro Author

tsk tsk

$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);

You are changing the input. How many forms do that?.

Let's say $_POST['mail']='email@gmail.com******' and our code is:

$mail= filter_input(INPUT_POST, 'mail', FILTER_SANITIZE_EMAIL);
// ....
echo "This email [$mail] is incorrect";

This code will show the next message

This email [email@gmail.com] is incorrect

However, the email "email@gmail.com" is correct (it is because filter deleted all the extra "*" but the user doesn't see it).

A proper system would show the next message

This email [email@gmail.com********] is incorrect

Anyways, this library allows to add custom validations but it's up to the developer to do the validations. Email are common but they aren't unique, for example SSN, phone, address, product code, ISBN and such. Html (url) is anything but common and IP is really niche. This library is not aimed to validate all and every possible situation, simply because it is not realistic.

But let's say about email:

$email=$validation->type('varchar')
      ->condition('fn.global.isEmail','the field is not an email')
      ->post('email');

function isEmail($value,$comparevalue) {
    if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
        return false;
    } else {
        return true;
    }
}

where fn.global.functionname is a call to a global function.

But this example can be improved.

  • If we use SQL at some point (what if we are storing this value), then we must set a maximum length and if we use NO-SQL then we want to limit it regardless.

  • Also, what if we want to limit the domains of the email?, we don't want free emails.

  • Also, what if the email must be unique and it mustn't be on the database?.

$email=$validation->type('varchar')
      ->condition('fn.global.isEmail','the field is not an email')
      ->condition('fn.global.emailDomain','This email is not allowed')
      ->condition('fn.static.ClassDao.emailUsed','This email already exists on the database')
      ->condition('maxlen','The maximum size of the field is 50',50)
      ->post('email');

function isEmail($value,$comparevalue='') ....
function emailDomain($value,$comparevalue='') ...

class ClassDao {
  public static emailUsed(...) ...
}

where fn.static.classname.functionname is a call to a static function inside classname.

So this library has the flexibility to create your own validations and still be integrated and executed on the validation pipeline.

Thread Thread
lawrencejohnson profile image
Lawrence • Edited on

There's nothing to stop you from doing additional validation AFTER you have filtered it. You have made a very unwise choice to allow users to freely submit any form data to your code. Regardless of what you do before sending it to SQL, there are far more security implications you are completely ignoring by assuming you can just deal with that later.

Honestly, your library is fine, it's nice really. All you need to do is filter your inputs before you do all of your validation functionality. Fighting it is only going to bite you later when you have to work for an organization that cares about security.

All of this goes back to my original point that this how-to guide is only a "How to Use My Library" guide. This doesn't teach new developers a very important aspect of allowing users to submit content to your application: security.