1. Lack of experience. Most web devs that's I've met have never even heard of using expiring session tokens in a cookie. (imho) It's been my experience that most javascript guys can be relatively young as it's the new teaching language (sorry python). They spend most of their time learning react/redux/moxd/angularjs2/vue and just haven't been exposed to security practices like expiring session tokens in cookie. It's not their fault, it's just that we don't know, what we don't know. Not realizing that this practice has been around for almost 20 years, the developer invented a new way of logging in using cookies.
2. Most people don't take security seriously. I recently had a conversation with a dev that was being a cool kid by using JWT bearer tokens. He was putting admin=true inside the bearer token and signing it. I asked him what would happen if I stolen his token. Would I become the admin? The answer appeared to be yes, the software would read the bearer token, inject admin=true into your session, and give you admin rights on the webserver. However, he explained the expiration of the JWT token was 1 hour. So I steal and use your token I only have 1 hour to become admin on your site?, I asked. Apparently he felt that was good enough.
3. Security is expected to be provided by the framework. XSS, CSRF, SQL injection - don't worry we're using Django. That seems to be the expectation of most people. You don't need to know about security, because the framework handles that. The problem is that this only gets you so far, there are things that live outside of the scope of the framework that you probably should know about, but don't. (I guess storing the user's password in a cookie would be one of those)
A JWT is just a base64 encoded JSON object that has a signature. You can pass one to any base64decode() function to see the actual data, so the important part is checking the signature to see whether it's been tampered with.
But the whole "admin=true" part, while it doesn't sound like best practice, isn't inherently less secure than using the JWT notation for scopes. "admin=true" might as well be "scope=admin" so the person criticizing the "cool kid" doesn't seem to understand JWT usage themselves.
What's important is where you sign and verify a JWT: Signing means using a secret key, which means actually having a secret key stored, which means that it has to happen server-side.
Proper JWT usage means that both the data creation/signing and data reading/verifying are always happening on the server, and you've got to trust the security of your servers, since they have the ability to read your shared secret key.
So to be secure, you shouldn't really send the JWT to an insecure client like a web browser at all. Since anyone can read a JWT, you're unnecessarily leaking information about the inner workings of the app, just giving hackers important info like the variable names you're checking for.
Instead, the best move is to use key/value storage for hashing your JWT into garbage and sending that over to the browser. When the user performs an action, they'll send the nonsense key and the server will retrieve the actual JWT and verify/perform the actual request handling.
Of course, this just takes the conversation back to session handling. There are various ways to mitigate the risk of someone stealing another user's session data and using it to impersonate the user, but those aren't unique to JWT.
Anyway, the comment above doesn't give enough detail about what the "cool kid" was doing in order to determine whether it was bad security or not. Sounds like either a lazy description of the actual scenario, or a poor understanding of JWTs.
A jwt that is only valid for a certain time is no less secure than a session id, as long as you verify the signature correctly.
The dude just didn't think about that or looked into how JWTs work. Which I believe is even worse :<
Whereas the parent poster said "what would happen if I stolen his token" (for example, via XSS). So in that case, it's a legit token in the hands of a bad actor, and the signature would be still be valid as far as the backend could tell.
In #1 you mention "security practices like expiring session tokens in cookie" and then go on in #2 to say that the exact same thing isn't good enough. You do know that the T in JWT stands for "token", right?
Are you sending raw JWTs straight to the browser? Why? That's the big problem, not setting "admin=true" inside of a JWT. The data in a JWT is a claim that's meant to be verified by signing. It's no more and no less.
If you want to describe the OAuth implementation or something more substantial than a "cool kid" then it might be more illuminating, but you don't give any context.
I really don't understand how these people make it through the magic 'must have 5 years experience' marker and just don't know proper security practices. It seems like people just lie on that.
And it's well within the scope of Django.
The blame is almost completely in #1 and #2.
1 - And, yes, protection against XSS, CSRF, and SQL injection are other great examples.
Yes. From Learning PHP, MySQL, Javascript, CSS & HTML5, Third Edition, from O'Reilly publishing:
So, to create a cookie with the name username and the value Hannah that is accessible across the entire web server on the current domain, and will be removed from the browser’s cache in seven days, use the following:
setcookie('username', 'Hannah', time() + 60 * 60 * 24 * , '/');
And that was published in 2014, not 2004.I dunno everyone has to learn how to use cookies if they are building web apps.
Password is obviously just bad.
I've been building webapps since forever and I've never cookies directly in Javascript like that and I can't, personally, think of a use case where I would do that.
I've only used cookies that store a session id and I store everything in the session. The session id cookies are handled entirely by the servlet container.
I don't believe I'm doing it horribly wrong.
This is why we have CSRF tokens, right? Orthogonal to session cookies, but when used together they avoid this vuln.
In the end, though, it is probably best to err on the safe side and only expose a salted and hashed session ID via cookies, and then doing a server side lookup to get the necessary data (which you would need to do regardless)
Here is a 2-page, 7.4K security checklist. If you verify and check each box, your application won't be bulletproof (it is software and you have 3rd party libraries), but it will be close to air tight. --Disclaimer: I have nothing to do with this security checklist or its authors, except appreciation and respect.
Security Guide For Developers - Latest: https://github.com/FallibleInc/security-guide-for-developers...
--Donald
Consider it a teaching moment and show folks how simple it is to store all your session-like stuff in cookies, along with a timeout and a version hashed with the server's secret.
Because it never would have occurred to me to do so. Or rather, had it occurred, it would have immediately begged the question of "what happens when the user monkeys with their cookie". Surely everybody else thinks the same way.
If so, how do we end up with this? Are there really "Teach yourself in 21 Days" books that have examples with this pattern that people are following?
Or does everybody just assume that they're going to be Facebook with 4000 servers and no way to quickly generate or store or manage or look up those keys for millions of simultaneous users, and that it's worth the tradeoff?