From ed2cd6b34f849f9cc9adb86318457155e47f7314 Mon Sep 17 00:00:00 2001 From: Chaosvex Date: Thu, 10 Nov 2016 23:00:58 +0100 Subject: [PATCH] Core/Auth: Resolved authentication bypass --- src/server/authserver/Server/AuthSession.cpp | 73 +++++++++----------- src/server/authserver/Server/AuthSession.h | 10 +-- 2 files changed, 36 insertions(+), 47 deletions(-) diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index 45c2b61436f02..b139d50ef8a0d 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -118,10 +118,10 @@ std::unordered_map AuthSession::InitHandlers() { std::unordered_map handlers; - handlers[AUTH_LOGON_CHALLENGE] = { STATUS_CONNECTED, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleLogonChallenge }; - handlers[AUTH_LOGON_PROOF] = { STATUS_CONNECTED, sizeof(AUTH_LOGON_PROOF_C), &AuthSession::HandleLogonProof }; - handlers[AUTH_RECONNECT_CHALLENGE] = { STATUS_CONNECTED, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleReconnectChallenge }; - handlers[AUTH_RECONNECT_PROOF] = { STATUS_CONNECTED, sizeof(AUTH_RECONNECT_PROOF_C), &AuthSession::HandleReconnectProof }; + handlers[AUTH_LOGON_CHALLENGE] = { STATUS_CHALLENGE, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleLogonChallenge }; + handlers[AUTH_LOGON_PROOF] = { STATUS_LOGON_PROOF, sizeof(AUTH_LOGON_PROOF_C), &AuthSession::HandleLogonProof }; + handlers[AUTH_RECONNECT_CHALLENGE] = { STATUS_CHALLENGE, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleReconnectChallenge }; + handlers[AUTH_RECONNECT_PROOF] = { STATUS_RECONNECT_PROOF, sizeof(AUTH_RECONNECT_PROOF_C), &AuthSession::HandleReconnectProof }; handlers[REALM_LIST] = { STATUS_AUTHED, REALM_LIST_PACKET_SIZE, &AuthSession::HandleRealmList }; return handlers; @@ -154,8 +154,7 @@ void AccountInfo::LoadResult(Field* fields) } AuthSession::AuthSession(tcp::socket&& socket) : Socket(std::move(socket)), -_sentChallenge(false), _sentProof(false), -_status(STATUS_CONNECTED), _build(0), _expversion(0) +_status(STATUS_CHALLENGE), _build(0), _expversion(0) { N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); g.SetDword(7); @@ -285,10 +284,7 @@ void AuthSession::SendPacket(ByteBuffer& packet) bool AuthSession::HandleLogonChallenge() { - if (_sentChallenge) - return false; - - _sentChallenge = true; + _status = STATUS_CLOSED; sAuthLogonChallenge_C* challenge = reinterpret_cast(GetReadBuffer().GetReadPointer()); if (challenge->size - (sizeof(sAuthLogonChallenge_C) - AUTH_LOGON_CHALLENGE_INITIAL_SIZE - 1) != challenge->I_len) @@ -428,7 +424,10 @@ void AuthSession::LogonChallengeCallback(PreparedQueryResult result) // Fill the response packet with the result if (AuthHelper::IsAcceptedClientBuild(_build)) + { pkt << uint8(WOW_SUCCESS); + _status = STATUS_LOGON_PROOF; + } else pkt << uint8(WOW_FAIL_VERSION_INVALID); @@ -477,10 +476,7 @@ void AuthSession::LogonChallengeCallback(PreparedQueryResult result) bool AuthSession::HandleLogonProof() { TC_LOG_DEBUG("server.authserver", "Entering _HandleLogonProof"); - if (_sentProof) - return false; - - _sentProof = true; + _status = STATUS_CLOSED; // Read the packet sAuthLogonProof_C *logonProof = reinterpret_cast(GetReadBuffer().GetReadPointer()); @@ -500,9 +496,7 @@ bool AuthSession::HandleLogonProof() // SRP safeguard: abort if A == 0 if (A.IsZero()) - { return false; - } SHA1Hash sha; sha.UpdateBigNumbers(&A, &B, NULL); @@ -571,24 +565,6 @@ bool AuthSession::HandleLogonProof() // Check if SRP6 results match (password is correct), else send an error if (!memcmp(M.AsByteArray(sha.GetLength()).get(), logonProof->M1, 20)) { - TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' successfully authenticated", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo.Login.c_str()); - - // Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account - // No SQL injection (escaped user name) and IP address as received by socket - - PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF); - stmt->setString(0, K.AsHexStr()); - stmt->setString(1, GetRemoteIpAddress().to_string().c_str()); - stmt->setUInt32(2, GetLocaleByName(_localizationName)); - stmt->setString(3, _os); - stmt->setString(4, _accountInfo.Login); - LoginDatabase.DirectExecute(stmt); - - // Finish SRP6 and send the final result to the client - sha.Initialize(); - sha.UpdateBigNumbers(&A, &M, &K, NULL); - sha.Finalize(); - // Check auth token if ((logonProof->securityFlags & 0x04) || !_tokenKey.empty()) { @@ -610,6 +586,24 @@ bool AuthSession::HandleLogonProof() } } + TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' successfully authenticated", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo.Login.c_str()); + + // Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account + // No SQL injection (escaped user name) and IP address as received by socket + + PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF); + stmt->setString(0, K.AsHexStr()); + stmt->setString(1, GetRemoteIpAddress().to_string().c_str()); + stmt->setUInt32(2, GetLocaleByName(_localizationName)); + stmt->setString(3, _os); + stmt->setString(4, _accountInfo.Login); + LoginDatabase.DirectExecute(stmt); + + // Finish SRP6 and send the final result to the client + sha.Initialize(); + sha.UpdateBigNumbers(&A, &M, &K, NULL); + sha.Finalize(); + ByteBuffer packet; if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients { @@ -705,10 +699,7 @@ bool AuthSession::HandleLogonProof() bool AuthSession::HandleReconnectChallenge() { - if (_sentChallenge) - return false; - - _sentChallenge = true; + _status = STATUS_CLOSED; sAuthLogonChallenge_C* challenge = reinterpret_cast(GetReadBuffer().GetReadPointer()); if (challenge->size - (sizeof(sAuthLogonChallenge_C) - AUTH_LOGON_CHALLENGE_INITIAL_SIZE - 1) != challenge->I_len) @@ -768,6 +759,7 @@ void AuthSession::ReconnectChallengeCallback(PreparedQueryResult result) _accountInfo.LoadResult(fields); K.SetHexStr(fields[9].GetCString()); _reconnectProof.SetRand(16 * 8); + _status = STATUS_RECONNECT_PROOF; pkt << uint8(WOW_SUCCESS); pkt.append(_reconnectProof.AsByteArray(16).get(), 16); // 16 bytes random @@ -779,10 +771,7 @@ void AuthSession::ReconnectChallengeCallback(PreparedQueryResult result) bool AuthSession::HandleReconnectProof() { TC_LOG_DEBUG("server.authserver", "Entering _HandleReconnectProof"); - if (_sentProof) - return false; - - _sentProof = true; + _status = STATUS_CLOSED; sAuthReconnectProof_C *reconnectProof = reinterpret_cast(GetReadBuffer().GetReadPointer()); diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h index 027011629eb6d..98d2cb9fcdbee 100644 --- a/src/server/authserver/Server/AuthSession.h +++ b/src/server/authserver/Server/AuthSession.h @@ -34,8 +34,11 @@ struct AuthHandler; enum AuthStatus { - STATUS_CONNECTED = 0, - STATUS_AUTHED + STATUS_CHALLENGE = 0, + STATUS_LOGON_PROOF, + STATUS_RECONNECT_PROOF, + STATUS_AUTHED, + STATUS_CLOSED }; struct AccountInfo @@ -90,9 +93,6 @@ class AuthSession : public Socket BigNumber K; BigNumber _reconnectProof; - bool _sentChallenge; - bool _sentProof; - AuthStatus _status; AccountInfo _accountInfo; std::string _tokenKey;