Security vulnerability from saving user info in PHP sessions? - php

I am creating a RESTful API-centric web application. Once a user logs in they will receive a session id and login key that will be used for accessing their data until their session expires. The web application (and possibly the mobile applications) will call an API every page load to get user information if a session is saved in the memory. I am working on optimizing this API call as much as I can, and I wonder if it makes sense to cache this information.
Every table with user data contains a updated timestamp (triggered on every Postgres update). So I could modify the API to accept an optional cache_timestamp parameter. The API would first check to see if any of the user data's tables have been modified since that timestamp. If they have, then it would return the updated user data; if not, it would return a 304 not modified and the application would use the cache.
My question is what information is too sensitive to save in memory (using PHP sessions). Currently the information contains things like profile (name, company, etc), contact (email, phone), settings (newsletter, notifications), and payment info (plan, trial, and an customer ID that refers to Stripe).
The only thing that I think would be on the edge is payment info, but they shouldn't be able to access any data from Stripe unless my API keys are compromised.

I'm not a Security expert, but since the sessions are stored on the server, the only way for an attacker to access the data is to have gained some privileges already.
You can look at this interesting post PHP Session Fixation / Hijacking about how to secure more your sessions.
If the user's session got hijacked, then there is nothing to do, the attacker will access the data like if it was the user in question.
If the attacker can exploit a fail related to your server, then he should probably be able to read the session data (which is stored serialized in some files by default).
So, crypting the sensitive data, can prevent him from reading it raw.

My opinion is also same, Payment info should be store in the Session variable, but then you are saying it's not accessible without API key. I think you are at safe side.

Related

How to save and manage the Session ID and a User ID in PHP and MySql

I need clarification on the doubts I have about PHP sessions.
I'm creating an Android app, in some activities I need to make queries to extract user data.
At the moment to do so, I send the user id to the PHP file via the hidden EditText from the Android app.
In the Android app the user id is not saved in shared preferences, but I get it through a request to Facebook Account Kit (for authentication use Facebook Account kit).
So when I need the user id, I request it from Facebook Account Kit, I get it and through a hidden field I send it to the PHP file, which I will use later in the WHERE clause of the Query.
Now, however, for security reasons, I would prefer to use the sessions to save the user id and then keep the user id in the session.
A friend of mine told me that if a hacker gets the id of the session, in which the user id is saved, it can happen that it has expired and that he can't get anything.
The problem is that I don't understand how to save the session ID and the userID and how to manage them at the database table architecture level.
I have to save the session ID in the database, I create a table called "Sessions" with 3 fields:
Session_ID,
ID_User,
Data_access.
To insert the user ID on the database I should always pass it from the app to the PHP file, and so if a hacker could discover the user id, I think he could very well get information about sessions with a WHERE clause ID_user = ID_user.
Quite right?
If I'm right, then what's safer than what I do?
Then if the ID of the Session changes with each access, to change it in the Sessions table in the MySql database I should switch from the Android app to PHP again the user id and through a query Update I should change the session id and date of access with ID_User = ID_User in the WHERE clause.
Exact?
If anyone has any advice for me or a criticism of how I handled the situation and has a better solution than mine, I listen to it willingly.
If I didn't understand anything about how the sessions work, then excuse me in advance for the time I stole from you.
Thanks anyway.
PHP sessions are based on Cookies. When a user opens a webpage, PHP set a cookie in response. Browser automatically ensures that in subsequent request, that cookie is also sent in requests, hence $_SESSION variables works. In my opinion, they don't provide much of the security. Instead of User Id, now a malicious user has to get his hands on the Cookies. Always use HTTPS for securing the Requests.
With Android app, you'll be making a custom request, so you'll have to explicitely set the cookie, once received from the very first call (You'll have to persist it on the client-side; Not a good approach).
The usual way of working of session is as following -
When $_SESSION is used to set a value for the very first time, PHP sets a Session cookie, which essentially is a random String.
Behind the scene (in Backend), PHP is maintaining an Object (key-value pair) against this string value. (SessionKey1 = { key: value, key2: value2 }; this could be on Disk File system or on a Cache layer (e.g Redis), depending on your server configuration)
When you set/updated/delete a key in session, SessionKey1 is modified.
Now you can create a similar behaviour for yourself. When userId is found on Android App side, send it to backend, create a row in session table (Session Id as a Random String and UserId as UserId). With each request send this SessionId alongwith the request (in the body or headers), on the backend check if sessionId received exit in Sessions table. If yes, get user Id and process.
Here is an alternative approach (probably a-bit more secure)
When Access Token is found after Account Kit verification
send it backend
validate the Token from Facebook APIs (Link)
Validation API also return user info, map it to your User's Data (from
your DB Structure).
(This will ensure that Token is always Valid, user won't be able to put a random token in order to attack as that will fail the verification from Facebook APIs).
Generate a UUID, create a row with
UUID as sessionId,
Your userId
Access Data
Created At (when row is created)
Expiry (Current Time + X days)
send this UUID in response.
Now on Android side, save this UUID somewhere. Create a request Intercepter, for all the request set this UUID in a custom header (e.g X-<application_name>-Auth). On backend side for each request, access this Header, check if it's expired, get the User Id from your session table, and proceed.
I think he could very well get information about sessions with a WHERE clause ID_user = ID_user.
Quite right?
You are absolutely right. But, securing the DB layer should be a separate task from the Application development. How do you think a Hacker would be able to execute queries in the first place? If one finds a way to run raw queries on DB, he can do a lot more damage than just extracting the data.
If I'm right, then what's safer than what I do?
There is not right answer, you just have to do your best to secure the application. Ensure that your application is following best security practices. For example - Use HTTPS, preventing SQL Injection.s (Search for OWASP Vulnerabilities)

How can I create a PHP session from one remote server to another?

I have ServiceSite.com (SS) and multiple GameSite.com's. All games authenticate through SS and then log in with their own personal databases. That's all done with a simple JSON API, no need to log into SS to get into a game.
I have the one goal of logging into a game and accessing the features of SS through the game, such as accessing a player's Contact List and Profile, both of which are shared between all games. While in GameSite.com/play, they'll hit a link to ServiceSite.com/contacts and get the response as if they were opening it from ServiceSite.com. I use JSON Web Tokens to manually log the user into SS, to simulate a real login to ServiceSite.com.
This works... so long as they're on the same domain. Meaning, as I'm developing a game, I'll use ServiceSite.com/tempgameurl and any call to ServiceSite.com has no problem establishing and keeping a session. But once the game gets its own domain, or if I'm working on my localhost, I cannot get it to recognize the session on subsequent requests. If I want a response, I will always have to pass the JWT token, which is not suitable for what I'm doing. The goal is to load a game, "poke" SS to create a log in, and then if a player were to visit ServiceSite.com, they would have the session as if they'd logged into ServiceSite.com's front page with their login manually.
In short, I expect that once I hit my first JWT request and make a session on ServiceSite.com from a GameSite.com, that's it, the session is made. But it seems to only actually make a session if I'm requesting from the same domain. I do see it create a session properly, filling in $_SESSION, but that data simply does not persist if the request originates from a non-ServiceSite.com URL.
Sessions and Cookies are domain dependent, it is a browser security issue. You cannot cheat this. However, there is a "trick" you can try, even though it is a bit more complex:
You need to set a cookie for each domain:
authenticate the user, emit a JWT code and create a key=>value type of record in a shared storage (database most likely). The key should be unique, the value should be JWT code and also set an expire time of 20-30 seconds.
in the response HTML you need to make the browser set cookies for the other domains. That can only be done on those domains. So you need to fool it with something like:
<img src="http://anotherDomain/setCookie.php?key=keyFromSharedStorage" style="display:none;" />
in the setCookie.php, check the shared storage and retrieve the JWT based on the $_GET['key']. Then set a cookie with that JWT.
You could pass the JWT directly, but passing a key that expires fast should be more secure. Add an image for every domain.
Instead of a cookie you can create a session on each domain. Same principle really.
Well try saving your needed data and sessions in database itself. It seems to be small amounts of data and logs.
After a game save the sessions on the database and open from whichever place you are at.

How to handle sessions across different devices?

I'm in the initial stage of building a php/mysql backend that exposes a REST interface to a website and iphone/android/etc devices.
I'm not quite sure what is the 'standard' or 'best practices' for dealing with sessions for multiple devices that use the same account.
Here is my current thoughts on how this would work:
I would use MySQL to store sessions for now, with a sessions table like so:
id, session_id (hash), user_id (int), created (timestamp), expire (timestamp), device (enum)
When a user login via iOS app or android app, I would return a session token in the success json for future api calls to use. Same with the website making an api call.
For security purposes, I should regenerate and overwrite the session token if the user re-login, but only for the session_id for that device.
I also have an expire column that tells me the expiration of the session so that if I wish, I can create a session that can expire in two weeks and is periodically cleaned by a CRON job.
This seem like a reasonable approach to me, but there are problems if the user uses an iphone and an ipad, or multiple android devices using the same account. Anytime the user logins with one would cause the other to log out.
I noticed instagram didn't invalidate the session even if I login from another iphone.
However, I don't think I can duplicate that behavior unless I never overwrite a session token when a user re-login or keep adding session rows into my session table whenever the user logins from the iphone?
What is the standard way of handling sessions across different devices?
I would highly discourage you from using mysql to store sessions. I would suggest using redis or memcache. Redis will store the data to disk in case your server crashes. Redis also allows you to set a TTL to expire the session, which would solve #4.
If you are using rest based calls, I would suggest just adding the session to the header as a cookie and pass that back and forth. Basically emulating the way a browser would access that page. I think that would make testing easier too.
Well it seems what you are looking for is not what most would traditionally call "sessions", which is something typically limited to a single browser or client instance.
It seems you are talking more about attaching application state to the user login. In which case, I don't see why you would have a need for a separate session table/token system. You would simply use your typical client-side methods of persisting a login, and then when that logged in client contacts your API, you would return application "session" state information, regardless of what actual client instance you are talking to.
This is not to say you wouldn't want to use some sort of token exchange system to give users "fresh" tokens in a case that you wanted to purge their state after a certain period of inactivity, just that you could have multiple active tokens per login.

Storing session for use in members area

I have created a registration/login system for my members area. Once the user has logged in I want to store a session variable that I can use to retrieve data associated to the user from the database.
Should I in encrypt the variable in any way? The data I want as a variable will either be the username or the id, which is best?
Should session ids be regenerated in anyway and when??
Data storage in session is considered to be "safe", so you dont need encrypt-decrypt it.
You should regenerate your session id after a successful login/logout. For security reasons, I would reccomend to ask the user for his password if he want's to perform a critical action (changing important data, deleting account or submit an order for example).
As AurimasL stated, you don't have to worry about session data on the server side. I reccomend this reading, if you are on a shared host, because then there are some security aspects: http://phpsec.org/projects/guide/5.html
Session IDs are stored like a cookie on the client's machine, and are passed back to the server for every single request. This is how PHP determines what information to load into a session once it receives the request.
Since sessions live on the server and not on the client, you only need to worry about session hijacking in regards to whether the information stored in them is secure or not. The answer to your question is no, I would not try to encrypt the information that is stored in session.
Just an add in the comments bellow,
Keep in mind that creating a sessions are expensive for your server app. Sometimes is a good idea stores the id in the session and other informations in cookies (informations that dont need security as the username).

Sessions or cookies?

I'm making a forum for learning mostly but hopefully it will have a couple of users some day.
What im wondering is should you use sessions or cookies for user authentication?
A cookie is a short piece of arbitrary data that the server sends through a header; the client stores it locally and sends it back on the next request. This mechanism can be used to maintain state from one request to the next even though HTTP itself is a stateless protocol. Cookies have two disadvantages: They offer only very limited amount of space (4 kB), and because they are sent back and forth in plain, a malicious client can fiddle with the contents before sending it back to the server, effectively making cookie data untrusted.
A session is a file on the server, identified by a unique ID which is sent back and forth between client and server so that the server can identify the client. The most popular way of sending the session ID is through the cookie mechanism, but it is also possible to pass the session ID through the URL (this is why you often see links that contain the URL parameter 'phpsessid'). This solves the two problems with cookies mentioned above: A file on the server can be as large as required, and the client cannot access the data other than through your own scripts.
Authentication is typically solved using cookie-based sessions; once authenticated, a new session is created, and the user ID is stored in it, and when logging out, the session is cleared and a new session ID is generated. Alternatively, you could store username and password in the session, and check them on every request.
Use a session.
A session is identified by a cookie, true, but not the same as storing user auth info in the client cookie, which is bad for security. A session cookie stores a guid or a hash in the cookie, then identifies the session (either database or file system based, depending on your server's php settings) based on that.
I recommend you store the primary key from your user table, not any other info, then look up the user info every time - this allows you to change their validation status, or security level on the fly while they are logged in; otherwise they will have to log out and back in before your administrative changes take effect for them - IE. you can't boot them.
Also, don't store the username/password, because that requires a less efficient query than by the indexed primary key (even if they are indexed as well).
They are essentially the same, working hand-in-hand. When you create a session..say through PHP, a cookie is created to store the session id too. On the other hand, you would create another cookie if you want to implement a "Remember Me" option to prevent your users from logging in every time.
I'm not a PHP expert, but Session and Cookie are related. In other programming languages you have the option of creating "Cookie based session" or "Cookie-less session". I'm not sure about PHP though so maybe you are referring to different concepts.
I feel using session is much more safe and easy then using cookies. The reasons are as follows:
1) In cookie we can only store a single piece of information, whereas in a session we can store as many information as we want.
2) Being stored on hard disk of user, cookies can be played with. Being a person interested in hacking, I have done that and gathered useful information about the user. Sessions cannot be used for such a thing.
If its a small amount of data (just one variable), I would use a cookie. Here is the code...
setcookie("cookie name", "cookie value or variable name", time+ 3600, "\");
this code sets a cookie that is readable for any of your webpages. It also will delete its self in one hour.
You can also see if the cookie exists like this (to see if it has deleted its self).
if (isset($_COOKIE['cookiename']))
{
}
to collect a value from a cookie...
$value = $_COOKIE['cookiename']; //makes a variable for this cookie for your program

Categories