I noticed that cherrypy session does not require a secret key configuration. On the contrary, Pylons session does: http://docs.pylonsproject.org/projects/pylons_framework/dev/sessions.html
I'm concerned about security issues if I'm using session to remember user authentication.
Any one can explain why cherrypy session does not need a secret key? Or is there any suggestion how should I make it secure to use session to remember user login?
There are basically two different ways of maintaining session state: on the server or on the client.
With the server-side approach, you keep the session data in files, a database, or in memory on the server and assign an id to it. This session id is then sent to the client and usually stored in a cookie (although they can also be embedded in URLs). Then with each request, the client's session id is read and used by the web application to load the session data from wherever it's stored on the server. This way, the client never has access to any of the session data and can't tamper with it, but the downside is that you have to protect against session hijacking through the use of stale session ids by malicious clients. This is the model used by most web frameworks and applications today.
Another approach is to store the session data completely on the client side inside of cookies. The downside to this approach is that the data can be seen and tampered with by the client, so you have to take care to properly sign and encrypt the data to prevent tampering. This is where having a good secret key comes into play. The upside is that you also don't have to worry about session hijacking.
Pylons uses Beaker sessions, which can be configured to store session data completely on the client side. That's why you need a secret key.
CherryPy only stores session data on the server and then sends the user a cookie with the session id, so the client never sees the session data and can't tamper with it. You can configure it to use files or just keep everything in memory. You can even hook into it and use a database to store the session data in.
Personally, I prefer the approach used by CherryPy, since it's the same approach used by the majority of the web. It's easier to secure, and you can easily share session data with other applications running on your server without worrying about encryption or keys.
Related
Where does Pyramid store the auth_tkt at rest? I'm trying to quantify how many open sessions my site currently has and I'm hoping I'm just blanking on what table it's being stored at.
auth_tkt is the default name of the cookie which is a parameter for Pyramid's AuthTktAuthenticationPolicy, which is stored in the visitor's web browser.
Pyramid has no database, but your app might have one. If so, then you'll need to trace through your application's code to find where you maintain server side sessions.
To extend on Steve's answer: auth_tkt is an authentication method which does not require a server-side session storage. It works by generating a cookie based on username and a server-side secret, so the cookie basically looks like this:
senatork:kuh87h887KHJKJH908uo
The client then sends the cookie and the server is able to validate the "claim" contained in the "ticket" by generating a new signature using the server-side secret and comparing it to the one contained in the cookie. Here's some more details in the documentation of the original Apache mod_auth_tkt (which Pyramid does not use, but it uses the same logic).
If you need a session storage for your app you'll need to implement it separately from auth_tkt authentication.
I develop and maintain a python pyramid web page. It is deployed live on a separate machine that I have administrative access to (call this Server). I also host it on my own laptop (call this Test).
Login accounts are hashed with bcrypt, such that I cannot read user passwords from the live instance. I can, however, replicate the SQL (I use sqlite) from the live instance to my own Test machine, and do so regularly for testing. I would then replace all hashed passwords with my own password for ease of testing.
Recently I realized that if I'm logged in as user X on my Test instance and then open my Server instance in another tab of the same browser, the Server instance acts as if I'm logged in as user X there.
Is this a security flaw in my web page design? Could it be used to gain access to accounts on the system without knowing their password? This php question says this is linked to the session name I've used for my cookie (and I guess to the secret as well). What are the best security practices for this situation?
If you are using the same database on each case (determining what goes into the cookie), and you hash the cookies with the same secret (determining what the outcome of hashing a given payload looks like), then your cookies are interchangeable. This can actually be useful sometimes for multiprocess testing. It's not a security flaw per se, it's by design, but you need to have a separate cookie hashing secret for every deployed instance if you want their cookies not to be usable by each other.
Check if you using the same session secret for development and production environments
I'm using the Python WSGI framework Falcon to make an app backend, and using Beaker to handle session management. In production, we're going to using Gunicorn in AWS.
There's something I've been unable to understand:
Gunicorn will run several workers, so does that mean the environment variables persist for different clients that have made requests? To put it another way, is a beaker session for one client only, or will it be available to several clients making requests in the same Gunicorn worker instance?
This is how I understand sessions to work from my reading:
A person logs into my app, and the user_id is added to the session with Beaker. Future requests from the same client will have this user_id stored in the session dict. Now, any future requests from that client will be able to access the variables stored in the session. Each client has its own session data.
Have I understood this properly?
The current method is to return an id to the client (on successful login) to pass to the backend when more user information is required.
Have I understood this properly?
yes, you do, for most part.
Gunicorn will run several workers, so does that mean the environment
variables persist for different clients that have made requests?
To put it another way, is a beaker session for one client only, or
will it be available to several clients making requests in the same
Gunicorn worker instance?
beaker save session data on server side, in a dedicated datastore identified by a unique session id, client side would send back session id via cookie, then server (gunicorn worker) could retrieve session data.
I recommend read a more detailed explanation on how session works, like this one: http://machinesaredigging.com/2013/10/29/how-does-a-web-session-work/
So, in order to avoid the "no one best answer" problem, I'm going to ask, not for the best way, but the standard or most common way to handle sessions when using the Tornado framework. That is, if we're not using 3rd party authentication (OAuth, etc.), but rather we have want to have our own Users table with secure cookies in the browser but most of the session info stored on the server, what is the most common way of doing this? I have seen some people using Redis, some people using their normal database (MySQL or Postgres or whatever), some people using memcached.
The application I'm working on won't have millions of users at a time, or probably even thousands. It will need to eventually get some moderately complex authorization scheme, though. What I'm looking for is to make sure we don't do something "weird" that goes down a different path than the general Tornado community, since authentication and authorization, while it is something we need, isn't something that is at the core of our product and so isn't where we should be differentiating ourselves. So, we're looking for what most people (who use Tornado) are doing in this respect, hence I think it's a question with (in theory) an objectively true answer.
The ideal answer would point to example code, of course.
Here's how it seems other micro frameworks handle sessions (CherryPy, Flask for example):
Create a table holding session_id and whatever other fields you'll want to track on a per session basis. Some frameworks will allow you to just store this info in a file on a per user basis, or will just store things directly in memory. If your application is small enough, you may consider those options as well, but a database should be simpler to implement on your own.
When a request is received (RequestHandler initialize() function I think?) and there is no session_id cookie, set a secure session-id using a random generator. I don't have much experience with Tornado, but it looks like setting a secure cookie should be useful for this. Store that session_id and associated info in your session table. Note that EVERY user will have a session, even those not logged in. When a user logs in, you'll want to attach their status as logged in (and their username/user_id, etc) to their session.
In your RequestHandler initialize function, if there is a session_id cookie, read in what ever session info you need from the DB and perhaps create your own Session object to populate and store as a member variable of that request handler.
Keep in mind sessions should expire after a certain amount of inactivity, so you'll want to check for that as well. If you want a "remember me" type log in situation, you'll have to use a secure cookie to signal that (read up on this at OWASP to make sure it's as secure as possible, thought again it looks like Tornado's secure_cookie might help with that), and upon receiving a timed out session you can re-authenticate a new user by creating a new session and transferring whatever associated info into it from the old one.
Tornado designed to be stateless and don't have session support out of the box.
Use secure cookies to store sensitive information like user_id.
Use standard cookies to store not critical information.
For storing large objects - use standard scheme - MySQL + memcache.
The key issue with sessions is not where to store them, is to how to expire them intelligently. Regardless of where sessions are stored, as long as the number of stored sessions is reasonable (i.e. only active sessions plus some surplus are stored), all this data is going to fit in RAM and be served fast. If there is a lot of old junk you may expect unpredictable delays (the need to hit the disk to load the session).
There isn't anything built directly into Tornado for this purpose. As others have commented already, Tornado is designed to be a very fast async framework. It is lean by design. However, it is possible to hook in your own session management capability. You need to add a preamble section to each handler that would create or grab a session container. You will need to store the session ID in a cookie. If you are not strictly HTTPS then you will want to use a secure cookie. The session persistence can be any technology of your choosing such as Redis, Postgres, MySQL, a file store, etc...
There is a Github project that provides session management for Tornado. Even if you decide not to use it, it can provide insight into how to structure your own session management. The Github project is called dustdevil. Full disclosure - we created this several years ago but find it very easy to use and have it in active use today.
What exactly is the 'secret' parameter of Pyramid's pyramid.authentication.AuthTktAuthenticationPolicy function? The documentation says that it's "(a string) used for auth_tkt cookie signing. Required." The tutorial says that it's "is a string representing an encryption key used by the 'authentication ticket' machinery represented by this policy".
What is auth_tkt cookie signing? What is this 'authentication ticket' machinery? Is this secret supposed to be something I store as a hash in a database or something? I'm really confused.
A tkt auth cookie is a secure hash of several pieces of information, including the username and optionally a timestamp, but not the user password. Once authenticated, you give such a cookie to the user, and every time the user returns you just extract the username again and know it's the same user.
To keep this cookie secure, you need to have a server-side secret, however. Only a server in possession of that secret can create these cookies; if an attacker ever got hold of it he could generate authentication cookies for arbitrary users without ever needing to know the passwords of these users.
The secret parameter for the policy is that server-side secret; it's like a master password for your server. If you run more than one process for your site (and with WSGI, you usually do), you need to make it consistent across your processes, to make sure each process can verify the cookies. You can specify it in your configuration file, in your source code, or in your database; it depends on how much flexibility you need, your security policies, and whether or not you need to share the secret with other systems.
You can share the secret with other systems in your domain that also need to authenticate your users, using the same standard. Apache has a mod_auth_tkt module for example, Plone uses the same standard, and by sharing the secret you can provide a single sign-on for your users across disparate web applications.
Note that changing the secret means existing sessions become invalid, and users would have to re-authenticate.
In any case, existing cookies can have a limited life-span; the embedded timestamp limits how long it will be accepted as valid, if you configure the timeout parameter on the policy. It's good policy to set a timeout, combined with a reissue time; any user that re-visits your application within the timeout will be re-issued a new cookie with a new timestamp to keep their session fresh. That way your session cookies automatically expire if your users do not return, and their cookie cannot be reused by an attacker at a later time. The reissue parameter lets you control how quickly a new token is issued; revisit your server within reissue seconds would not produce a new token.
The secret parameter as far as I remember is just a string used as a salt for the creation of the cookie. You can put whatever you want. Having it in your config file should be more than enough. Saving it in the database might be overkill though if you want to invalidate anything created, I guess changing the secret will invalidate all cookies and session create before that change.