Can you spot a vulnerability in my authentication protocol?

Some time ago, we needed a solution for Single Sign On authentication between multiple web services. At least at that time, we thought the OpenID protocol was too complicated, and we were not sure about its Ruby on Rails plugins. Therefore, we developed our own protocol, instead of introducing OpenID providers and OpenID users.

I have two questions:

  • Was it bad not to create our own OpenID provider and configure our OpenID consumers accept only this? Public login or registration is not allowed, and we like to keep authentication simple.

  • Can you spot a critical error or vulnerability in the next design?

If you, as a commune, can approve this project, I will consider extracting this code into the Ruby on Rails plugin.

Please review the flowchart and sequence of the sequence .

Details:

Authentication Provider ("AP"):

  • A central service that contains all user data.
  • In this setting, there is only one “access point”.
  • It may be possible to have multiple “APs,” but this should not be relevant in this context.
  • "AP" knows every "S" in advance.

Authentication Client (Service "S"):

  • There are several internal and external web services.
  • Each service knows the "AP" and its public key in advance.

Actor ("A"):

  • The end user who authenticates herself with the AP using a username and password
  • Can request directly any URI "S" or "AP" before it logs in.

Connections between "A", "S" and "AP" are protected by HTTPS.

The authentication logic is briefly described:

This is a description of the graphic flowchart and sequence diagram that were linked at the top of this message.

1) Supplier "AP"

  • "AP" makes an HTTP POST request from server to server "S" to receive nonce.
  • "AP" generates an authentication token.
  • Authentication current is an XML object that includes:
    • validity period (after 2 minutes),
    • previously requested nonce (to prevent replay),
    • identification name "S" (token for Service_1 is not suitable for Service_2),
    • end user information.
  • The authentication current is encrypted using AES256, and the encryption key and initialization vector are signed with the private RSA key of the AP.
  • The resulting strings ("data", "key" and "iv") are first encoded by Base64, and then URL encoded so that they can be delivered to the URL query string.
  • End user "A" is redirected via HTTP to service "S" (HTTPS GET request).

2) Service "S"

  • Gets the authentication token in the URL parameters from the user agent.
  • Decrypts an authentication token with the public public key AP.
  • Accepts only one authentication token only once (the token includes unce, which is valid only once).
  • Verifies that the authentication name in the authentication token matches the service name.
  • Verifies that the authentication token has not expired.

Notes:

This is not a problem if someone else can decrypt the authentication token, as it does not contain confidential user information. However, it is very important that no one but the AP can create a valid authentication token. Therefore, an RSA key pair is involved.

The RSA private key is used only for signing the token, because it cannot encrypt data that is longer than the actual key length. Therefore, AES is used for encryption.

Since the authentication token is supplied as an HTTP GET request, it will be saved, for example. in the Apache log file. The use of one-time inaction and expiration dates should minimize the possibility of a second attack. A POST request will require an HTML page with a form that is automatically submitted by Javascript, so GET is used.

Service "S" generates nonce only in a request for the server-server API. Therefore, unauthenticated requests should not present a DoS vulnerability.

+4
source share
4 answers

You confuse authentication ("I am the one who say that I am") and authorization / access control ("I am allowed access to this"). You can simply implement OAuth and then request the server via HTTPS with "is this the OAuth identifier that I can access?". You do not need to worry about repeated attacks as you use HTTPS.

"Security is complex, so I will create my own."

The authentication token is encrypted using AES256, and the encryption key and initialization vector are signed with the RSA private key.

AES-256 and AES-192 have weak key graphics. But you do not use it for confidentiality; you use it as some kind of integrity check. This does not work: the attacker receives a “signed” authentication token. The attacker restores the key and IV. Attacker encrypts another authentication token with the same key and IV and uses the same “signature”.

What is wrong with hashing and hash signing? Also note that if you intend to use custom signing, you need to be careful with padding (IIRC PKCS - it adds at least 11 bytes anyway).

EDIT: And if you use a cipher where you should use a hash / MAC, you really shouldn't develop a security protocol!

+7
source

Here are some quick thoughts on question 1:

  • The development of a working security protocol is very complex, so, as a general principle, I would prefer to use the existing one.

  • However, I appreciate that OpenID may not have been installed at the time. In addition, OpenID is still relatively new, and perhaps not all of its limitations have been clarified.

  • However, you are using OpenID in a limited scenario where the big problem of OpenID (multi-member participation) does not come into play. You use only the "technical core" OpenID, which is easier to understand.

  • Your requirements and overview of your protocol reminds me of Kerberos. I am also tempted to click on the LDAP + sign, but I do not know what specific solutions exist for this.

  • The point in favor of your protocol is that you took the time to describe it in detail. This is what puts you higher than most home-made security protocol developers!

+4
source

In short, I find that this protocol is being rebuilt in the wrong place and is ultimately vulnerable to attack.

So what is a vulnerability?

End user "A" is redirected via HTTP to service "S" (HTTPS GET request).

This is likely to be a violation of OWASP A9 . In no case is a user session identifier transmitted over an insecure channel, such as http. Even if the session identifier has not yet been authenticated, the attacker is patient, he can sniff the wire looking for the session identifier, and then periodically check if they are authenticated, and then use them to access your system.

"Complexity is the worst enemy of security."

- Bruce Schneier

The authentication identifier is encrypted using AES256, and the encryption key and initialization vector are signed by private RSA APs.

First of all, RSA can be used to encrypt a message, so there is no need for aes. HTTPS, on the other hand, will be more efficient and proven security. I don’t understand why you should pass the authentication token to the client when you already have a secure communication channel between the server. The server can simply say, "Hi, someone redirected this session ID to me, what is its status information?" This is a matter of the weakest link in the chain, and your session ID should be strong enough. This would require that the session identifier be sent by the client as a GET or POST request when a hand disconnection occurs that might open the door for Session Fixation . You can check the IP address before and after the handoff, sometimes the client IP address can change legally, but the handoff will be a very narrow window in which this can happen, and most importantly, it completely terminates the Fixation session.

In general, you should avoid re-inventing wheal. Especially when it comes to security issues like those that have already been resolved. Kerberos is beautiful, especially if you need to bind authentication other than http. Using LDAP for session management is another option.

+2
source

Do you really just sign the AES key and then send the encrypted token, RSA key signature, and then key-iv to PLAINTEXT?

This is unsuccessful. An attacker can use this key to decrypt a token, change it in any necessary way, and encrypt it. Your server will never find the difference.

If you want to check the integrity of the token, just make a hash and sign this hash. For this, hashes are used. No need to use encryption here.

+1
source

All Articles