Skip to content

Commit

Permalink
Core/Accounts: sessionkey field in account table is only a temporary …
Browse files Browse the repository at this point in the history
…storage to pass data from authserver to worldserver and should only be used as such. Clearing sessionkey from database after a successful login to prevent possible exploits.
  • Loading branch information
Shauren committed Feb 7, 2013
1 parent 5b45a87 commit fb43a92
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 24 deletions.
2 changes: 1 addition & 1 deletion sql/base/auth_database.sql
Expand Up @@ -26,7 +26,7 @@ CREATE TABLE `account` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Identifier',
`username` varchar(32) NOT NULL DEFAULT '',
`sha_pass_hash` varchar(40) NOT NULL DEFAULT '',
`sessionkey` varchar(80) NOT NULL DEFAULT '',
`sessionkey` varchar(80) NOT NULL DEFAULT '' COMMENT 'Temporary storage of session key used to pass data from authserver to worldserver',
`v` varchar(64) NOT NULL DEFAULT '',
`s` varchar(64) NOT NULL DEFAULT '',
`email` varchar(254) NOT NULL DEFAULT '',
Expand Down
3 changes: 3 additions & 0 deletions sql/updates/auth/2013_02_07_00_auth_account.sql
@@ -0,0 +1,3 @@
UPDATE `account` SET `sessionkey`='';
ALTER TABLE `account`
CHANGE `sessionkey` `sessionkey` varchar(80) NOT NULL DEFAULT '' COMMENT 'Temporary storage of session key used to pass data from authserver to worldserver' AFTER `sha_pass_hash`;
8 changes: 8 additions & 0 deletions src/server/game/Accounts/AccountMgr.cpp
Expand Up @@ -187,6 +187,14 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPass

LoginDatabase.Execute(stmt);

stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_VS);

stmt->setString(0, "");
stmt->setString(1, "");
stmt->setString(2, username);

LoginDatabase.Execute(stmt);

return AOR_OK;
}

Expand Down
35 changes: 13 additions & 22 deletions src/server/game/Server/WorldSocket.cpp
Expand Up @@ -750,7 +750,6 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
uint32 clientBuild;
uint32 unk2, unk3, unk5, unk6, unk7;
uint64 unk4;
BigNumber v, s, g, N;
WorldPacket packet, SendAddonPacked;
BigNumber k;

Expand Down Expand Up @@ -779,6 +778,8 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
clientSeed);

// Get the account information from the realmd database
// 0 1 2 3 4 5 6 7 8
// SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ?
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);

stmt->setString(0, account);
Expand All @@ -795,27 +796,11 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)

Field* fields = result->Fetch();

uint8 expansion = fields[6].GetUInt8();
uint8 expansion = fields[4].GetUInt8();
uint32 world_expansion = sWorld->getIntConfig(CONFIG_EXPANSION);
if (expansion > world_expansion)
expansion = world_expansion;

N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
g.SetDword (7);

v.SetHexStr(fields[4].GetCString());
s.SetHexStr (fields[5].GetCString());

const char* sStr = s.AsHexStr(); // Must be freed by OPENSSL_free()
const char* vStr = v.AsHexStr(); // Must be freed by OPENSSL_free()

sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: (s, v) check s: %s v: %s",
sStr,
vStr);

OPENSSL_free((void*)sStr);
OPENSSL_free((void*)vStr);

///- Re-check ip locking (same check as in realmd).
if (fields[3].GetUInt8() == 1) // if ip is locked
{
Expand All @@ -831,7 +816,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)

k.SetHexStr(fields[1].GetCString());

int64 mutetime = fields[7].GetInt64();
int64 mutetime = fields[5].GetInt64();
//! Negative mutetime indicates amount of seconds to be muted effective on next login - which is now.
if (mutetime < 0)
{
Expand All @@ -845,12 +830,12 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
LoginDatabase.Execute(stmt);
}

locale = LocaleConstant (fields[8].GetUInt8());
locale = LocaleConstant (fields[6].GetUInt8());
if (locale >= TOTAL_LOCALES)
locale = LOCALE_enUS;

uint32 recruiter = fields[9].GetUInt32();
std::string os = fields[10].GetString();
uint32 recruiter = fields[7].GetUInt32();
std::string os = fields[8].GetString();

// Must be done before WorldSession is created
if (sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED) && os != "Win" && os != "OSX")
Expand Down Expand Up @@ -948,6 +933,12 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// NOTE ATM the socket is single-threaded, have this in mind ...
ACE_NEW_RETURN(m_Session, WorldSession(id, this, AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter), -1);

stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_CLEAR_SESSIONKEY);

stmt->setUInt32(0, id);

LoginDatabase.Execute(stmt);

m_Crypt.Init(&k);

m_Session->LoadGlobalAccountData();
Expand Down
3 changes: 2 additions & 1 deletion src/server/shared/Database/Implementation/LoginDatabase.cpp
Expand Up @@ -35,14 +35,15 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED, "INSERT INTO account_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, 'Trinity realmd', 'Failed login autoban', 1)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_ACCOUNT_BANNED, "DELETE FROM account_banned WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_SESSIONKEY, "SELECT a.sessionkey, a.id, aa.gmlevel FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_CLEAR_SESSIONKEY, "UPDATE account SET sessionkey = '' WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_VS, "UPDATE account SET v = ?, s = ? WHERE username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET sessionkey = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT a.sha_pass_hash, a.id, a.locked, a.last_ip, aa.gmlevel, a.v, a.s FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_FAILEDLOGINS, "UPDATE account SET failed_logins = failed_logins + 1 WHERE username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_FAILEDLOGINS, "SELECT id, failed_logins FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT id, sessionkey, last_ip, locked, v, s, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_EMAIL, "SELECT id, username FROM account WHERE email = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_NUM_CHARS_ON_REALM, "SELECT numchars FROM realmcharacters WHERE realmid = ? AND acctid= ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_BY_IP, "SELECT id, username FROM account WHERE last_ip = ?", CONNECTION_SYNCH);
Expand Down
1 change: 1 addition & 0 deletions src/server/shared/Database/Implementation/LoginDatabase.h
Expand Up @@ -53,6 +53,7 @@ enum LoginDatabaseStatements
LOGIN_INS_ACCOUNT_AUTO_BANNED,
LOGIN_DEL_ACCOUNT_BANNED,
LOGIN_SEL_SESSIONKEY,
LOGIN_UPD_CLEAR_SESSIONKEY,
LOGIN_UPD_VS,
LOGIN_UPD_LOGONPROOF,
LOGIN_SEL_LOGONCHALLENGE,
Expand Down

0 comments on commit fb43a92

Please sign in to comment.