0

We have a situation where a user's identity can be verified as follows: the network provider knows the identity of the user and injects secure headers into the HTTP request, which our servers can use to authenticate the user.

We're writing client-server applications and want to use this mechanism to automatically authenticate the user. We can't use HTTPS end-to-end for the authentication request because obviously the network couldn't inject headers in that case.

EDIT: roughly equivalent setup:

(client <-VPN-> HTTP proxy) <-internet-> our server

Assume the VPN (bold section) is secure and the user is authenticated within in the VPN.

The client generates a HTTP request. A proxy within the network knows the client's identity and generates a token which is automatically added to the headers in the proxied HTTP request. All of this happens in a secure domain and cannot therefore be compromised. (Unfortunately we can't change anything in the VPN setup, such as have the proxy make a HTTPS request instead.)

Our server can query back to the network (securely) to determine the identity of the client who initiated the request.

Assumptions:

  1. This HTTP requirement is a given and can't be changed.
  2. An attacker can't fool the identity verification process by presenting fake headers.
  3. An attacker might be able to otherwise intercept/compromise the HTTP request/response.
  4. Server is stateless (so no storing one-time keys server-side).
  5. Storing a private key in the client application is not an option as it could be compromised
  6. The HTTP request/response will be used auto-authenticate the user, but all other interactions before (if necessary) and afterward will be over HTTPS.

Here's what we've tried so far:

  1. Client fetches a public key PK from server over HTTPS
  2. Client generates a symmetric key SK
  3. Client encrypts SK using PK, and sends this to server over HTTP
  4. Server verifies user's identity and generates authentication token AT
  5. Server encrypts AT using SK -> E(AT,SK)
  6. Server signs E(AT,SK) using its private key and sends to client
  7. Client uses PK to verify signature
  8. Client uses SK to decrypt E(AT,SK) giving AT
  9. Client uses AT to authenticate all subsequent HTTPS traffic.

(And we should probably use separate key pairs for encryption and signing, but let's ignore that for now).

As far as I can see, this is secure against eavesdroppers (as they won't have SK) but if a malicious attacker can modify the HTTP request, there is nothing stopping them from generating their own symmetric key instead of SK, encrypting it with PK, replacing the request payload with that and the server will have no idea that it's not talking to the real client. The server will then happily encrypt a valid AT and send it back to the attacker who can then proceed with impunity.

Is there a way to shore up this hole? Is it even possible to do this with a stateless server?

EDIT: if the server can detect tampering and abort the authentication process, that would be sufficient. "This is not possible because X" is also a valid answer, if it can be demonstrated.

  • What is in the header set by the network provider? Unless that header is verifiably signed by the network provider (eg using a secret key shared with you, or public key crypto), and part of the signed material is request-specific, it would seem to be impossible to prevent a man-in-the-middle between you and the network provider subverting the network-provider-header authentication step. – bobince May 29 '14 at 10:43
  • @bobince Agreed. Let's just say the header contains opaque data. So there is nothing tying the request payload to the headers, and therefore nothing stopping an attacker stealing the headers and using them for a different payload. I was hoping there was something we could do in the payload to verify its integrity, but since an attacker can follow exactly the same steps as a genuine client and we won't know the difference, unfortunately I think the answer is "it's not possible". – CupawnTae May 29 '14 at 13:53
1

Why can't it be changed? You can use an HTTPS proxy where the user connects via SSL to the gateway adding the headers and then relays the communication on to your servers, also over SSL. You can't have one SSL connection the entire way though, but that doesn't mean you can't have SSL connections for each step of the journey.

Otherwise, you are effectively asking an impossible question because you want to have a secure connection between you and the client, but want someone else to be able to be a man in the middle and modify what you are sending. Those are mutually exclusive goals unless you make it so that the intended man in the middle can be in the middle of the communication.

  • It can't be changed because we have no control over the network provider - this is the mechanism we have forced to use and we control only the client and the server. By the time the request reaches any of our infrastructure it has been out in the wild and so presumably may have been compromised. If the server can detect tampering and we can abort the authentication at that point, that would be sufficient - I should probably add that to the question. – CupawnTae May 28 '14 at 14:34
  • @CupawnTae - I think you are going to have to add more details in general to the question. As it is currently stated, I don't see a clear solution. You have an untrusted connection from the user to the network provider that you have no control over, so you can't detect tampering, period. There is nothing you can really do to deal with that since you can't guarantee anything about who is actually talking to the network provider unless there is some undisclosed mechanism they use to authenticate the user. – AJ Henderson May 28 '14 at 14:43
  • Sorry, was rushing out earlier. So I take your point about wanting one man in the middle to be able to change stuff, and another not to. But they're different data streams. Or message and envelope I guess. If an attacker messes with the headers, the authentication will fail, and we're happy with that. But we don't want the request payload to be tampered with, and it's that that we want secured end-to-end. If we had a shared secret there'd be no issue, so some sort of key exchange would be ideal, but I don't know of one that doesn't require some kind of state transition on both ends. – CupawnTae May 28 '14 at 14:51
  • And I didn't see your second comment until after posting. The connection between the user and network provider is not a problem - it's between the network provider and the server that is insecure. I'll add a diagram to the question. Thanks for your attention so far – CupawnTae May 28 '14 at 14:57
  • I added more details to the question, not sure if it makes it clearer, but the VPN-with-proxy is a good representation for the setup. – CupawnTae May 28 '14 at 15:23

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.