PHP - prevent users from play around with url GET variables - php

I have the following url
localhost/url/index.php?user_id=3
what is the best way to prevent site users from doing something like ?user_id=whatever, and i really dont want to use POST for some reasons in this case

Don't shoot querystring parameters ($_GET) directly into the database without some sort
of sanitizing (suggestion: use stored procedures).
Use some kind of authorization to protect resources
the user shouldn't be able to access.
Display a nice error page.

In this case you can use:
$_COOKIE['user_id'] = 10 or
$_SESSION['user_id'] = 10
In my opinion, Session would be better as you can log them out after every session of theirs and as said by #mehdi, it cant be edited by users, unlike cookies.
to use session, you will need session_start(); in front of every file

In addition to all that has been mentioned, since you are building the correct query string, etc. then include a hash of some sort that is a hash of all of the bits of data. The same applies when storing data on the client's machine as a cookie...
When you receive the GET (or read the cookie), use the data in it to re-calculate the hash, and stop/redirect/error out if the data no longer validates the hash check. When you do this, use some server-side salt that isn't displayed in the URL or in web page source, etc.
$user=3;
$urlGet="?userid=".$user."&uuid=".sha1($user."salt");
print("<a href='/index.php".$urlGet."'>click</a>");
Then when the link is clicked...
if(sha1($_GET['userid']."salt")!==$_GET['uuid']){
header("location: /index.php");
exit'
}

Related

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

PHP Session Security Question

I was doing some research on StackOverflow on how to properly set sessions and prevent hijacking, etc. I found an answer that someone posted on one of the questions and he provided the following code:
For when a user logs in and the username and password match
$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] .''. $_SERVER['REMOTE_ADDR']);
Checking if user is logged in, for protected pages:
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] .''. $_SERVER['REMOTE_ADDR'])) {
session_destroy();
header('Location: login.php');
exit();
}
It seems to work fine, but my questions are: how secure is this, is this a good method or should I try something else? The post had no upvotes or anything so not sure if it's good.
Also, not sure how to get information about a user with this session .. do I need to store anything in the database?
Thank you!
There are two major problems with this code.
1) IP addresses change for legitimate reasons. If the client is behind a load balancer, like at a corporate network, then he will be unable to use your web app.
2) Checking the user agent is a lot like having a get variable that says ?is_hacker=false. If the hacker has the session id, he has the user agent and its trivial to spoof.
Further more i have no idea why you would want to use md5 for this when doing a plain text comparison is actually more secure. Because the user agent is first an attacker could use the md5 prefixing attack to produce a collision and there for would bypass the REMOTE_ADDR check. (A useful md5 collision attack doesn't come up too often, but this one is fun!)
Even with this check in place CSRF and XSS can still be used to influence the session. XSS can be used to read a CSRF token and then use XHR to make any request the attacker desires. One could make the argument that this is trying to mitigate OWASP a9, but really you need to be using SSL to protect the session id.
This looks like a good method, however the fingerprint hash is generated by client data, which can be spoofed. A good method to use for the login form is to generate a random token that is stored in the session and passed through the form. Once the token is validated (or not) it should be unset for a one time use only.
The session should also store the user id once the user is logged in to retreive the user info stored in the databse.
I agree with Rook's comments, it's a pretty good analysis of your code.
There's lots to consider for securing PHP sessions but with an up to date version of PHP it's not difficult to achieve, some things to think about:
- Where the session files are stored on your server (mainly an issue if it's a shared server)
- Using a secure connection for all sensitive data and cookies going between the client & server
- Doing what you can to make the cookie session ID on the client secure
- Not storing any sensitive data in a session variable
As for storing things in a database it depends on your needs but I'd say you probably don't need it and storing data in the session variable is fine for security, just (as I've already stated) don't store anything sensitive there. Retrieve sensitive data from another location, most likely a database.
If you need to know more about PHP session security I've got a series of blog posts on the subject.

get or session?

i have a login form, which is in login.php. after authorization i moove client to some.php file! so, from following two methods, which is better?
i can send information aboud user id e.t.c by GET
i can use SESSION - s for this
what is more preferred?
and two words about why i ask this question.
i hear somewhere that SESSIONs aren't good programing method, and it's not suggested to use them in such situations...
thanks
Sessions are indeed the preferred solution. You can't trust data sent in the querystring ($_GET, $_POST, $_COOKIE etc) because all of those can be changed by the user, but you can trust the that noone has tampered with the $_SESSION data since $_SESSION is stored on the server.
There's nothing inherently bad about sessions. In fact, in this situation I would store the userid in the session rather than passing it around in the URL. It'll be much cleaner, and more professional, IMHO. Storing trivial information in the session is fine.
$_SESSION might have its flaws, but using $_GET for this kind of thing is even worse.
If I understand the question right, then none. Use POST for this instead and then create SESSION upon logging in.
Let's say user comes to index.php where is login form. He fills in info and push "login". You send the data to login.php using POST. If the user name, password and whatever other information is correct, you create SESSION and redirect user somewhere else.
I would use SESSION if you want to store some information, that is based on the authentication success. Data in GET, POST variables is too easy to manipulate.
If you have to decide between $_SESSION and $_GET, then, for secure stuff, use $_SESSION. All the user can do with sessions is destroy them (by deleting the PHPSESSID cookie), but the user cannot manipulate them.
If you have to pass information once, $_SESSION is very good. You can store some data into the $_SESSION variable, change location via PHP (so the user cannot block the script by means of disabling JavaScript. Just use header('Location: '.$path);), use the $_SESSION content on the other page and the user does not have a time interval when he could destroy the session. This is safe.
The safest way would be to use SESSIONS because that would mean that only a token|identifier is stored on the client side, and all of the data represented by the token|identifier is stored on the server. Besides you can set expiry time for sessions too, that would make it more secure.
SESSION is the best solution . Which makes more secure one .User cant alter any of his data

Login system and sessions (php)

I've created a login page and registration page and now I want to use that to password protect pages and have pages which show information specific to that user.
Would storing the user ID of the user logged in in a Session variable be a safe and correct way of doing this?
How easy would it be for a user to change the session variable to a different ID and access another user's information, and not having to type the users login details in?
EDIT: Would posting the user ID from each page to the next be more secure?
Here's an article on session security
If you encrypt user name in such a way that only your PHP scripts can decrypt it then you should be safe I guess.
That's what session meant to be
For session security, you can check http://phpsec.org/projects/guide/4.html
While I'm not aware of any way in which a user could manipulate the information in $_SESSION unless your code (or code on your server) allows them to, so don't do anything crazy like...
foreach($_POST as $key=>$value) { // DON'T DO THIS
$_SESSION[$key] = $value; // DON'T DO THIS!
} // WHY ARE YOU DOING THIS!?
You shouldn't do anything like this, where you're just putting whatever data the user gives you in your $_SESSION variables. Like the database, writing to the session should be thought of as a form of output, and you should sanitize what you put in it (and where it's put) accordingly.
So, unless you're doing something crazy like this (you might be; it can be much more subtle), I don't think you have to worry about a user changing the session variable. You might have to worry about the threats of a shared hosting environment where someone who's probably not quite an end user is manipulating the session info.
What's not so safe is the session identifier, as there are a few straightforward ways to hijack a session in PHP.
I recommend checking out that book I've been linking to, Essential PHP Secutiry. It's a very small and straightforward (but thorough) explanation of several basic PHP security concepts, many of which can be generalized and should be kept in mind when doing any web dev work.
I'll talk about the default session behavior, here: sessions are based on a cookie "PHPSESSID" which is set to an MD5 checksum (32 alphanumeric characters). PHP accepts this cookie from the browser, and uses it to load server-side session data. The client has no direct way to modify data in the session, but does get to specify their own session ID.
You can add additional layers of security (SSL, checking the client IP, etc.), but by default if I know your cookie I can effectively login as you. As far as how "easy" that is, well, that depends on lots of other layers of security: is someone sniffing your traffic, do you have malware installed, etc.
Tools like Suhosin attempt to improve session security.

Is it possible to pass a variable to php without the users 'seeing it'?

I have a link on a page, and I would like to send a variable to a php file like this:
href = "php_file.php?qry=$query"
the $query variable contains a query which I would like to make to mysql, inside the php file.
My problem is, I don't want the users to 'see' what I am passing along. I would like to use $_POST but from what I know, that isn't possible.
Is there any other simple way?
Thanks
That is not possible. Even if you used POST it would be very insecure.
My suggestion would be to put the query in the $_SESSION variable and reference it back in php_file.php If you have multiple queries you could give them some kind of IDs and store the id=>query pair in session.
Quick example:
<?php
session_start();
$_SESSION["query1"] = "SOME QUERY";
$_SESSION["query2"] = "SOME OTHER QUERY";
?>
<a href='php_file.php?q=query1'>Execute first query</a>
<a href='php_file.php?q=query2'>Execute second query</a>
//in php_file.php
session_start();
$query = $_SESSION[$_GET["q"]];
Obviously this is very simplistic and you might want to add some more "security" to it (check for empty parameters etc.) but at least your query wouldn't be visible to the user.
Yes, as stated use a session: http://www.php.net/manual/en/book.session.php
Also, don't stick URI params into a SQL query: http://php.net/manual/en/security.database.sql-injection.php
You could use sessions, or a cookie. But if you're trying to have the client send you information that the client cannot know about, I think you need to rethink the problem.
I hope $query isn't SQL!
Aside from encryption (and even then) if there's data on the client side, there's no way to prevent the client from being able to determine it's value.
Definitely do not put queries on the client side! Store whatever it is in the $_SESSION. That way the actual data is on the server side. It's never sent to the client, so they will never see it.
You obviously want to prevent users from loading stuff like php_file.php?qry=DELETE+FROM+users in their browsers by hiding or obfuscating the SQL code. I suggest you reconsider the whole idea: you're asking to be hacked.
You can hardcode a list of operations in your server side code and just pass an identifier, e.g.:
php_file.php?qry=fetch-totals
and then
<?php
if( $_GET['qry']=='fetch-totals' ){
// ....
}
?>
Well if you don't want them to actually see the query parameters in a link try any URL shortening service (google will help). And when the user is redirected to you save this parameter to session and then do the redirect once again but without any query parameters. This solution will only work in case, once again, the link is just ugly and you don't want to leave it like that. As mynameiscoffey said savvy will still be able to figure it out.
As well as cookies, hidden forms, JavaScript and so on BTW.
You can, in theory, use encryption, and decrypt the value on the server. The overhead is huge, however. And a sophisticated enough user will get to it anyway. The plaintext of the value to be hidden will exist in a variable at some point; a debugger and a breakpoint at just the right time is all they need.
In this scheme, it does not matter how complex the encryption is. You don't have to go all the way with RSA or somesuch; something like XOR with key will suffice. You're protecting against casual snooping here, not against a determined attack.

Categories