AES encryption & security flaw

2019-04-02 17:58发布

问题:

Check update#1

This logic is a candidate for a authentication procedure, done by simple HTTP requests:

  • I'm sending: userName + encrypted_userName (encrypted_userName is actually the encrypted result of userName, done using AES & as key i use the md5 hash of the password). NOTE: I'm not sending the md5 hashed Password.
  • on the server I'm comparing: encrypted_userName with own_encrypted_userName (since on server i have access to full info on user, i calculate own encrypted_userName).

Question: is this a security flaw? Say bad guy captures full HTTP request, can he extract password from this 2 infos?

CODE DETAILS, if needed:

private static Cipher getCipher(String key, int mode) throws Exception{
     byte[] rawKey = getRawKey(key.getBytes("UTF-8"));
     SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
     Key key2 = skeySpec;
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
     cipher.init(mode, key2);
     return cipher;
}

private static byte[] getRawKey(byte[] seed) throws Exception {
/*  BEFORE:
     KeyGenerator kgen = KeyGenerator.getInstance("AES");
     SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
     sr.setSeed(seed);
     kgen.init(128, sr); // 192 and 256 bits may not be available
     SecretKey skey = kgen.generateKey();
     byte[] raw = skey.getEncoded();
*/
     byte[] raw = MD5Util.getMD5HashRaw(seed);
     return raw;
}

(NOTE: reason why i use the hash of the password is that code is compatible among platforms (client is Android device), while the commented version is NOT)

UPDATE#1

Short answer:

Presented logic is not even close to be considered a secure authentication mecanism (for Why? check Michael's answer bellow)

Decided to use Kerberos (AND not https, since I am not familiar + seems complicated to setup):

It is not a true version of Kerberos (like v4 or v5), it is just my own implementation so lets call it "similar with Kerberos" (I know, I know: DONT "roll your own encryption"!!!),

Here are some details:

  • it works on UDP (now)
  • authentication is done only once, by:

    • client sending a Authenticator message (contains: [userId] in plain text & [something_ecrypted] with [entered_user_password] (curently [something_ecrypted] contains just a timestamp, call it [authenticator_creation_timestamp])) NOTE: password is not transmited
    • server upon receiving message, tryies to decrypt the [something_ecrypted] with [actual_user_password] -> if SUCCESS then client is who it pretends to be, so i send him back a OK response (as in Kerberos this response contains some stuff, like a [public_key] (a RSA key, but encrypted with user_password) + ticket granting ticket (call it [TGT], encrypted with a password known only by server, currently it doenst expire, this [TGT] also contains some stuff, like these 2 timestamps: [TGT_creation_time_stamp] + [authenticator_creation_timestamp] (the one received in the Authenticator message))
    • after receiving this OK message, client has procured a valid [public_key].. so nice!
  • protection agains "reply attack" is not a 100% guarantee, but I see it "safe enought":

    • on each next HTTP reaquest, i attach as headers these 2 guys [new_request_creation_timestamp] (encrypted with [public_key], procured above) + the [TGT] (untouched, as received above)
    • on server I just need to validate [new_request_creation_timestamp] agains some math (obvious [TGT] needs to be valid too):

      ** i expect that the following variables to be almost equal

      delta1 = [TGT_creation_time_stamp] - [authenticator_creation_timestamp]

      delta2 = now()-[new_request_creation_timestamp]

      (I actually allow a difference between them of 5 seconds, but from my tests, its just a matter of some 10-20 millis,

      ** So initial delta (calculated when creating OK response to Authenticator) should perpetuate on next interactions.

I do find this new approach quite trust-worthy, but if you have an opinion or see a BUG in logic, please share.. Thanks

回答1:

Yes, this is a weak security mechanism.

  1. Anyone who captures the information sent to the server can easily replay it to authenticate themselves (replay attack).

  2. It is vulnerable to offline password guessing - anyone who captures the information sent to the server can then very quickly test a password list to find what password your user has chosen (by encrypting the observed username using the hash of each password in turn). The hashing can even be precomputed, speeding the attack up further.

Password based authentication protocols should be resistant to replay attacks and offline password guessing attacks.

Simply using an HTTPS (TLS) connection to your server and sending the username and password in plaintext would normally be a better solution.

In response to your update 1:

  • I strongly advise using HTTPS. It is used everywhere for a reason - it has undergone immense security review and been found to be (largely) secure - far better than what you can get through a SO post.
  • I haven't considered your updated scheme thoroughly, but as it is based on Kerberos it is also subject to offline password guessing attacks as I described above.
  • Having successfully authenticated, don't forget about then actually protecting your data - you'll likely need to derive a shared symmetric key then use authentication + encryption on your data...


回答2:

What i understand is : you are sending Username + Encrypted Username to the server.

Ans: Since you are sending the Username and the encrypted Username which is : UserName + AES(UserName + MD5 Hashed Password)

If anyone knows or find that you give the Username and also gets the Username from your data to server: No worries. There you stand with AES. If you have doubt in AES encryption check this. Your data is secure.



回答3:

I don't think this is a security flaw per se because even knowing both the plaintext message and the encrypted one, it is practically impossible to get the AES key. But I still wouldn't recommend to store the passwords hashed with MD5.