From 92178e66e8ffb5befcf9cec2426ca1775c621a81 Mon Sep 17 00:00:00 2001 From: arrai Date: Wed, 2 Sep 2009 01:51:26 +0200 Subject: [PATCH] [8450] Prevented using of plaintext passwords in sql queries --- src/game/AccountMgr.cpp | 51 ++++++++++++++++++++++++++++++++---------------- src/game/AccountMgr.h | 1 + src/game/WorldSocket.cpp | 11 ++++------- src/shared/Auth/Sha1.h | 2 -- src/shared/Util.cpp | 20 +++++++++++++++++++ src/shared/Util.h | 1 + src/shared/revision_nr.h | 2 +- 7 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/game/AccountMgr.cpp b/src/game/AccountMgr.cpp index 915408e49..0e95766b7 100644 --- a/src/game/AccountMgr.cpp +++ b/src/game/AccountMgr.cpp @@ -22,6 +22,7 @@ #include "Player.h" #include "Policies/SingletonImp.h" #include "Util.h" +#include "Auth/Sha1.h" extern DatabaseType loginDatabase; @@ -41,17 +42,12 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass normalizeString(username); normalizeString(password); - loginDatabase.escape_string(username); - loginDatabase.escape_string(password); - - QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'", username.c_str()); - if(result) + if(GetId(username)) { - delete result; return AOR_NAME_ALREDY_EXIST; // username does already exist } - if(!loginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s',SHA1("_CONCAT3_("'%s'","':'","'%s'")"),NOW())", username.c_str(), username.c_str(), password.c_str())) + if(!loginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s','%s',NOW())", username.c_str(), CalculateShaPassHash(username, password).c_str())) return AOR_DB_INTERNAL_ERROR; // unexpected error loginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL"); @@ -121,9 +117,11 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, normalizeString(new_uname); normalizeString(new_passwd); - loginDatabase.escape_string(new_uname); - loginDatabase.escape_string(new_passwd); - if(!loginDatabase.PExecute("UPDATE account SET username='%s',sha_pass_hash=SHA1("_CONCAT3_("'%s'","':'","'%s'")") WHERE id='%d'", new_uname.c_str(), new_uname.c_str(), new_passwd.c_str(), accid)) + std::string safe_new_uname = new_uname; + loginDatabase.escape_string(safe_new_uname); + + if(!loginDatabase.PExecute("UPDATE account SET v='0',s='0',username='%s',sha_pass_hash='%s' WHERE id='%d'", safe_new_uname.c_str(), + CalculateShaPassHash(new_uname, new_passwd).c_str(), accid)) return AOR_DB_INTERNAL_ERROR; // unexpected error return AOR_OK; @@ -131,19 +129,19 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd) { - QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); - if(!result) + std::string username; + + if(!GetName(accid, username)) return AOR_NAME_NOT_EXIST; // account doesn't exist - delete result; if (utf8length(new_passwd) > MAX_ACCOUNT_STR) return AOR_PASS_TOO_LONG; normalizeString(new_passwd); - loginDatabase.escape_string(new_passwd); // also reset s and v to force update at next realmd login - if(!loginDatabase.PExecute("UPDATE account SET v='0', s='0', sha_pass_hash=SHA1("_CONCAT3_("username","':'","'%s'")") WHERE id='%d'", new_passwd.c_str(), accid)) + if(!loginDatabase.PExecute("UPDATE account SET v='0', s='0', sha_pass_hash='%s' WHERE id='%d'", + CalculateShaPassHash(username, new_passwd).c_str(), accid)) return AOR_DB_INTERNAL_ERROR; // unexpected error return AOR_OK; @@ -191,10 +189,13 @@ bool AccountMgr::GetName(uint32 acc_id, std::string &name) bool AccountMgr::CheckPassword(uint32 accid, std::string passwd) { + std::string username; + if(!GetName(accid, username)) + return false; + normalizeString(passwd); - loginDatabase.escape_string(passwd); - QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1("_CONCAT3_("username","':'","'%s'")")", accid, passwd.c_str()); + QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash='%s'", accid, CalculateShaPassHash(username, passwd).c_str()); if (result) { delete result; @@ -216,3 +217,19 @@ bool AccountMgr::normalizeString(std::string& utf8str) return WStrToUtf8(wstr_buf,wstr_len,utf8str); } + +std::string AccountMgr::CalculateShaPassHash(std::string& name, std::string& password) +{ + Sha1Hash sha; + sha.Initialize(); + sha.UpdateData(name); + sha.UpdateData(":"); + sha.UpdateData(password); + sha.Finalize(); + + std::string encoded; + hexEncodeByteArray(sha.GetDigest(), sha.GetLength(), encoded); + + return encoded; +} + diff --git a/src/game/AccountMgr.h b/src/game/AccountMgr.h index 2b3dbedcd..9bbc358d8 100644 --- a/src/game/AccountMgr.h +++ b/src/game/AccountMgr.h @@ -50,6 +50,7 @@ class AccountMgr uint32 GetId(std::string username); uint32 GetSecurity(uint32 acc_id); bool GetName(uint32 acc_id, std::string &name); + std::string CalculateShaPassHash(std::string& name, std::string& password); static bool normalizeString(std::string& utf8str); }; diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index 36da6924f..b8cf809a8 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -865,13 +865,10 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) // Re-check account ban (same check as in realmd) QueryResult *banresult = - loginDatabase.PQuery ("SELECT " - "bandate, " - "unbandate " - "FROM account_banned " - "WHERE id = '%u' " - "AND active = 1", - id); + loginDatabase.PQuery ("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 " + "UNION " + "SELECT 1 FROM ip_banned WHERE ip = '%s'", + id, GetRemoteAddress().c_str()); if (banresult) // if account banned { diff --git a/src/shared/Auth/Sha1.h b/src/shared/Auth/Sha1.h index b4b640adb..ffb4a1711 100644 --- a/src/shared/Auth/Sha1.h +++ b/src/shared/Auth/Sha1.h @@ -42,8 +42,6 @@ class Sha1Hash uint8 *GetDigest(void) { return mDigest; }; int GetLength(void) { return SHA_DIGEST_LENGTH; }; - BigNumber GetBigNumber(); - private: SHA_CTX mC; uint8 mDigest[SHA_DIGEST_LENGTH]; diff --git a/src/shared/Util.cpp b/src/shared/Util.cpp index b5cd93fd0..cdd890bc7 100644 --- a/src/shared/Util.cpp +++ b/src/shared/Util.cpp @@ -441,3 +441,23 @@ void vutf8printf(FILE *out, const char *str, va_list* ap) vfprintf(out, str, *ap); #endif } + +void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result) +{ + std::ostringstream ss; + for(uint32 i=0; i>((1-j)*4)); + char encodedNibble; + if(nibble < 0x0A) + encodedNibble = '0'+nibble; + else + encodedNibble = 'A'+nibble-0x0A; + ss << encodedNibble; + } + } + result = ss.str(); +} + diff --git a/src/shared/Util.h b/src/shared/Util.h index 522c917d9..d7f269fe1 100644 --- a/src/shared/Util.h +++ b/src/shared/Util.h @@ -289,4 +289,5 @@ void vutf8printf(FILE *out, const char *str, va_list* ap); bool IsIPAddress(char const* ipaddress); uint32 CreatePIDFile(const std::string& filename); +void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result); #endif diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 5fb4ec863..3eb469eee 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8449" + #define REVISION_NR "8450" #endif // __REVISION_NR_H__ -- 2.11.4.GIT