I am writing a PHP script that needs to integrate with an ASP.NET login (which happens to be built on Sitecore, not sure if that matters). I need to replicate the ability to generate/login/encrypt a session & data cookie, and also detect if the user is logged in by detecting/decrypting a session & data cookie. Both the PHP & ASP scripts can share the same MS SQL database and are on the same filesystem, so that's not an issue. Most of my issues are just with setting/reading the ASP cookies within PHP.
I have 2 cookies set by ASP.NET,
ASP.NET_SessionId and .ASPXAUTH
It is my belief that the ASP.NET_SessionId is for the session obviously and .ASPXAUTH is for the data.
My questions are:
It is my belief that in order to know if someone is logged in (or login someone in) via an ASP session, in PHP, I will need to compare the session data with the sessions stored on the filesystem, does anybody know where (or what determines where) these are located?
Does anybody know the algorithm used to encrypt/decrypt the ASPXAUTH cookie? I'm aware of the standard "Encrypt" and "Decrypt" methods, but I want to know the code that makes them run precisely. IE is it first some sort of data array that is then salted and hashed? Do the bytes of the output need to be shifted/converted? If so, in what order/way?
I appreciate any assistance, I will award an answer for the person that is the most helpful in answering either of these questions in the next few days.
Currently I have been able to reproduce cookie generation via setcookie() in PHP. That is, I can login via ASP.NET app, take the cookie data, plug it into the PHP app and logout via the ASP .NET app. For those who are going to troll me, I am well aware this is possible and I do not NEED to explain why I am doing this, but it involves a lot of time, money and reasons, so yes, I do need to use BOTH PHP & ASP.NET.
THANKS!
UPDATE
I believe I was partially able to decrypt the cookie using this answer: https://stackoverflow.com/a/988018/775586 Anybody know how to finish it off?
It is my belief that in order to know if someone is logged (or login
someone) in via an ASP session, in PHP, I will need to compare the
session data with the sessions stored on the filesystem, does anybody
know where (or what determines where) these are located?
Nowhere on the file system. By default ASP.NET stores session data in the memory of the application domain. So you can simply forget about accessing this part of the memory from PHP. There are other modes that you could choose which allow you to store the ASP.NET session data either out-of-proc (in a dedicated Windows Service) or in SqlServer. For more information about the different ASP.NET Session modes I invite you to read the following article.
Does anybody know the algorithm used to encrypt/decrypt the ASPXAUTH
cookie? IE is it first some sort of data array that is then salted and
hashed? If so, in what order/way?
It uses the FormsAuthentication.Encrypt and Decrypt methods. They in turn use whatever algorithm and keys you have defined in your machineKey section in your web/machine.config files. For more information about how Forms Authentcation works in ASP.NET I invite you to read the following article.
Okay so for the first question...
ASP doesn't store on the raw filesystem, but can store session data in a database if configured properly and you can specify where. From what I recall reading, this is in a database called "tempdb" or a database which may also have some sprocs in it. More info on that in more plain English here: http://www.codeproject.com/Articles/104082/Configuring-ASP-session-state-on-SQL-server
For the second and more important question:
This amazing article will give you a breakdown of how the ASPX_AUTH cookie is generated and the algorithm to do so: http://www.codeproject.com/Articles/16822/The-Anatomy-of-Forms-Authentication
Related
I would like to know if it is a good idea to sign cookies with hash to check it's integrity? First of all, I do realize that I should not store any sensitve data in cookies and use sessions instead. That's exactly what i do. But still I am feeling not comfortable with user being able to modify even not so important data. (I'm kind of security paranoic :) )
I came up with the following solution. Let's say we have cookies for:
PHPSESSID
site_lang
recently_viewed
Now whenever I update cookie value I recalculate hash for cookie with key of let's say cookie_hash and value of let's say md5(serialize($_COOKIE)+$secret)
the only thing that I am not using PHPSESSID for calculation and validating hash because it is not being managed by CookieManager class (my custom class) and might be refreshed with new session id and corrupt hash.
My concern is what if some third-party package sets it's own cookie bypassing my CookieManager of course. it will collapse hash. So is it a good idea at all?
MD5 is weak for this, and the scheme you proposed (hash(data||secret)) is flawed anyway. Cryptography is hard, please don't try to come up with your own. :)
What you may be looking for is invented already, it's called message authentication. Have a look at things like HMAC, which is one proper way to do something very similar.
In most cases, authenticating cookie values doesn't make sense in a web application and provides no additional security, but there are cases, when it does. Your examples above don't seem so. :) For example the session id is cryptographically random already, and the other two usually present no harm if changed by a user (but in very special cases, they probably may, though I can't come up with a reasonable example). If something matters and should not be changed by the client (user), that should probably be stored in a server-side session.
However, you may decide to store application state on the client in encrypted and/or authenticated cookies, one reason for that may be a stateless application on the server (see the default session management in Ruby on Rails for example), and in that case, something like your idea (but done correctly) is indeed the solution, but it has its own set of risks (as do server-side sessions).
Note that anytime you store state on the client, one threat that comes up besides secrecy and authenticity is replay. This affects your idea as well. Say it is a problem in your application if the user can change the last_viewed cookie, but you still don't want to put it in the session. You properly authenticate the cookie, maybe even encrypt it, the client has no access. But what if at some point, the user saves the cookie, and in a different session replays it? (Okay, your example tries to protect all cookies at once, which may make this a little bit more difficult, but you get the idea, replay is still a potential problem.)
So in short, you most probably don't need this, but if you do, then use proper message authentication (something like an authenticated encryption, or a proper MAC like HMAC).
I don't know how deep you digged in PHP and Webdevelopment, so please forgive me if the level of my answear is to low.
If you are paranoid you should read more about PHP, sessions, cookies, hashing algorithms and more.
For example:
PHP session handling
PHP session configuration
PHP session security
With this you can modify your sessions & your handling a little bit to serve your paranoia.
By the way you shouldn't use something like md5 in reference to make your web application more secure.
If i understand what you want to do, you want to write a hash of your serialized session array plus a secret/salt into the session to verify the integrity of the session and its data.
If this is your motivation, you really should rethink, at least in my opinion.
A session is just a file on your server (on the users system it's a database entry in a sqlite database of firefox or something else, but without the data you write to the cookie array, that data are just writen to the server) and the session ID is a file name/path to this data on the server, except your sessions are saved on a database.
So with your approach you would just save the value to verify the integrity of the data in the same data (on the server) you want to verify.
And where you want to save the secret?
I think it's a little bit useless.
Depending on your needs and the needs of your application you could search about the key word session TAN, you could set a additional cookie with a random value you save on the session to verify each other, you could save and check the IP (depending on the law of your country and the way your users connect), shorten the session lifetime and more.
You could also set ini directives like session.cookie_httponly (that's one i recommend if you don't want to access your session cookie by a script language like JavaScript) you can find on the links above and more.
Something is a matter of faith, something evident.
Digg in deeper and understand how the technology works under the hood and you can make your decision more easy by yourself.
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.
I want to pass the user id and username stored in the session variable in php with an ajax request.
I know that i can print the values to the html of the page as a hidden text box, or as a jQuery data value, but i feel that this is not secure and that the user can make changes to the value and the ajax call will send that value which would make it in-secure. Please let me know how professionals handle this problem...
Thanks in advance!
Professionals handle this problem by carefully screening all input, enforcing strong password standards (so that users can't guess other users' passwords), and by storing the credentials in the code on the page but rather by using a randomly generated session token to map the user's token to identity on the server.
Client's can easily send any data they want by circumventing all of your client code. You have to assume the client is evil and look at protecting your server from that perspective.
EDIT:
If you need some help with tokens and their usage, this question might help you: PHP cookies and member security
If you are new to security I would highly recommend the Web Application Hacker's Handbook. I have read it and it is very thorough and interesting to read.
There is also a new book out called the Web Application Defender's Cookbook that looks quite promising, though I haven't read it.
I'm looking to develop an application for healthcare purposes using PHP. I want to encrypt the data so that nobody but the actual users to the application have access to the data.. not even system administrators. Does anyone have thoughts on a process to do this?
I did some research, and this seems possible where one user needs to access his/her data. But, I want to place emphasis on the fact that multiple users will need to access a set of data. Not just one user.
I realize that this could be done with a third common password amongst users, which can act as a salt.. but that doesn't seem very practical :)
To encrypt data use openssl rsa inside a browser. There are some implementation in js available. As fare as I know, the module is not running in every browser.
Store private key inside a local db (html)
encrypt/decrypt data inside browser
build input form with js
save encrypted data then on the server
But in that case even the php appl. has not access to the data :(
I have website w1 written in rails using auhtlogic for authentication and w2 in PHP(say), I want w2 to access session information stored by w2 and login user into w2 and also retrieve user_id from session.
By default, Rack (which Rails uses to manage its sessions) stores session information in cookies by marshalling the session hash (see here), which results in a string that is specific to Ruby. It would be extremely difficult to use PHP to deserialize this information.
If you're dead set on doing this, you're going to have to handle the session serialization yourself. I think a full solution is outside the scope of a single question on SO, but a few pointers:
It would be wise to store only a session id in the cookie, and then keep the actual session data in a database that would be accessible from both the PHP and Rails apps. If you really want to keep the session information in a cookie (or in another place like memcached, where you'd also have to serialize it), look into serialization strategies that work across languages, like MessagePack.
You'll want to do something to ensure that the cookie is not tampered with by the user. Rack uses HMAC, which is a good solution. I've never used PHP, but I'm sure they also have a library for it.
You probably already know this, but just in case: This is all assuming that your two apps are sharing the same domain name. If they're not, then your users' browsers won't share the cookie between the two apps, and there's not really anything you can do. For example, you could share sessions between railsapp.yourdomain.com and phpapp.yourdomain.com, but not railsapp.com and phpapp.com.
Good luck!
i tried a solution sometime ago that was more a hack, but for my propose it worked.
after login, i used to write the user's cookie in a file in a public directory and when this user tried to access the other server where he had to access too, my application on this second server, just had to "know how to access" the remote file stored in the first server and load this content as cookie. I did used CURL at that time.
Note that it introduce some security breaches, and probably your security will rely on "obscurity" - for example, the algorithm to mount the file name where the cookie is stored and how to access it and any external webserver configuration.. Said that, i think we could think as well use a shared memcached to store the cookies..
Have you considered using Open ID?