8

My REST service currently uses SCRAM authentication to issue tokens for callers and users.

Tokens issued by the SCRAM exchange have an expiry time after which a repeated sign-in is required. We also will be issuing 'infinite' tokens that have no expiry to simplify integration for individuals (who will use our service for personal use) and in preparation for a JSONP endpoint.

We have the ability to revoke caller privileges (the account to which the token is attached) and ban IPs, as well as impose quotas to any type of request across any time period.

One thing that I haven't implemented, however, is MAC for requests. As I've thought about it more, for some requests I think this is needed, because otherwise tokens can be stolen and before we identify this and deactivate the associated caller account, some damage could be done to our user accounts.

In many systems the MAC is generated from the body or query string of the request, however this is difficult to implement as I'm using the ASP.Net Web API and don't want to read the body twice. Equally importantly I want to keep it simple for callers to access the service, and I need to be able to support both desktop/mobile apps as well as web browsers.

So what I'm thinking is to have a MAC key sent to a user on registration, and have them calculate a request MAC on:

  • the url, possibly minus query string
  • the verb
  • the request ip (potentially is a barrier on some mobile devices though and definitely is in javascript)
  • utc date and time when the client issues the request.

For the last one I would have the client send that string in a request header, of course - and I can use it to decide whether the request is 'fresh' enough.

My thinking is that whilst this doesn't prevent message body tampering it does prevent using a model request to use as a template for different requests later on by a malicious third party. I believe only the most aggressive man in the middle attack would be able to subvert this, and I don't think our services offer any information or ability that is valuable enough to warrant that.

The services will use SSL as well, for sensitive stuff. And if I do this, then I'll be using HMAC-SHA-256 with the key generated using a PRNG.

Does this sound enough? Have I missed anything?

I don't think I'm a beginner when it comes to security, but when working on it I always. am shrouded in doubt, so I appreciate having this community to call upon!

  • 1
    How about using https? – CodesInChaos Oct 31 '12 at 09:35
  • @AndrasZoltan, if the client is compromised, then you're hosed (no scheme can provide security in that threat model). That's a bit of a tangent, though. Anyway, I agree with CodesInChaos: HTTPS is the elephant in the room -- it is the standard solution, and it's not clear why you've rejected it. – D.W. Oct 31 '12 at 12:02
  • A general bit of advice: I think questions on this site work better when you focus primarily on identifying the requirements (i.e., explaining the problem you are trying to solve), without making assumptions about the best solution. This question seems heavy on a proposed mechanism, but I don't see a clear statement of the problem you are trying to solve (the security goals, the threat model, the constraints/requirements). – D.W. Oct 31 '12 at 12:06
  • Can you explain further what mixed-content issues you are facing? I suspect they are solvable, e.g., by hosting all Javascript libraries on a HTTPS URL. (And, if you need to access a HTTP service from a HTTPS-hosted page, don't use JSONP! In general, JSONP is pretty ugly from a security perspective.) – D.W. Oct 31 '12 at 16:32
  • I'll update my question tomorrow with the full set of requirements for the services I've developed - they're close to going live, so I can't really justify changing the security much (although I don't think I have an issue with a lack of security here, more a question of having too much)! - there are a lot of use cases for them; but if it helps make things clearer then it'll be worthwhile. – Andras Zoltan Oct 31 '12 at 21:01
  • As I went through and started to update my question I started to understand why the MAC is irrelevant if HTTPS is used. I have two types of callers - those that can only access non-personal data (running job searches), which will simply be issued with a persistent API token; and those that can - access personal data (after signing in a user). All I do is make sure that this second class of caller must always use HTTPS (and check the certs of course) and the security works. – Andras Zoltan Nov 01 '12 at 09:07

2 Answers2

4

If you use SSL for transport, and do it properly, then any extra MAC is redundant; and, when it comes to it, so is SCRAM. A selling point of SCRAM is that it is supposed to resist situations where SSL is used improperly, i.e. without appropriate server authentication (unfortunately, it happens). But the security argument of SCRAM is rather weak in such a situation, because it will not prevent a man-in-the-middle attack; and, without a MitM, the basic plain-password-within-SSL is already good. The only advantage of SCRAM over a plain password is that in case of a MitM, the attacker does not learn the password right away. He still sees all the exchanged data, and can insert commands of his own, and he obtains enough data to perform an offline dictionary attack, something that very few passwords come through unscathed.

In your proposal for adding a MAC, you do not say where the MAC key comes from. This is critical. A MAC has any value only as long as the key is unknown to the attacker. But if the client and the server already share a key which is unknown to the attacker, why would they even bother with a password and SCRAM ? Let them use Pre-Shared Key TLS, i.e. SSL/TLS with the shared key as basis for mutual authentication and encryption: no certificate at all (so no certificate validation to get wrong), slick and fast operation.

Even better, if the client and server share a password, don't want to use certificates, fear offline dictionary attacks, and don't want the server to store the passwords as is, then the solution is TLS-SRP. Client and server authenticate each other relatively to a common password, the server does not store the password but only a hash-equivalent of it, and the password is safe from offline dictionary attacks, even in case of a MitM attempt (not only is the attempt thwarted, but the attacker does not even gain enough data to "try passwords at home").


The SCRAM designers were probably told about SRP at some point, because they added in section 9 of the specification the following paragraph:

Authentication mechanisms that protect against this attack are available (e.g., the EKE class of mechanisms). RFC 2945 [RFC2945] is an example of such technology. The WG elected not to use EKE like mechanisms as a basis for SCRAM.

They give no justification whatsoever of why they reject PAKE protocols (which they improperly call "EKE", which is only the name of the first known PAKE protocol).

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • Very good and interesting points here, thanks. To answer: The MAC would be a PRNG-generated hex key sent by email to the client. Also, there are I believe mitigating reasons why I'm using SCRAM/Tokens and therefore also why I need to bring the MAC in. Of primary importance is the range of clients I have to be able to support - specifically HTTP sockets-based clients (apps on mobiles) but also JSONP based clients (web pages) as well. Whilst this is a pain, it means I have to have a lowest-common-denominator solution that every client can use without having loads of different security modules – Andras Zoltan Oct 30 '12 at 23:48
  • To clarify: the MAC *key* would be sent by email. Also our passwords are stored stretched by pbkdf2 using SHA256, which plugs in nicely to SCRAM. Service account passwords are generated from a wide character set by a PRNG, and user passwords are generally user-chosen. – Andras Zoltan Oct 31 '12 at 00:24
  • @AndrasZoltan, on crypto keys sent by email to the user - well, the usability of that for users sounds inferior to standard web authentication methods. Maybe it would be worthwhile to start over, set aside the specific mechanism you have in mind for now, just focus on articulating the requirements in the question, and let us work out the best way to meet those requirements? – D.W. Oct 31 '12 at 12:04
  • Marking as answer because the scenario I considered the MAC to be required for can easily be mitigated by SSL as you've suggested. I would disagree with you about SCRAM(-SHA-256 in this case), however. When your user and caller passwords are stored stretched like ours (to help slow down offline attacks in even of DB theft), a SCRAM auth exchange offers a simple yet effective way to achieve sign-in whilst avoiding sending a clear password. I agree that the SCRAM auth - as the RFC suggests - should still be done over SSL - and will be making sure that it is. – Andras Zoltan Nov 01 '12 at 09:17
0

For most settings, I recommend that you just use HTTPS (SSL) and CSRF tokens. This is the standard architecture for securing a web application / web service. If you use HTTPS + CSRF tokens, you don't need a MAC.

I would push back on the idea of "using SSL only for the sensitive stuff". That has some problems. I would recommend using HTTPS sitewide. Search on this site for information about pros and cons of using SSL sitewide and how to implement it.

I don't know whether your interface is for programmatic use only or if it will also be used by humans. If so, HTTPS will probably also provide the best usability for users, if the client-side has a human sitting behind a web browser.

D.W.
  • 98,420
  • 30
  • 267
  • 572