Protect user's information in the referral URL - php

I decided to refresh my site today with a pair of upgrades. One of them is referring availability. So, as I method of referrer recognition, I am going to use special URL with referrer ID in it (if there is some other but better method, feel free to let me know about it). After I implemented the basics of that availability, I made a decision to make the system more secure. With that, I mean hiding the referrer's ID. Now, I am here, looking for suggestion on how can I make it secure (hidden or encrypted), but still be able to decrypt it on the server-side. Don't suggest me to use Base64 encryption, it's too simple and everyone can decrypt it these days.
I could try making my own system of encryption, what do you think?

It depends on what you want to pass.
First of all don't pass info that is not supposed to be publicly passed.
Second, you could create a token, save that in the DB next to the user, and authenticate on that token.
That token could be something that is valid only for a few hours... you make the choice, what works best for you.

Related

How to secure a php based webservice

I'm developing one android application and I'm creating a php based webservice to retrieve the information from the database.
The thing is that I really don't know how to secure this service.
For example, if my android application needs to retrieve some information from the server it will call http://mywebservice.com/service.php, and it will send several POST parameters as the user and password to login, or something like, for example, one user id to retrieve his data.
Of course, anybody with the knowledge enough will be able to retrieve that data too. And this is what I don't want to happen.
Anybody who know the parameters to send to my server will be able to retrieve information from it.
How can I secure this?
I've been reading about OAuth, OAuth2, two legged and three legged implementations of it, https..
But at the moment, I really don't know how to secure this.
I want that the webservice only answer to my application and not to anybody else.
PS: Even there is something like http://myservice.com/get_information.php that you send an id and you can retrieve a lot of information. Of course, I control that in my application, only logged and authorized people can do that calling, but it's a problem anyway. What's the best way to do this kind of things?
Some concepts to secure a webservice(might be forgetting some notions):
Protocols: HTTPS in the current case so data are not transfered in a clear format.
The Sessions: A session has a lifetime, a unique identifier(session token/id/whatever) and contains an error code. When a user will call your webservice, a session will be created and its token answered back. At every call of the webservice you'll test if the session is still alive. You can add complexity to the expected inputs, outputs and exchanges. The error_code will be used for logging(errors can come from an attack or a bug of your webservice).
Data Encryption: Use asymetric functions like password_hash() or crypt() for authentication issues. Use symetric algorithms like AES 128(10 rounds) or 256 (14 rounds) for sensitive data you'll need to retrieve.
Testing inputs: If you find yourself inserting given arguments in a query, try to prevent SQL injection. Some bad-minded people can also try to send arguments which would make your webservice fail.
Go for standards: As Çagatay said, try to implement for example oAuth2 because standard is most of the time much better than what we'll build :S
Hope it helps.
edit: The REST security sheet is good also.
Always use SSL to prevent some man-in-the-middle attack. Otherwise someone that sniffs the connection (in case of connecting via public wi-fi or company networks it's a huge risk) can see the username and password.
Do not send username and password on each request, instead implement oAuth2, your client in this case will have to send the username and password only once and then for the other requests you'll have to send only the auth key. Good documentation for implementing a oauth server: http://www.sitepoint.com/creating-a-php-oauth-server/
Look at this document: https://www.owasp.org/index.php/REST_Security_Cheat_Sheet
I ended using OAuth. More especifically this library https://bshaffer.github.io/oauth2-server-php-docs/
If you follow the instructions it's really easy to use and it works very well. I think it's a really good way to start working with OAuth.

Session integration, is this approach secure?

A user logs in using default Laravel authentication, which puts an encrypted cookie in the browser, and saves the session in the database.
The user moves to a classic asp page, where I check the cookie value, get the hash, and call the laravel app back passing the session id hash.
Then I use that in laravel to see if there's an active session for that id, and if so I return true, so the user can be logged in, in classic asp.
On each page request in the classic app, I check the last_updated_time in the db and update it on each page. All logging in and out is done in laravel, and classic relies on the database to see if a session is active.
I would also call a public url to get sessions variables and add session variables using laravel, since it's all encrypted and using classic asp for this would be hard.
The only risk I see is session highjacking, but I don't think it's a higher risk than usual.
Is it important to lockdown the laravel URL I call to check if it's a valid session?
Am I missing a security hole here?
Is this method secure?
From what you've stated you probably haven't opened up any security holes. The session cookie is not itself encrypted on the users machine, but you are making sure it is encrypted between their machines and yours, as well as between each of your machines. You should make sure you've set the Secure Flag to help prevent the cookie being accidentally sent over traditional unencrypted transport (HTTP), but as stated, this doesn't effect storing the cookie itself.
That being said, you are essentially hijacking your own users sessions. While a hole might not be introduced now, you are potentially weakening the overall system, which could lead to hole in the future.
Is there a better way to do it?
This might well be a dumb question, but are you sure you need the session? If you're juggling credentials between servers, it sounds more like you want to use Access Tokens and scrap the session.
Using Access Tokens is similar to using sessions, but you need to make your services stateless. This means your no longer storing information about the logged in user any specific machine so you'll need to pull anything you need from the database every time they hit a server requiring that information.
This is a good thing in the long run as it's much easier to scale your services when you don't need to worry so much about where the session is and what's inside it.
OAuth 2.0 is widely used standard (Facebook, Twitter, Google), and was specifically designed to be easy to use. The RFC is complex, but there's a log of good guides out there don't worry.
The one slight down side (if you can call it that) to OAuth 2, is that it MUST happen over an encrypted connection. If your use case can not guarantee encryption over SSL or (preferably) TLS, then you should use OAuth 1.0 (WITH revision A) instead.
This is due to the fact that OAuth 2.0 exposes it's "secret" token in requests, where as OAuth 1.0 only ever uses it to provide a signature hash. If you take this route it's advisable to use someone else's library as the hash is very, specific.
Further Improvement
(Note: This section added after the answer was accepted)
One system I've been exploring recently is Json Web Tokens. These store information about the user to save each machine repeatedly looking it up in a database. Because the token is hashed with a secret, you can be sure that, so long as your secret isn't exposed, a valid token represents a successfully logged in user, without having to touch the database.
You should avoid putting anything too personal in the tokens if possible. If you must store private or secret information in the token, you can encrypt it, or you can use a reverse caching proxy to exchange the JWT for a traditional security token. This may initially seem to defeat the purpose, but it means some of your services may not need database access at all.
I'm no security expert but I don't see an issue with this. The packaged Laravel database session handler works the same way. The cookie contains a hash that references a record in the database. The session data is base64 encoded but that's neither here nor there. I think you could actually avoid rolling your own and just use Laravel's DatabaseSessionHandler.
Illuminate/Session/DatabaseSessionHandler
... I just read a little deeper into your question and noticed the part about the public URL to set and retrieve session data. I think this is a really bad idea. Mostly because it will provide an open door to the end user allowing them to read and write session data. This can only end badly.
Like I said above, the data is only base64 encoded so I believe you'll be able to parse, read and write that to your hearts content within asp.
Edit
Ok... I think this is the last edit. The data is php serialized and then base64 encoded. This question looks like it may help you to that end. If it doesn't and an API endpoint is the only way, find some way to block the end user from accessing it.
Aside from session-hijacking, no. This is the standard way applications interact on a internal basis. Of course there might be a better way to get at the data if you choose a different type of session store other than your database, Memcached for instance.
There are couple of things that can be done.
Make the channel HTTPS. It will make almost impossible to sniff on your transport layer.
Rather than making interactions with your cookie, you could use a JWT to get this task done. Which will help you to use the existing functionality in your system while connecting with ASP system as well. You can write a small REST web service which allows ASP to connect. You could use this lib. You can refer this article which will give you an idea how it should be done.
Please let me know if you need more information.

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.

Logging in users with CodeIgniter

I have written the registration page in my CodeIgniter application. Everything works fine, and it's using the PHPass library for password hashing.
Now, I want to write the login part of the system, and was wondering how exactly I'd go about doing this with CodeIgniter. I'm mostly confused about the correct (and best practice) way of doing it. Do I just accept the users login credentials, determine if they're correct and if so, set up a session for that user? Do they need a cookie? Does that cookie need to be encrypted? Do I need to track the user in my database (CodeIgniter can do this for me) and watch for IP address changes or hostname changes?
There are many many auth libraries but since you are a beginner I strongly believe that it's better to make something on your own (unless you are on a very strict time frame). Because, as my colleague once told me, without making a mistake you won't understand why better solution is actually better.
Back to your actual question.
Do I just accept the users login credentials, determine if they're correct and if so, set up a session for that user?
Well, yes. There is no other reasonable way to do it, is there? :)
Do they need a cookie?
Session ID is stored automatically in a cookie. You can store other options in a cookie, but have in mind that cookies can be stolen (so it's NOT a good idea to save username/cookie). Plus people use more than one device (e.g. tablet and desktop) more and more so be sensible about using cookies.
Does that cookie need to be encrypted?
I believe I answered that already.
You should probably start here with this: http://codeigniter.com/wiki/Category:Libraries::Authentication and http://codeigniter.com/wiki/Category:Libraries::Authorization
From CI Wiki: Authentication is different from Authorization.
Authentication answers the question “is this user who they claim to
be?” Authorization answers the question “given this user, are they
authorized to perform this action?”
Why don't you use one of the many CI auth libraries?
How should I choose an authentication library for CodeIgniter?
You can just have a look at the CI wiki for all the particular details you are after:
http://codeigniter.com/wiki/auth

Without using SSL, what's the most secure way to make an AJAX request to a PHP page?

So, it's impossible to do AJAX requests securely without using SSL. I get it. You can either view-source the data that's being sent via Javascript, or you can directly access the PHP page by spoofing headers, yada yada.
But let's say this web app doesn't particularly require true security, and instead it's just a sort of game to keep most reverse-engineers at bay. What sort of hurdles should I employ?
I'm not looking for some ridiculously over-the-top Javascript implementation of an encryption algorithm. I want simplicity as well as mild security... if that isn't contradictory by nature. So, what would you guys recommend?
For example, I'm running a contest where if a user clicks an image successfully (jQuery), it passes their userid and a timestamp to a PHP page, both MD5 salted by random data and then encoded with MIME. The PHP page then validates this userid and timestamp, then returns a winning "code" in the form of another salted MD5 hash. I'm also employing multiple header checks to help ensure the request is from a valid location. Am I missing anything, or is that about all I can do? It seems like someone could just fire the jQuery click event and ruin the whole thing, but I don't see how I can prevent that.
I'll be awarding the answer to anyone who comes up with an ingenious faux-security mechanism! Or... just whomever tells me why I'm stupid this time.
I believe header checks can be easily fooled. Doesn't hurt though.
Since your algorithm is exposed on the client side, the user can simply send the appropriate data to your server with an automated script to fool your server into thinking it was clicked.
In addition to that, you have to watch out for session hijacking. A user can essentially submit this ajax request on behalf of someone else, especially if they have the algorithm. Does your application have different behavior for certain users? If so, then the session hijacking could turn into priviledge escalation issue.
It is not necessarily true that you need to encrypt the payload with SSL in your case in order to build a secure application. From what you've described, there is no sensitive data being sent over the wire.
Ensure that you have some basic silly checks on the server side to check for automated or malicious behavior. For example, if you find that the header information is missing, you may want to have some sort of flag/alert that someone is toying with the response. Another place you may want to do this is the pattern of requests.
A more secure model is to have the server assign the user some session token that they cannot reverse-engineer. This session token ideally should begin with the timestamp instead of the username to promote the avalanche effect of the salted hashing algorithm.
Since it seems like your application deals with prizes and potentially money, I would invest some more time in securing this app. Hope these tips have helped you.

Categories