How to prevent URL variables tampering in PHP? - php

I am building a web app in CakePHP, authorized users can add, update, delete a record. In some controllers to add a record my URLs structure is like:
records/add/id_of_parent_record/secondvar:another_decision_dependent_value.
My concern is a user may tamper with these GET variables which would result in corrupting the whole record. I know i can use sessions for these vars, but I am looking for the best approach. Please share you knowledge and experience.

General rule of thumb is that URL variables (of any kind, so that includes everything in the URL) should only be used in selecting and displaying variables. This way, if the user screws up something, so what? They screwed up and you're not guaranteeing that support. They don't have easy ability to futz with backend data by pasting the wrong thing in (This is more or less the idea behind the RESTful GET).
If something needs to be modified, on the other hand, it should be done both with authentication (HTTP Authentication is considered more ideal) so that only users who have authority to modify can modify. It also is generally done through PUT/POST/DELETE request. In the PHP frameworks, POST would be the easiest/most common as PUT and DELETE take a good deal more effort for complete support in PHP.

Always use a POST request for this kind of stuff (Create, Update, Delete) , so it can't happen accidentally.
But even if you use POST, do not trust user input.
Also have a look at Post/Redirect/Get.

In addition to the POST and Post/Redirect/Get advice.. In general:
Never ever trust any of the information you receive in a HTTP request (including GET parameters, POSTed data, Cookies and HTTP headers). Always ensure the user has permission to perform each action on the data objects in question and you always validate on the server side that the data is as sensible as you can, before accepting and processing it.

Related

Do I always need to validate request variables

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.

SECURITY: Secure id in a url

I use the following url when I edit a post from the user :
../post/edit/3 //If the id of the post is 3 for example
To avoid that the user modifies the url intentionally, for example /post/edit/5, I use the following logic to make sure the user doesn't edit the post when he doesn't have permission:
if (//user is allowed to edit post){
//edit post
}
else {
throw new AccessDeniedException('You do not have the permission to edit this post');
}
Is this the general approach that you use when editing a post? Is there a way to do something cleaner so that the user cannot play with the id of the post in the url?
EDIT
The more I think about it, the more I realize that I have never seen an id in a url like this in a website that is concerned with security. So, I agree we can still use the id and check if the user can show/see this id, but still the user can already do too much.
Wouldn't it be better to hash the id, allowing us to generate a new encrypted ID using any available algorithm:
<?php
echo hash('md5', 'id_to_edit');
?>
What is the standard approach to secure an id in a url? In general, is it a good idea to display info like the id in a url?
Special situations may call for special measures, but in a typical situation, all that is necessary is:
Use SSL so that sessions can't be hijacked by eavesdroppers
Check the user's permissions before doing anything.
Plenty of sites do it similar to the way you described initially. For example, WordPress has URLs like https://example.com/wp-admin/post.php?post=112&action=edit. Clearly, a curious user could choose to edit the post=112 part.
So, one standard you might consider is: "Do I need to be more concerned about security and privacy than WordPress?"
If, for example, you don't want people looking at log files to know what IP addresses are editing what posts, you have a few options. Each approach has trade-offs so what the best one is will depend on what your biggest concerns are.
For example:
You might use a hash to conceal the post id number, like you suggest in your update to your question.
Or you might just send that info via a POST method (instead of GET) over SSL and not include it in your URL at all.
One advantage of the first approach is that people can use bookmarks to get back to the page. You might not want that. Or you might. Depends on your app.
One advantage of the second approach is that (for example) Google Analytics won't reveal if one post id is being accessed/edited over and over again or if many post ids are being accessed/edited. This may matter to you depending on whether such information might tell someone something and who has access to your Google Analytics stuff. Or it might not matter at all.
There are a lot of other possible considerations too, such as performance.
By the way, if you do use MD5, be sure to include something in the input that an attacker will not know. Otherwise, it will be trivial for an attacker to reverse a discovered hash via a lookup table and generate further legitimate hashes for sequential post ids. In PHP, you'd want to do something like:
hash('md5', $some_hard_to_guess_secret_string . $data_you_wish_to_hash);
There is no single best practice that applies to every situation. But in a typical situation, it is not necessary to hash the post id value or even send it through POST. In a typical situation, be sure to use SSL (so that sessions can't be hijacked) and check user permissions before doing anything and you are likely good to go.
You must treat all data coming from the client as suspect. This includes the URL. You should check that this client is indeed authenticated and that he is authorized to perform whatever action is indicated (by the URL, post data, etc). This is true even if you are only displaying data, not changing it.
It is not important if the record id is easily seen or modifiable in the URL. What matters is what can be done with it. Unless the id itself imparts some information (which would be surprising), there is no need hide it or obfuscate it. Just make sure you only respond to authenticated and authorized requests.
check permissions
don't use GET values for validation, authentication, authorization. session, post variables are ok.
to make things interesting... $x =md5(random number + post_id + userid) send all the values seperately like /edit/3?id=$x&y=rand_number when you get back to the edit page you check everything. else throw them an exception.
few more ideas involve db but if you are interested.
That's standard approach. You should alwasy check permissions on both: showing form and on action after submiting the form.
Regardless if you hash the ID or not, you must check permissions when editing a post, or someone could potentially stumble upon a page they are not supposed to be able to edit and they could cause serious damage. This could either be through randomly guessing, or through browsing through the history of another user that used your app.
Check permission before allowing someone to edit something.
That isn't to say you can't hash your IDs so they aren't quite as linear, but take a look at popular applications such as Wordpress, or even Stack Overflow. They are all based on incrementing numbers because regardless of knowing the ID or not, if you don't have permission, you can't edit it.
Obfuscating IDs will not increase security. As previously mentioned - you should always check permissions.
The reason why you might have an impression that you haven't seen url like this in a website that is concerned with security is because some of those websites are usually running on something like Java or .Net, and are using GUIDs ( http://en.wikipedia.org/wiki/Globally_unique_identifier ). Some of them however are using sequential IDs (e.g. gmail is using sequential IDs for emails).
MD5'ing is not a good idea. Cracking it is really easy, especially if it's something like md5(5684). I've looked up couple of hashes of numbers <100.000 here http://md5.noisette.ch/index.php and it found every single of them.
It can be better to use ACL for that. You can configure your application to deny everything and use ACL to give an access to the specific object.
It's a common practice not to use any hashes instead of ids in URL. Clean id allows you to grep apache logs, application logs with simple command. All logic must be in the code to give or deny access to the specific domain entity.
How much more secure do you need to be than checking if the user that's already confirmed who they are (logged in) has permission to edit the post in question? If you simply had a hashed value displayed in the address bar it would still be relatively easy to find the hashing algorithm and then they could still have control over what post they're trying to edit. Security through obscurity will always be a false sense of security.

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.

Security questions about cookies and javascript

Ok, i have always wondered if these 2 actions are possible:
To manipulate cookies. I mean, if i login for example into facebook it will save a cookie in my browser. Could i edit it in anyway? I think so since it is set into MY browser and not set locally.
To manipulare a javascript script. I mean, since javascript is read by the browser and every user can read the language, could it be edited? For example, let's say i have an ajax call that send data strings like user=basic or something (it's just an example), could someone change it to user=admin?
I hope this kind of things are not possible or i am pretty much f****d!
In that case, I'm sorry to say you are pretty much f****d.
You must always assume that everything on the client side can be manipulated by some evil hacker. This includes cookies and JavaScript.
Firefox makes this extra easy, using the Edit Cookies extension for cookies, and Firebug to edit JavaScript (and HTML and CSS).
Both users and javascript can manipulate cookie data. However, broswers have optional (maybe default) protection against setting cookie data cross-domain.
I think modifying cookies should be pretty easy, as they're stored locally. I checked and in firefox there's a bunch of sqlite files that seem to have that. I don't know much about sqlite, but it seems that modifying them should not be a problem (especially since you could get to the browser source code in this case and see how it interacts with them :) )
I'm not sure about javascript modification, it most surely can be done by messing around with low level HTTP stuff (intercepting request and sending bogus responses with the modified code). Anti cross-site scripting policies helps a little, but I wouldn't rely on them much, there should be security checks server based to be safer.
Yes/No, your domain can only manipulate cookies set by your domain. Your JS script, being on youdomain.com or localhost cannot edit a cookie set by facebook.com. Think about it, Internet would have imploded by now if you could do that.
However, users can edit their cookies at will.
Yes.
Yes and yes, and there are even tools specifically designed to make doing so easy. Getting security right is hard, and unfortunately it's something that greener web developers often completely miss.
The only thing you can really safely store in a cookie is a login token. Basically, each time your user logs in, generate something like a GUID. Save the GUID to a column in the user's record (like LoginToken or whatever) and then set their cookie to the same GUID. When they logout, clear the record's LoginToken. Then when a request comes in, you can just query your database for the user who has a LoginToken equal to the value in the cookie. It's safe to assume that by holding the token, the requestor is in fact the user represented by the token.
If a malicious user edits their cookie, they'll get nothing more than logged out, since you'd treat a not-found token the same as no token at all.
On the server, once you check a token, you then determine if that user has admin rights (usually by looking at their record).
As far as being able to modify script, that's just a fact of life. Your server code has to assume that every request is malicious. Before you do anything, verify their token and verify that they're allowed to do what they're requesting.
2 things:
Validate the data client-side for usability, but also do it server-side to prevent someone from tampering with the data
Encrypt cookies to make it harder to manipulate

URIs vs Hidden Forms

I'm working in CodeIgniter, and I want to send requests to my controller/model that have several parameters involved. Is there a difference between passing those parameters via a hidden form (i.e. using $_POST) as opposed to passing them through URIs (e.g. 'travel/$month/$day/')? Are there any security concerns with this approach?
Example Security Concern:
URIs
http://www.example.com/travel/$month/$day/
Hidden Form:
form_hidden('month',$month);
form_hidden('day',$day);
Rule of thumb — GET requests should never change the state of things. So, if you actually change something or request — use hidden forms with nonce values (to prevent accidental resubmissions and CSRF attacks). Otherwise, there's no difference.
Auth should be decoupled from URIs and POST data — there are cookies, HTTP auth and SSL client certificates. Everyone knows that there is a 11th June in 2009, and a lot of people may know that you use /$year/$month/$day/ scheme in URIs (or "year","month" and "day" POST fields) on your site. But only those who are entitled to access should be able to see what's on this page (or POST data to this URI). And, yes, both GET and POST data can be easily tampered, so you obviously have to check for validity.
If you choose URIs, if the user bookmarks the URLs,
it brings security problem.
and if any user clicks any links ,
then the target web server can now know
HTTP_REFFER, and the server administrator
can know the link.
it means he can see the URI.
so my personal opinion is that
you better choose hidden form.
If you monitor your incoming-data (users are evil goblins, remember), and clean when necessary it's not going to make much of a difference. The difference only comes down to usability: if you want users to be able to access the same results without always having to go through a form, then use the URL method.
In all honesty, your example doesn't given enough data to determine which method (POST/GET) would be appropriate for you.
Suggested Reading: GET versus POST in terms of security?
I ran into this same issue recently. When anything additional is exposed in the URL, you run the risk of exposing website methods/data. After quite a bit of research, I elected to only show variables when absolutely needed or if the page was just a simple view. The more data you expose in your URL, the more checks you'll likely need to put in place (what if the user modifies the URL in x way).
Another consideration is the ability to bookmark or link to URLs (presumably views). One idea is to hide variables in the URL via an encrypted string. You could then store the encrypted string in your database and serialize as needed. I did this for a search engine and it gave me the best of both worlds. This was with CodeIgniter.

Categories