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.
Related
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.
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.
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?
In the MVC way of doing things, where is the best place to run, for example htmlspecialchars() on any input? Should it happen in the view (it sort of makes sense to do it here, as I should be dealing with the raw input throughout the controller and model?)
I'm not quite sure... What are benefits of doing it in the view or controller? This is just reguarding outputting to a page... to minimize potential XSS exploits.
Well, that depends, doesn't it? You should sanitize everything you OUTPUT in the view. First, because sanitization depends on the format of your output. A JSON sanitized output is different than an HTML sanitized output, right? Second, because you never want to trust the data you have. It might have been compromised through any number of ways.
That won't protect against SQL injections and such, though. Now, you never want to do that in a client-side javascript, because an attacker may easily replace that. Again, my advice is sanitization at the point of usage. If you are just writing to a file, it might not be needed. And some database access libraries do not needed it either. Others do.
At any rate, do it at the point of usage, and all the source code becomes more reliable against attacks and bugs (or attacks through bugs).
This is why thinking in design patterns sucks. What you should be asking is where is the most efficient place to do this? If the data is write-once/read-many then sanitising it every time it's output (on page view) is going to put unnecessary load on the server. Make your decision based on how the data will be used, where you can setup caching, how you do searches, etc.. not on the merits of a pattern.
From what you've said I'd perform the sanitation just ahead of writing it to the DB. Then you're not only ensuring the data is safe to insert but you're also ensuring that no future mistakes can result in unsanitised data being sent. If you ever want the original text for some reason you just invert your original transformation.
You should not be concerned about storing html encoded text in your DB since ALL text is encoded in one form or another. If you need to search the text you just encode the search string as well. If you need another format then that's another story but then you would have to evaluate your options based on your needs.
I think the best way is to escape the view - output, and store everything in original in your database.
Why ? With this method you're able to use the db records for every use case.
You can do it in the view (via javascript validation), but data coming from the rendered view to the controller is still considered untrusted, so you will still have to sanitize it in the controller.
In the examples I've seen (such as nerddinner), the sanitizing code is part of the model classes. Some people use validation libraries.
I don't there's any 'best' place to sanitize. Depending on the use case, we may need to implement sanitizing logic in more than one tiers.
The general rule is : fat model, thin controller.
Now, how you apply that rule is a different story :)
The way i think of it is your controller should really just be controlling the flow, redirecting to pages and etc. Any validation should take place in your model. If you want to do client side validation, you'd probably put it in the view. Any developer concerned about security would do validation on the client and on the server.
I put it in the "controller" as most of today's frameworks define it. (Not getting into the discussion of how pure that is) It is not something that belongs directly in a view template, but it also does not necessarily need to be in the model, as you may want the original data sometimes and not others.
So when I'm loading data from the model in the controller and assigning it to a view (smarty template, in my case), I run it through the HTML Purifier first.
I'm going to buck the answering trend here and give this advice:
Untrusted input should be confined as rigidly as possible - by reducing the number of places that you interact with input before its safety has been evaluated, you reduce your threat exposure when someone who is thinking about a bug fix or functionality improvement rather than security changes the system under discussion.
Depends on the type of user input and what the validation it is you're running on it.
If you want to clean the input, I'd put the logic in the controller, and also in the view when you output data that comes from the database (or any source really).
If you are doing data validation, I'd do it both on the client side with javascript, as well as in the model.
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.