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.
Related
I am developing a site where I am sending parameters like ids by url. I have used urlencode and base64encode to encode the parameters.
My problem is that how can I prevent the users or hackers to play with url paramenters Or give access only if the parameter value is exist in database?
I have at least 2 and at most 5 parameter in url so is this feasible to check every parameter is exist in database on every page?
Thanks
You cannot stop users from playing with your QueryString.
You can only validate them in your script before you do anything with them.
This also applies to POSTed variables as well, they can be hacked almost as easily.
So Validate, validate, validate.
In general if you concern about internal data put them in a session variable. But remember always everything out there is evil. You alway have to check if any input contain SQL injections.
If you use session cookies make sure that hey are http only. So no JavaScript can copy the session cookies and if possible never put them in the url itself. It's quiet easy to copy the url and hijacking a existing session.
This depends a bit on what you are using the parameters for. If they are private and should not be accessible to other users, you should link the data to a specific user and deny access to everyone who isn't authenticated as the correct user.
Also, always remember to sanitize user inputs, which includes URL parameters. Use prepared statements when passing user inputs to a database and encode it before serving it back to other users.
The best I would to is to validate on server side for the user entered paramters. Also I would check if the requests originated from my site (XSS & CSRF). Transmitting data post would be good but provides minimal security IMHO.
Therefore, validate and authenticate the originating location to ensure that it does not come from an outside source
Can I use a posted value in a PHP redirect header safetly without checking it:
header( "Location: $base".$_POST['return'] ); // $base is set to the base of the site
(If the user would somehow manipulate return to a file that doesn't exist it would simply return a nice 404 message)
Is there any danger in doing this? Is there anything the user can set it to that can compromise the system or in any way do damage?
The header() function is no longer vulnerable to HTTP Response Splitting. The only vulnerability you have to worry about is OWASP a10 - unvalidated redirects and forwards.
Providing a $base of anything other than the null string will prevent an attacker from forwarding a user to a remote domain, which could be useful for Phishing. Redirecting to the same domain could be useful to the attacker if are checking the referer as a form of CSRF prevention, but that is a weak form of protection that you really shouldn't be using anyway. Even with a base, the attacker can change the path by supplied a value like: /../../../admin.php, but this is still relative to the originating domain which in most cases is safe.
One great way to deal with unvalidated redirects is to avoid the problem entirely by not using a REQUEST variable. Instead store it in a $_SESSION['redirect'], and use that for the next request. To be a bit more robust, you could say $_SESSION['redirect_checkout'], or something page specific.
Another option is to use a white list, create a list of all values you would like to accept, and make sure the user supplied value is in your list.
Yes, absolutely! Don't trust any $_GET or $_POST values anytime!
Suppose a third party site posts the form. It may post whatever address.
A simple solution would be not to include the address, but a md5() hash of the address into the form. Once the form gets posted, it's the task of your script to map the hash to an actual address and then emit the Location header.
My other post might be of interest.
You might argue, that your app is bullet-proof. Why shouldn't I pass an URL directly?
In fact, even well-designed applications aren't that bullet-proof. Step back and try to remember your last 'Ah, I forgot something. Let's fix it' event.
Did you check at each point control each and any condition?
User clicks on a web-form submit-button twice. Thus controller runs twice.
User presses F5 an resubmits the last updating controller twice.
User somehow manipulated parameters and a controller gets called with off values passed in.
Therefore, I propose to not pass links or other parameters directly or unprotected / unvalidated.
#Col. Shrapnel: I'm fully aware, that any URL at any point could be submitted to a web-app. That's trivial.
Nevertheless, at a given point of control flow, there are certain acceptable next states of control flow.
To ensure, that only those next control-flow states get reached, I propose to validate.
A more general approach
In fact, my recently updated internal framework never passes any parameters as GET or POST parameters from request to request. All parameters are saved and retrieved from a user session [inside a so called Flow, a part of a bigger control flow].
Using the framework, only one single parameter - the FlowID - gets passed around. If the framework doesn't find the FlowID in the session's flow-store, the framework throws an exception and the dispatcher emits an error message.
I upvoted Stefan's answer.
I also have this to add. I wrote a nice class for building and parsing URLs. You could use it for validation, if you'd like.
See Url.php and UrlTest.php for usage.
https://github.com/homer6/altumo/tree/master/source/php/String
Hope that helps...
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.
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.
I've had another developer pose the possibility of combining and encrypting/obsfucating all the parameters to pages for php, as a security measure against manipulations via crafted urls and to prevent interior knowledge of the database (e.g. knowing the id in the database of a specific entry).
In other words, instead of single or multiple public query parameters like ids, there would be a single encrypted blob that would be decrypted server-side, and re-encrypted when links are crafted.
Are there problems with this approach? Are there substantial advantages that make it worthwhile? Is this approach used in the wild to good effect?
You should design your system to prevent unauthorized access. Obsfucating (useful encryption on data the client generates is not a possibility) is not a worthwhile defense.
For instead, instead of giving the user a database ID, given them a hash (with perhaps a session seed) of the ID. The 128bit+ search space of the hash and (for reasonable DB sizes) low probability of collisions would be a much better approach. You could also encrypt the ID on the server for values the client never needs to manipulate (with a seed) but make sure it has the same properties as the hash I mentioned—namely that the search space is very large compared to the possible value space.
If you want to prevent users from messing around with the GET arguments, i would recommend the following:
Add a hidden form to all of your pages. Clicking anywhere on the page, would fill-in some data into the form and submit it securely through POST / SSL. Along the submission details, pass the URL where you want to direct user to.
On the server side, collect arguments, put them into session either globally or under some sort of identifier which you append to the destination URL. Send redirect back. This way if user refreshes page, he's not nagged about POST data. Also if he starts messing with going back and sideways in the application, kill that session cache and send him to starting page.
I have seen this technique in some on-line banking softwares. Another benefit is that user can't open new window.
In my opinion it can add some degree of security, but would severely change development approach and give you more work. I never used this approach myself and I think that ID's are safe to pass around as long as you have a proper ORM system in place which under no circumstances won't let user A access data by user B regardless of what kind of code your developers will write.
There may be some cases when this type of URL encryption (or Obsfucating) is useful. Let's say you build a pretty robust security in your application and all your hosts are safe and sound.
Now if your operations staff happens to be external and you don't want them to know/see these sensitive data (IDs) by changing log levels on the fly then it is better to encrypt them and decrypt them on demand by individual module.
As a general practice one should not pass any sensitive data in URL parameters and care should also be taken to NOT to log them even at higher level.