22

I work for a small company, developing an ASP.NET web-application. Recently, we've had the requirement of exposing an API endpoint come up, such that an automated script running in the cloud can periodically pull back some specific JSON-formatted data from the app via a web request. The implementation of this I can handle, but I wasn't sure regarding security concerns. I was reading about HMAC this morning & liked the look of it, as it seemed quite similar to the security protocols of other APIs I've used previously. However, it made me wonder what the value of some of the steps were.

If a client and server have securely agreed on a passphrase / key via prior communication, what risk is there in sending a POST request with the passphrase as part of the body of the HTTPS request, such that the passphrase identifies the user? Trying to look this up I came across Replay Attacks and similar, but can these work over SSL & given the client-side & server-side environments can both be trusted?

Edit: Adding a bit of clarification based on a user's comment below. Our intended use case is to have a script run periodically (once an hour, day, etc) either on one of our servers or in the cloud. It will pull back specific information from our app, as well as third-party APIs, & update a cloud-based spreadsheet for our business development team. It's something we ideally want to leave running & not require any user intervention. Our app normally requires login with a username/password to generate a temporary session, but we were hoping to simplify the process a bit & just provide an API for the script to securely retrieve specific data.

  • 2
    POSTing a key (token) over HTTPS is fine if your TLS is properly configured. I'd opt for a one-time token instead of a key. I.e. the tool first needs to authenticate against an authentication API using a username and pass (+ timestamp*) in order to receive a token (which is valid for 1 transaction or a certain time period) after which that token can be used to submit data. *Timestamp is validated against server's clock within a certain deviation margin, to protect against replay attacks – BlueCacti May 22 at 13:44
  • @BlueCacti : I 100% agree. Default cyphers on HTTPS are good for keeping messages private as they're happening, but don't prevent someone from spending a day or two w/ some cloud computing time to brute force them and see the contents. You can mitigate this some by eliminating weak cyphers, but let's face it, too many people run stuff out of the box w/out hardening. – Joe May 22 at 14:41
  • @BlueCacti an alternative to authenticating to another service to receive a one-time token would be using shared secret + TOTP to generate a one-time token. – Stobor May 23 at 4:11
  • Who use the API? An Browser or another Server? – Peter Rader May 23 at 5:57
  • 1
    @Lovethenakedgun The idea would be that the token has a certain validity, which could also be a certain timespan. This token can then be used by the client to perform certain actions (in the future additional API functionality could be added). If you are 100% certain that the API will only serve one purpose, you could put all necessary data in 1 request: client key, parameters for the request, timestamp (and TOTP-code) – BlueCacti May 23 at 9:42
43

Assuming you mean TLS instead of genuine SSL (which is far older and broken), it is absolutely fine to transmit the password in a POST request. This is standard and how virtually every major and secure web authentication service works. You just have to make sure that the TLS is configured properly. TLS mitigates all the attacks you are worried about. It uses HMAC (or a similar authentication) for integrity, and mitigates replay attacks, reflection attacks, and similar issues that affect authentication systems.

  • 5
    There are a few things that SSL/TLS does not cover, and vulnerabilities in the last few years such as POODLE (SSLv3), BEAST, CRIME/BREACH, renegotiation plaintext injection vulnerability, HEARTBLEED, … that require additional work to counter. For example, to actually prevent replay would require additional application-level tracking of seen messages. To prevent cleartext injection would require application-level signatures. A few years back I wrote up HTDSA to help mitigate these and potential future flaws in the same vein. – amcgregor May 21 at 18:12
  • 3
    Well, many web authentication services use tokens not passwords (e.g. OAuth2). There is a big difference between a scope-limited, short-lived token and a username/password pair. However yes, those tokens are included in the cookie or some other part of the HTTP request. – Bakuriu May 21 at 20:44
  • 2
    @amcgregor TLS should prevent replay attacks. See security.stackexchange.com/questions/20105/…. (Assuming you're talking about a MITM replaying a whole session to try to impersonate the client at a later date.) – Jordan Rieger May 21 at 23:55
  • 1
    @JordanRieger I am not referring to whole-session replay, I am referring to application-level "replay" of the HTTP-encapsulated messages, e.g. JSON blobs, HTML fragments, etc. (The former is a much easier target than the latter, and there have been several cleartext injection vulnerabilities that would make total application trust of the transport into its own security problem, thus HTDSA application-level and application-verified signatures in addition to transport-level encryption, tampering prevention, perfect forward secrecy, etc., etc.) – amcgregor May 22 at 14:16
  • 1
    Apologies for the immediate addition: TLS attempts to protect the transport from shenanigans (while also offering identify pinning, though this is unfortunately not easily accessible from most HTTP clients.) HTDSA protects the authenticity and message integrity going over the transport using public/private key crypto that may be easier to manage than full SSL, and expressly protects against cleartext injection vulnerabilities (app. signature will fail) as well as cross-API-client use & correlation. A "token" issued to one app is not usable by another, but neither is any API response at all. – amcgregor May 22 at 14:21
11

HTTPS serves a few purposes, preventing replay attacks and providing confidentiality of the message being sent. To uphold these guarantees, the client must of course verify the TLS certificate from the server correctly, i.e. match certificate against the expected domain (or if you have self-signed certificates, against a fingerprint). Otherwise, a man-in-the-middle attack can take place without either end noticing. This way, the client knows it is really talking to the right server.

But how can the server trust the client? For that, you could use either a client certificate or, as you propose, an API key. API keys are a common concept so if there was some big issue with doing this, we would have stopped doing it by now. It is good practice to regularly renew an API key and it might convenient to have a key ID field to be able to rotate them easily, but generally it should not be a big risk to use the same key for years -- of course, it depends on the sensitivity of the information, how many people have access to the key, etc.

  • I'd think that use of a password would be sufficient for the server to trust the client. This doesn't seem like a situation where a client certificate would be necessary (though it would be secure). – forest May 21 at 6:56
  • @forest I never said it was :-). But it's good to know of the option, because they do provide pretty good security. I think few people know of them given how rarely they are used. They're also a hassle for users, but that's not applicable between two machines. – Luc May 21 at 6:57
  • Agreed, and if this is some application, a client certificate would be more secure. – forest May 21 at 7:00
  • 4
    @IllusiveBrian Client certificates are part of the TLS spec so any decent TLS library will support them. It's usually not relevant to the API. That's one of the main advantages of them, actually. It's managed in TLS so the API doesn't have to worry about authentication. In the last few years I've been experimenting with these and I find them quite easy to use. Browsers have decent support for them. It seems that the biggest barrier to their use is ignorance of them. If you want to use them be prepared to educate people. – JimmyJames May 21 at 19:45
  • 2
    @Luc "They're also a hassle for users" I would say yes and no. They are quite simple for everyone if you have the infrastructure to support them. I've worked in places where every user had a client-cert pre-configured on their machine. So to authenticate users, all that was required was just enable client-cert authentication on the host. The browser handles the rest. You just need to the users to know that the pop-up asking which cert to use is not a problem. Some browsers ask even if there is only one available. – JimmyJames May 21 at 19:53
-7

I disagree on the safety of sending shared secrets over HTTPS.

Here's my reasoning :

SSL/TLS was intended to keep someone from being able to compromise the conversation as it happens. As such, there exist webservers installed with weak ciphers. (Not everyone can keep their OS up-to-date; some of us still have to support outdated hardware that may not be able to be updated)

With a weak cipher, or with some of the flaws that @amcgregor listed, someone might be able to view the message minutes after they were sent, which is the reason why they're suggesting that you use the timestamp to hash the authentication token.

If you're sending the shared secret with every message, then an attacker need only see any one of the incoming messages to permanently undo your security. (at least, until that password is changed, which let's face it, isn't going to happen unless they do something to alert you to it)

If you're using more secure means (a challenge/response to assign a time-limited token), then the snooping party needs to view two specific messages (the challenge and response), and use that to get candidates for the shared secret, and then either get more challenge/response keys to narrow it down, or start trying all of the candidates and give you a sign of their attack.

Putting your shared secret on the wire, no matter how good the encryption, means that you're relying on a single layer of security, and in practice that is a bad idea.

  • 4
    I flagged the post because you should be editing your previous answer, not creating a new one. It's absolutely fine to stick by your opinion even if it is not well received, but it is against the rules to evade downvotes in this manner. It doesn't matter if your answer itself is correct or incorrect. – forest May 24 at 3:09
  • 2
    I agree that the previous version of this answer might have created a distraction with the opinion about the ciphers. I think that in some cases, to recreate an answer that hit so many downvotes but with a major point changed can be ok (combats runaway voting). But in this case, I think that you will get as many downvotes because of the core content and logic of the answer. – schroeder May 24 at 7:36
  • 1
    Why wouldn't your reasoning cause banks to not provide online banking over TLS? – Greg Schmit Jun 4 at 4:23
  • @GregSchmit : You're right, and it's a reason to at least use two factor auth in your banking. But it's still a slightly different situation than what's being proposed -- there's a login phase, so you send the password once, then get some sort of a token to indicate you're logged in. But they're proposing to take away that layer of protection, and send it every time. The edits have since made it so it might be a once a day thing and read-only, and not like APIs that I deal with. – Joe Jun 4 at 14:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.