5

I am having a lot of trouble understanding where I as a developer can validate the data that my users send to me. Let's say for a simple example I have a web page where it has a simple form that contains three fields:

Name -> text field
email -> text field
Lunch Choice -> Dropdown field
  values:
    Burger
    Hotdog
    Pizza

Once the user submits the form their name and order is saved and they can pick up their lunch the next day.

If I am a vicious user and I got to this site and edit the html to say that the pizza value is actually salad and the value of the option is some other value.

Now when the form is submitted and saved, some bad data is going into the database.

Where can I stop this?

My first thought was to have some javascript validation, have an ajax call talk to the server to make sure the values requested are valid. This sounds like a great idea, except javascript runs on the client, not the server, so that is also susceptible to attack.

If I let the user submit the form and then handle the submit on the server and do the checking there, the user has already submitted the form so I would need to do some kind of redirect back to their form?

I'm sure I am not the first developer to have questions about input securities and I was wondering if there is a best practice for handling this type of problem.

Thanks in advance!

  • As an aside, if your site obviously requires JS (ie, it shouldn't work without it), you don't really need to handle the redirecting back to the form on validation failure. It can be great for user experience if supporting noscript users is necessary, but let me assure you from experience that it can be a lot more work. It can be a great burden off your shoulders if you simply require JS for the form and let anyone who bypasses that deal with unhelpful errors (<noscript> tags can be used to communicate to users that they need JS). – Kat Jul 4 '17 at 21:06
  • As an aside, I should make it clear that supporting users without JS is a good idea. But simply can be a lot more work (especially if you want to return them to the page with the form data partially filled back in and with helpful errors). Obviously a malicious user doesn't need that, but that makes great sense for things like fields that should be required, email addresses that are trivially incorrect, etc. – Kat Jul 4 '17 at 21:09
  • langsec.org deals with this very subject. – Matheus Moreira Jul 6 '17 at 22:00
6

Is a basic question. You should validate EVERYTHING on your server side. The back-end is the right place to make validations. Of course javascript validations are useful too to drive standard users into the right values, but for hackers (or any advanced user) is very easy to trick.

It's suppossed you have a database on back-end and you know what kind of food is able to be assigned to each user. You should check if the received value is present on the valid recordset. If is ok you can go on with your workflow. If not, you can show an error and stop the proccess.

Another important problem you'll face is not only the logical bypassing. Beware of special chars and filter everything dangerours like single quotes, double quotes, dashes, semicolons, etc... or you'll face too a sql injection or a XSS (cross site scripting) attack. That is another story... but I mention it because is very important too.

3

Oscar already posted a great answer, but in response to some of your questions:

My first thought was to have some javascript validation, have an ajax call talk to the server to make sure the values requested are valid. This sounds like a great idea, except javascript runs on the client, not the server, so that is also susceptible to attack.

That's overcomplicating things. Like you said, this is susceptible to attack and furthermore, is completely nullified when Javascript is disabled in the browser.

If I let the user submit the form and then handle the submit on the server and do the checking there, the user has already submitted the form so I would need to do some kind of redirect back to their form?

Yep.

Traditionally, if you want to use JS validation, you do it to suggest corrections at the frontend. "Hey, there's no @ in your email address. Please enter a valid email address." This saves you the round trip you describe above. Javascript is not for enforcing security, it's for enforcing a better user experience.

Then, once they enter a valid email address and submitted their content, there's no longer any way for them to bypass your mechanisms. The ball is in your court. On the server you check for the nasty things Oscar mentions, sanitize all the strings and if you detect something amiss, you do return the user back to the input page (and if you want to be nice, you repopulate the form fields using the sanitized values).

So at this point, even if JS were disabled, the user still gets an HTML message explaining they need to enter a valid email address. Yes, this does mean crafting two different sets of error messages-- one for JS, one in HTML (which is why I personally never bother with the JS validation).

Just be careful about redisplaying any of the content they provided you. If they embedded malicious code in the strings, displaying them on the resulting page without sanitizing them first can end badly.

3

Performing input validation means to check your input to be sure you can process it. The tricky part is that by validating it, you're already doing some minor processing, and that can create a hidden vulnerability.

The first step is usually to validate the length of the input. Most input will temporarily land in a finite buffer. Ensure that the amount of input you copy into the buffer doesn't exceed the length of the buffer - if there's too much input and not enough buffer, this can create a classic "buffer overflow" problem; exploiting these is a staple of hackers.

The next step is to ensure the data is in the format you expect. If you're expecting a number, ensure the bytes contain only digits and permitted number symbols, such as plus, minus, separator, decimal point, currency symbol, etc. Note that these are locale specific: in the US, a million dollars could be entered as 1,000,000.00, while in Germany a million Euros could be entered as 1.000.000,00. If you're expecting alphanumeric characters and numbers, use a "white-list" to accept only the characters you expect. It's safer to rely on a whitelist of good characters than a blacklist of bad characters; your blacklist may keep you safe with your configuration as of today, but let's say someone in the future replaces your database with a different database. It's possible one of the unexpected characters permits a SQL injection. Same is true with scripting and HTML.

Note that if you reverse these checks, and test for special characters before checking the input length, your validation code might be vulnerable to a buffer overflow. It's important to do them in the order that keeps you safest.

So the next step is to appropriately encode the input. For example, if you're going to accept < and > and put the results on a web page, you'll probably want to make sure you're HTML encoding the symbols so you don't inadvertently create a hole where an attacker can plant a <script>attack!</script> on the output page.

It's also advised to attempt to protect against SQL injections here (protect someone entering something bad like ' OR 1=1;DROP TABLE STUDENTS-- , but that's a double edged sword, because it doesn't fully guarantee protection. You might try to prevent this by putting in a validation check against accepting the apostrophe character. The next line of defense must be in the code that interfaces with SQL, and that code needs to be responsible for executing the queries safely (using Parameterized SQL queries, ORMs, or other defensive strategy.) You could pen-test your input against the above SQL injection attack, and not find a flaw because you only know about the one kind of injection attack. But let's assume the attacker figures out a new avenue of attack and tries using HTML encoding to get around your check, and it turns out you forgot to test and/or sanitize against that type of input. You could still be vulnerable unless you're careful with the SQL coding. This is a small example of how a defense in depth strategy can help keep you safe.

1

To avoid unexpected data being written to the database, validate it on the server side, right after the form is submitted, by the script/process which receives it.

Any data received from external source should be treated as potentially malicious, therefore, every process which receives it should sanitize it before processing.

Client side validation objective is to provide a user-friendly interface. Server side validation objective is to ensure that the user's input is friendly.

I recommend OWASP's Input Validation Cheat Sheet and SQL Injection Prevention Cheat Sheet.

0

Validate and Sanitise all user inputs

Theres basically two types of validation, one is essential (Server-side) one is desirable for UX (Client-side)

Client-side validation

Client-side validation that occurs in the browser, before the data has been submitted to the server. This is more user-friendly than server-side validation as it gives an instant response.

Within that there is built in browser based validation and HTML5 Constraints API / JS Based approaches.

  • Built in form validation is done with HTML5 form validation features, and generally doesn't require JavaScript. This has better performance, but it is not as customisable.

  • JavaScript validation is coded using JavaScript. It is completely customisable but also completely overridable and bypassable

Server-side validation

Server-side validation is validation that occurs on the server, after the data has been submitted — server-side code is used to validate the data before it is put into the database, and if it is wrong a response is sent back to the client to tell the user what went wrong. Server-side validation is not as user-friendly as client-side validation, as it requires a round trip to the server, but it is essential — it is your application's last line of defence against bad data. All popular server-side frameworks have features for validating and sanitising data (making it safe).

Credit to the awesome mozilla project for the above text and definitely recommended reading.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.