Do I always need to validate request variables - php

Do I always need to validate user input, even if I'm not actually saving them to a db, file, or using them to include files etc..
Say I just wanted to echo out a request variable or I was using it to send email, is there any need to validate or sanitise it? I've always heard people say that all user input should be checked before doing anything with it, but does it actually pose any threat, if I'm not doing any of the above?

I wouldn't recommend it.
my rule is - NEVER TRUST USER'S INPUT.
lets say that your'e working on a team.
as you wrote, you build a simple form that submit the data to php file and than mail it.
after 3 weeks another team mate wants to use that form.
he's assuming that the data in the php file is clean . he dont know that you dont filtered it.
this is a crack for troubles.

Do I always need to validate user input, even if I'm not actually saving them to a db, file, or using them to include files etc..
Everything you are going to do with user supplied data depends on the context in which you are going to use it. In your single sentence you are already talking about 3 different contexts (db, file, include). Which all will need a different strategy to prevent things for that specific context.
Say I just wanted to echo out a request variable or I was using it to send email, is there any need to validate or sanitise it?
There are more things you can do besides validating and sanitizing. And yes you should handle this case (which is another context btw). Basically you should handle all user data as if it is malicious. Even if you are "just echoing it". There are numerous things I could do when you are "just echoing".
Considering we are in the context of a HTML page I could for example (but not limited to) do:
<script>location.href='http://example.com/my-malicious-page'</script>
Which can be for example an exact copy of you website with a login form.
<script>var cookies = document.cookie; // send cookieinfo to my domain</script>
Which can be used to get all your cookies for the current domain (possibly including your session cookie). (Note that this can and imho should be mitigated by setting the http only flag on the cookies).
<script>document.querySelector('body')[0].appendChild('my maliscious payload containing all kinds of nasty stuff');</script>
Which makes it possible to sideload a virus or something else nasty.
<!--
Fuck up your layout / website. There are several ways to do this.
I've always heard people say that all user input should be checked before doing anything with it
This is mostly wrong. You only need to decide how you are going to handle a piece of data once you know what you are going to do with it. This is because you want to prevent different things in different situations. Some examples are (but not limited to): directory traversal, code injection, sql injection, xss, csrf.
All above attack vectors need different strategies to prevent them.
but does it actually pose any threat, if I'm not doing any of the above
yes totally as explained above. All data that is coming from a 3rd pary (this means user input as well as external services as well as data coming out of the database) should be treated as an infectious disease.

Related

Is placing data in an href safe?

I'm wanting to pass data from one php page to another on click, and use that data in populating the linked page. At first I was going to use ajax to do this, but ran into trouble, and then realized it was as easy as placing the data in the href of the link.
My question is, is it safe to place the data directly in the href in this manner? I know that passing the data via the URL (which this ends up doing) is safe, but I heard somewhere (that I can't recall), that placing the data directly in the href of a link can cause problems with web-crawlers and the like.
Is this true? Is there anything else I should worry about in using this method? Or is this the best way for me to send data, unique to each link, to another page on click?
The PHP:
while($row = mysql_fetch_assoc($result_pag_data)) {
echo "<a target='_blank' href='secondary_imgs.php?imgId=".$row['imgId']."'></a>";
}
There should be no problems with web crawlers as they just follow the links.
There is however a potential security problem in that malicious users can address arbitrary rows in your table by altering the URL string. This may or may not be a problems depending on what the links point to.
If you need to restrict your data to particular users then this is not a good idea, otherwise, its simple and straightforward if it works for you then do it.
I think it's safe enough if you want to display some data, but never use get method to insert data, especially careful when it comes to sql. NEVER use get method to modify sql, if had to, validify the arguments first.
Be careful with post method too. In a word, never trust users, you never know.
It looks like it's safe since you're "only" querying an image with a specific id (that's all you're doing, right?). Just ask yourself if
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
9.1.1 Safe Methods
Implementors should be aware that the software represents the user in their interactions over the Internet, and should be careful to allow the user to be aware of any actions they might take which may have an unexpected significance to themselves or others.In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe".
applies.
Neither passing data through URL, nor embedding it into href is safe.
That data can be seen by user, so you are not protecting your data from user.
That data can be modified by user, so you are not protecting your data from modification and your script from getting evil or misformed parameters.
So, if you are designing the system which is going to be run under strict protection in a friendly environment - it's OK to pass params through the URL (hovewer, note that URL string is limited to 4096 characters). If not - it depends on protection level you want.
The simpliest way is to use POST requests instead of GET. THis way you'll not protect your data from evildoers, but ordinary users will not have the ability neither see nor modify it. Anyway, it's a good idea to validate the input on the server always.
Define "safe".
Without knowing the the threat model is nor how the data is used it's impossible to answer.
Certainly there are very important differences between a GET and POST (but note that a POSTed for can still send GET variables via the action URL).
It's no less dangerous using a POST rather than GET to send data. Nor using a cookie. All can be modified at the client end.
If you're talking about CSRF, then there's lots of methods to prevent this - try Google for starters.

Modify html before submitting form: prevent this hack

I came to a realization that malicious users can modify the html of a form in their browser before submitting a form.
For example, switching the names of two input fields of the same types.
I am creating a website that's largely dependent upon relationships between each entries in the database.
If this happens, it could jeopardize all functions of my sites. (I've tested it, and it does switched the inputs from the two fields who names are switched in the browser by the user, ie. me)
How could we prevent this?
If this kind of hack causes problem on the server side, you cannot fix it in your browser code. It means that you need to fix this on the server.
Anyone can generate any kind of POST or GET to your server, and you need to be prepared for that.
So, make sure that you detect this kind of tampering on the server, and deal with it there, by returning an error message, or by silently ignoring such invalid requests.
If the server is prepared for this, you can let people hack away in their browser as much as they want.
You should be validating your inputs as seen on the PHP Manual for Validation. For example, we have form inputs title and body for a post. When the user submits the post, the title should be between 1 to 40 characters, so we should validate that through PHP. Second, the body should not contain malicious text or code, so we should sanitize that with a function such as addslahes().
The entire topic revolves around PHP security. The only way to prevent hacking attempts and malicious intent is to learn security. Start learning with the link above.
As far as I know the simplest and often best solution is to check if each input field has a valid value with php before sending the query to the DB. For example, a field with the name "telephone" should only be numeric and not longer then say 10 ciphers. Make the rules strict enough and you shouldn't have any problems. In addition you should also make sure your DB fields are strict ie. only allow the length and data type you want.

PHP $_POST & Denying Fake Forms Security

I'm currently writing a web application which uses forms and PHP $_POST data (so far so standard! :)). However, (and this may be a noob query) I've just realised that, theoretically, if someone put together an HTML file on their computer with a fake form, put in the action as one of the scripts that are used on my site and populate this form with their own random data, couldn't they then submit this data into the form and cause problems?
I sanitise data etc so I'm not (too) worried about XSS or injection style attacks, I just don't want someone to be able to, for instance, add nonsense things to a shopping cart etc etc.
Now, I realise that for some of the scripts I can write in protection such as only allowing things into a shopping cart that can be found in the database, but there may be certain situations where it wouldn't be possible to predict all cases.
So, my question is - is there a reliable way of making sure that my php scripts can only be called by Forms hosted on my site? Perhaps some Http Referrer check in the scripts themselves, but I've heard this can be unreliable, or maybe some htaccess voodoo? It seems like too large a security hole (especially for things like customer reviews or any customer input) to just leave open. Any ideas would be very much appreciated. :)
Thanks again!
http://en.wikipedia.org/wiki/Cross-site_request_forgery
http://www.codewalkers.com/c/a/Miscellaneous/Stopping-CSRF-Attacks-in-Your-PHP-Applications/
http://www.owasp.org/index.php/PHP_CSRF_Guard
There exists a simple rule: Never trust user input.
All user input, no matter what the case, must be verified by the server. Forged POST requests are the standard way to perform SQL injection attacks or other similar attacks. You can't trust the referrer header, because that can be forged too. Any data in the request can be forged. There is no way to make sure the data has been submitted from a secure source, like your own form, because any and all possible checks require data submitted by the user, which can be forged.
The one and only way to defend yourself is to sanitize all user input. Only accept values that are acceptable. If a value, like an ID refers to a database entity, make sure it exists. Never insert unvalidated user input into queries, etc. The list just goes on.
While it takes experience and recognize all the different cases, here are the most common cases that you should try to watch out for:
Never insert raw user input into queries. Either escape them using functions such as mysql_real_escape_string() or, better yet, use prepared queries through API like PDO. Using raw user input in queries can lead to SQL injections.
Never output user inputted data directly to the browser. Always pass it through functions like htmlentities(). Even if the data comes from the database, you shouldn't trust it, as the original source for all data is generally from the user. Outputting data carelessly to the user can lead to XSS attacks.
If any user submitted data must belong to a limited set of values, make sure it does. For example, make sure that any ID submitted by the user exists in the database. If the user must select value from a drop down list, make sure the selected value is one of the possible choices.
Any and all input validation, such as allowed letters in usernames, must be done on the server side. Any form validation on the client, such as javascript checks, are merely for the convenience of the user. They do not provide any data security to you.
Take a look # nettuts tutorial in the topic.
Just updating my answer with a previously accepted answer also in the topic.
The answer to your question is short and unambiguous:
is there a reliable way of making sure that my php scripts can only be called by Forms hosted on my site?
Of course not.
In fact, NO scripts being called by forms hosted on your site. All scripts being called by forms hosted in client's browser.
Knowing that will help to understand the matter.
it wouldn't be possible to predict all cases.
Contrary, it would.
All good sites doing that.
There is nothing hard it that though.
There are limited number of parameters each form contains. And you just have to check every parameter - that's all.
As you have said ensuring that products exist in the database is a good start. If you take address information with a zip or post code make sure it's valid for the city that is provided. Make countries and cities a drop down and check that the city is valid for the country provided.
If you take email addresses make sure that they are valid email address and maybe send a confirmation email with a link before the transaction is authorised. Same for phone numbers (confirmation code in a text), although validating a phone number may be hard.
Never store credit card or payment details if it can be avoided at all (I'm inclined to believe that there are very few situations where it is needed to store details).
Basically the rule is make sure that all inputs are what you are expecting them to be. You're not going to catch everything (names and addresses will have to accept virtually any character) but that should get most of them.
I don't think that there is any way of completely ensuring that it is your form that they are coming from. HTTP Referrer and perhaps hidden fields in your form may help but they are not reliable. All you can do is validate everything as strictly as possible.
I dont see the problem as long as you trust your way of sanitizing data...and you say you sanitize it.
You do know about http://php.net/manual/en/function.strip-tags.php , http://www.php.net/manual/en/function.htmlentities.php and http://www.php.net/manual/en/filter.examples.validation.php
right?

Passing base64_encoded serialized data between form submissions

I'm creating a wizard-based series of forms for taking user inputs. One of the requirements for that wizard is that the script (PHP) cannot save the inputs into the database (MySQL) until the user clicks the 'Save' button, so I have to device a mechanism to transport user inputs in one form to another when the user clicks 'Previous' or 'Next' buttons. I looked into using various methods including cookies, sessions, temporary files etc, but I settled for embedding base64_encoded serialize data in a hidden field that exists in all the forms in the series. The value in this field will be decoded on form submissions and re-encoded for putting in the next form after other values from the current form are inserted.
Here is a sample of how the hidden field looks:
<input type="hidden" name="wizard:presave" value="YTo2OntzOjU6InRpdGxlIjtzOjEwOiJRdWVzdGlvbiAyIjtzOjQ6InRleHQiO3M6MTk6IlllcyBpdCdzIGEgcXVlc3Rpb24iO3M6NDoidHlwZSI7czo2OiJjaG9pY2UiO3M6NzoiY2hvaWNlcyI7YTowOnt9czo1OiJwb2ludCI7aToxO3M6Mjoib3AiO3M6MTM6ImVkaXRfZXhlcmNpc2UiO30=" />
So the questions are:
Is it considered a good/bad practice?
Is there any length limit of hidden fields in HTMLform?
What are the possible security issues?
And are there better alternatives? (with explanations, preferably without using javascript)
Thanks in advance!
I've never seen this particular method of parameter passing in my career, so I can't say whether it's good or bad. It's certainly not "standard". Standard methods would either be passing the submitted method along (unencoded/normally) using hidden inputs, or storing in session. I think you might be making work for yourself, so in that sense it would lean towards "not ideal".
As long as you are using POST for your forms, there is no defined limit for data sizes that I'm aware of in the HTTP specifications. Older servers may have practical limits, but unless you're doing something extreme such as media file uploads, they shouldn't be a worry.
Possible security issues are the normal web security flaws. Anything you take from a user and re-output to a page could contain cross-site scripting vulnerabilities and would have to be properly sanitized (this is somewhat moot if you're encoding everything). Users can craft their own data and submit it if they like. Basically, assume all the data you handle is unsafe and tainted.
Sessions would work much better here. The data the user submits wouldn't have to go through a lengthy encoding process. As well, you'd only have to validate it once. After it's been submitted and validated, you can simply store it on the server in $_SESSION and leave it alone until the final button is clicked. Otherwise, you have to worry about re-outputting it, re-receiving it, and re-validating it at each step. A malicious user could submit one set of data, have it checked and re-output as encoded data, but then craft the next form submission by unencoding, changing data, and re-encoding.
I would highly recommend that you reconsider sessions, as it simplifies all your data operations into a "do-once" scenario.
Is it considered a good/bad practice?
Depends on the purpose. As far I've only seen such constructs as a client side URL hash to remember the state of the selections in large ajax-based applications (so that they are bookmarkable) and then often also Gzipped to make it shorter. In your speficic case I'd say: make use of the HTTP session and only pass a request based identifier (also called token) in the hidden field so that you can get the associated information from the session.
Is there any length limit of hidden fields in HTMLform?
In GET the complete query string (all parameter names and values and separators together) is usually limited to 2048 characters, but you can better adhere an officious limit of 256 chars. In POST it is dependent on server configuration. Often this defaults around 2GB.
What are the possible security issues?
Well, it is obviously decode-able.
And are there better alternatives? (with explanations, preferably without using javascript)
You could Gzip it to make it shorter and less obvious. Or, as already said, make use of the session in combination with a request based identifier.
Well, you can store into the session either by serializing or just simply store it the way it is for each step. When the user clicks Save, you grab and validate the data from all the steps in the session.
tsk tsk :)
Is it considered a good/bad practice?
subjectively - bad practice..you're using the wrong hammer for the job.
Is there any length limit of hidden fields in HTMLform? - Not sure if there is a limit.
What are the possible security issues? - Possibly, quite a few, but you can sanitize the data received for every request. Besides, the data is pretty easy to decode and can be easily modified on the client side (I can see that its some sort of json that you are using :) )
And are there better alternatives? (with explanations, preferably without using javascript) - Use the right tool .. sessions perhaps?
And yes... You are most likely going to face performance and scalability issues (should you have a substantial user load) with all that sanitizing, parsing, formatting and security code running for every request.

What is the correct way to make web form input safe for a variety of contexts?

What do you all think is the correct (read: most flexible, loosely coupled, most robust, etc.) way to make user input from the web safe for use in various parts of a web application? Obviously we can just use the respective sanitization functions for each context (database, display on screen, save on disk, etc.), but is there some general "pattern" for handling unsafe data and making it safe? Is there an established way to enforce treating it as unsafe unless it is properly made safe?
Like it's already been said, there are several things to take into account when you are concerned about web security. Here are some basic principals to take into account:
Avoid direct input from users being integrated into queries and variables.
So this means don't have something like $variable = $_POST['user_input']. For any situation like this, you are handing over too much control to the user. If the input affects some database query, always have whitelists to validate user input against. If the query is for a user name, validate against a list of good user names. Do NOT simply make a query with the user input dropped right in.
One (possible) exception is for a search string. In this case, you need to sanitize, simple as that.
Avoid storing user input without sanitation.
If the user is creating a profile or uploading info for other users, you have to either have a white-list of what kind of data is acceptable, or strip out anything that could be malicious. This not only for your system's security, but for your other users (See next point.)
NEVER output anything from a user to the browser without stripping it.
This is probably the most important thing that security consultants have emphasized to me. You can not simply rely on sanitizing input when it is received by the user. If you did not write the output yourself, always ensure that the output is innocuous by encoding any HTML characters or wrapping it in a <plaintext> tag. It is simple negligence on the part of the developer if user A uploads a bit of javascript that harms any other users that view that page. You will sleep better at night knowing that any and all user output can do nothing but appear as text on all browsers.
Never allow anyone but the user control the form.
XSS is easier than it should be and a real pain to cover in one paragraph. Simply put, whenever you create a form, you are giving users access to a script that will handle form data. If I steal someone's session or someone's cookie, I can now talk to the script as though I was on the form page. I know the type of data it expects and the variables names it will look for. I can simply pass it those variables as though I were the user and the script can't tell the difference.
The above is not a matter of sanitation but of user validation. My last point is directly related to this idea.
Avoid using cookies for user validation or role validation.
If I can steal a user's cookie, I may be able to do more than make that one user have a bad day. If I notice the cookie has a value called "member", I can very easily change that value to "admin". Maybe it won't work, but for many scripts, I would have instant access to any admin-level info.
Simply put, there is not one easy way to secure a web form, but there are basic principals that simplify what you should be doing, and thus eases the stress of securing your scripts.
Once more for good measure:
Sanitize all input
Encode all output
Validate any input used for execution against a strict whitelist
Make sure the input is coming from the actual user
Never make any user or role-based validation browser-side/user-modifiable
And never assume that any one person's list is exhaustive or perfect.
I'm more than a little sceptical that such a general purpose framework could both exist and be less complex than a programming language.
The definition of "safe" is so different between different layers
Input field validation, numbers, dates, lists, postcodes, vehicle registrations
Cross field validation
Domain validation - is that a valid meter reading? Miss Jones used £300,000,000 electricty this month?
Inter-request validation - are you really booking two transatlantic flights for yourself on the same day?
Database consistency, foreign key validation
SQL injection
Also consider the actions when violations are discovered.
At the UI layer we almost certainly do not just quietly strip out non-digit chras from numberic fields, we raise UI error
In the UI we probably want to validate all fields and flag each individual error
in other layers we might throw an exception or intiate a business process
Perhaps I'm missing your vision? Have you seen anything that gets close to what you have in mind?
You cannot use a single method to sanitize data for all uses, but a good start is:
Use Filter_Var to Validate/Sanitize
Filter Var takes a number of different types of data and strips out bad characters (like non-digits for things you expect to be numbers), and makes sure it is of valid format (IP Addresses).
Note: Email Addresses are far more complicated than the Filter_Var's implementation, so Google around for the proper function.
Use mysql_real_escape_string before inputting anything into a Mysql Database
I wouldn't suggest using this until you are about to input stuff into a database, and it is probably better to just use prepared mysqli statements anyway.

Categories