Is it unsafe to use query strings in the url? - php

Our PM has ordered us to implement security for a site we've been working on.
To display product details, I make use of query strings.
My URL looks like www.domain.com?index.php&product id=1&product-type-id=4
My colleague argued that this is unsafe, and that we should hide that information from the URL. They suggested that we use a session instead.
In my opinion, nothing is unsafe about the use of query strings as long as I do server side validation, pass the active user id to my query to make sure people can only access their products.
What vulnerabilities could a URL like this cause:
www.domain.com?index.php&product id=1&product-type-id=4

When deciding between $_POST and $_GET ask yourself this: Is there any reason the user shouldn't be able to see this? Using $_GET also allows the user to bookmark or share the url, so for a product page like this I would 100% recommend continue to use it in this way. $_GET is not inherently unsafe as long as you are sanitizing anything you receive from it. They both exist for a reason and have their uses.

The security problem isn't tied to the query string. The difference between get and post are just at the protocol level and either can be forged.
The security issue comes up when you don't properly validate variables and escape them as needed.
Never trust user input. Always validate it.

Related

is it safe to use $_POST for button action?

Is it safe to use $_POST for button action ?
for ex.
<button name="submit">Table A</button>
php (what my code here does is, if i click the button(Table A) the table A will appear then, in default is not viewable.)
if(isset($_POST['submit'])) {
<table>
code....
</table>
}
FOR MY QUESTION: is it safe ? to the attacker ? like xss, sql injection, or something ? I want an advice, to have more safer website. (or atleast safer from attackers)
It is safe provided you don't echo the output or use it unescaped within a SQL statement. Also your code should really be...
if(isset($_POST['submit'])) {
...
}
to avoid errors if it isn't set
Developer has always to sanitize and to validate the input he's getting from the request.
Depending on the purposes - you need either to enforce the sanitation or to make less cleaning (for example for DB you need to clean it up/escape additionally, for HTML output to make XSS protection, etc.)
You may read up on:
How to sanitize the input (POST/GET variables, referral, cookies, user agent, and other headers)
Cross-Site Request Forgery (CSRF) prevention;
additionally you may want to use Captcha or other protection from automatic submits, etc.
For your specific purposes, in the question itself - you are not using the value of $_POST['submit'] in any way, except checking of presence, so no additional validation is needed, it's fine like that.
Short answer
NO
POST variables are not 'safe' on their own.
Long Answer:
There are many issues around authenticating POSTed variables on your PHP script. The most well known is Cross Site Request Forgeries whereby the value is sent to your page but you have no idea where the value came from, or who sent it.
To counter this you need to set up single use unique keys to send and receive, typically using PHP SESSIONS or similar concepts that can not be touched by the end user.
The second issue is that you should never ever ever trust the contents of a POSTed variable. you need to fully escape the variable as well as ensuring that the variable is given absolutely minimum access to your code, so if it is a compromised value, it is hopefully cleaned and/or it can not harm your script.
Your Code:
Looking at your question in detail you suffer from CSRF (point 1, above) in that your PHP code has no idea if the submitted button came from the page your button exists on and therefore the PHP has no idea if the browser should see the contents of "Table A". (If everyone can see it, why hide it in the first place?)
There is also the factor your code could be used by a nefarious party to send many, many POSTed submits to the script, over a short space of time (100,000 over 2 seconds) causing a DOS attack, again due to there being no validation of where the POST came from and its implied authenticity.
Further points: You need to clarify what you deem as "safe", it is a very relative term.
You can use the button with POST. But make sure, you have validated the referrer URL of the action. Because someone may try to copy your form and submit in loop. This will down your site.
So you should check the referrer URL matches with your site URL.
Also always use form token to validate the form (Like captcha)

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.

How to prevent users to change url parameter in PHP?

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

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.

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?

Categories