5

RE: Duplicate - Did anyone actually read my question? The question marked as duplicate is in no way, shape, or form what I'm asking. I specifically state that a DB compromise must not allow an attacker access. Storing a session ID that can be used to gain access via MITM is worse than no security. It totally bypasses the need to hash passwords at all, correct?. Also, I specifically state that storing a secret API key requires too much security in storage to be valid.

Disclaimer: I searched ad nauseum on what I thought would be a very common question, and found no definitive answers. Also, IANBS

Some facts about my current project design for reference:

  • REST API on App Server(s)
  • Server application is Node.js + Express.js, running on AWS Elastic Beanstalk
    • App Servers are behind Nginx for reverse proxy and SSL offload. This is inherent to AWS SSL EB.
  • Database is MongoDB, replicated and sharded.
  • ORM is Mongoose
  • Client is native Android, Browser (Using backbone.js), and native iPhone (future)
  • ALL traffic is HTTPS protocol.
  • Application is HIPAA compliant. No other (known) regulatory compliance requirements.
  • TFA Via Authy
  • eCryptFS is in place on DB servers, providing file system that MongoDB data files are on.
  • SSH logins to all app/db servers are via SSL keys only.
  • All application data payload is JSON.

Goals of security requirements:

  • Compromise of user database, while bad, does not compromise user passwords or allow attackers to achieve unauthorized client authentication just by having user database (via bcrypt hashed storage of passwords + TFA)
  • REST API remains truly stateless - App servers are distributed in every US AWS region, and we have more pressing issues than managing shared state (I think). Anything considered client/server session state must be passed on every HTTPS Request and Response to remain truly stateless, unless I can be convinced otherwise. For example, it could be acceptable that a failure of an app server require the user to login to another server to 'restart' a session, and not be seamless. This still meets the definition of stateless.
  • Meets vague HIPAA "Secure at Rest" requirement, which is assumed by the masses to mean data is encrypted on disk when not on-line/mounted.
  • Prevents unauthorized access to PHI (Personal Health Information) which the application will store in the MongoDB.

Now, to my specific questions: I know how to store password securely using bcrypt. There is a very easy to use bcrypt module for node. API Keys (a-la Amazon AWS) are out, since they must be stored securely on client and server. I am OK sending the user's password to the server ONCE along with the Authy TFA to establish the user is who they say they are, and they also are in possession of a physical token (Authy authorized device). If the user successfully authenticates, and SSL truly prevents a MITM attack, now what? Once the user sends a valid user id and password once, I need to return something that is also verifiable against his user account on the server on every transaction. Will HMAC Signing the request using this token accomplish this while remaining secure against MITM, replay, and ??? attacks? Since the app is on a mobile device and runs in a browser (for admin functions only), I do need to expire the user's login. It is acceptable for this to be time based relative to login time. This can probably be done via a timestamp in the DB, and on the mobile app, regular garbage collection will "destroy" whatever token the client is holding to HMAC sign the http requests with. I don't think basic http authentication meets the requirement (cookies). If a token is built on the server and returned on successful authentication and I store that token with an expiration date in the user DB, does a DB compromise break security if TFA is also in place? Is it safe to return the user's salt to be used as a token, and the client uses the salt + password to generate the same hash that's stored in his user record in the DB to sign the request, as long as the salt and password are not persistent? How does this work in a pure web based client login? Using HTML5 storage? (blech) client cookies? (Double Blech) Can PBKDF2 assist in any of this? I can add elements to the app-level JSON payload, which are sent via normal HTTP GETs/PUTs and Server responses if that helps at all, possibly by having the signing token be part of the signed payload hash. I also will send timestamps with every request that must be < 30 seconds of server time. It is part of the signed payload as well.

  • Hi Nik, welcome to Security.Stackexchange! This is actually quite a broad question and will likely be closed. You'd be better off asking seperate questions rather than one large chunk. Check the FAQ for more info here: http://security.stackexchange.com/helpcenter – NULLZ Jun 06 '13 at 04:33
  • Excellent find there @MichaelHampton cheers! Yes, I believe those two answer from Thomas and Poly cover this question. – TildalWave Jun 06 '13 at 04:40
  • Unfortunately, the answer that mine is marked as a duplicate of is in no way, shape, or form a duplicate. Does anyone even read detailed questions? That question dealt with storing session IDs, two things my question SPECIFICALLY says I don't want to do. A stored session ID is the key to the castle. It has no bearing on request signing, database compromise, or any of my questions. – regretoverflow Jun 06 '13 at 15:08
  • - I will ask a new question eliminating all the details in hopes that someone will actually read it. – regretoverflow Jun 06 '13 at 15:47
  • Since I can't answer this question anymore, the technical answer to my question appears to be SRP. The problem is there are not very many if any production quality implementations for use in my specific project parameters (node.js). – regretoverflow Jun 06 '13 at 16:09
  • 1
    @NikMartin A stored session ID can be hashed with a cheap hash and no salt since it has lots of entropy. – CodesInChaos Jun 06 '13 at 16:53
  • 1
    Against MitM and replay you should validate the server's public key. As long as this key is valid, SSL already prevents MitM and replay, so no need to add it at the application level again. – CodesInChaos Jun 06 '13 at 16:59
  • To come full circle, based on the technology I'm using, I have decided to use a mongoDB backed server-side session object (via express.js and connect-mongoose), and store the signed server.sid on the client as a cookie. This accomplishes all of my goals with the added benefit that I don't have to write my own token passing, signing, and expiration scheme, good old secure cookies will handle it, with e twist that the client side cookie is only storing the sid of the server side session object. And it's still by (my) definition stateless. – regretoverflow Jun 07 '13 at 03:09

0 Answers0