mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2025-02-05 07:51:13 +00:00
Don't send login final hashes to everyone
Someone thought it was a good fucking idea to make logins NetXCmds. NetXCmds are sent to everyone however. Thankfully logins are two passes. And the second pass uses a salt based on the playernum. Therefore, in order to actually make use of the final hash, you'd have to be the same playernum as who originally sent it. Still a stupid exploit. P.S. The netcode is LOL XD by VincyTM -Telos
This commit is contained in:
parent
016f1fe533
commit
91502f1499
4 changed files with 74 additions and 70 deletions
|
@ -44,6 +44,7 @@
|
||||||
#include "lzf.h"
|
#include "lzf.h"
|
||||||
#include "lua_script.h"
|
#include "lua_script.h"
|
||||||
#include "lua_hook.h"
|
#include "lua_hook.h"
|
||||||
|
#include "md5.h"
|
||||||
|
|
||||||
#ifdef CLIENT_LOADINGSCREEN
|
#ifdef CLIENT_LOADINGSCREEN
|
||||||
// cl loading screen
|
// cl loading screen
|
||||||
|
@ -116,6 +117,9 @@ static UINT8 resynch_local_inprogress = false; // WE are desynched and getting p
|
||||||
static UINT8 player_joining = false;
|
static UINT8 player_joining = false;
|
||||||
UINT8 hu_resynching = 0;
|
UINT8 hu_resynching = 0;
|
||||||
|
|
||||||
|
UINT8 adminpassmd5[MD5_LEN];
|
||||||
|
boolean adminpasswordset = false;
|
||||||
|
|
||||||
// Client specific
|
// Client specific
|
||||||
static ticcmd_t localcmds;
|
static ticcmd_t localcmds;
|
||||||
static ticcmd_t localcmds2;
|
static ticcmd_t localcmds2;
|
||||||
|
@ -3760,6 +3764,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
XBOXSTATIC INT32 netconsole;
|
XBOXSTATIC INT32 netconsole;
|
||||||
XBOXSTATIC tic_t realend, realstart;
|
XBOXSTATIC tic_t realend, realstart;
|
||||||
XBOXSTATIC UINT8 *pak, *txtpak, numtxtpak;
|
XBOXSTATIC UINT8 *pak, *txtpak, numtxtpak;
|
||||||
|
XBOXSTATIC UINT8 finalmd5[MD5_LEN];/* Well, it's the cool thing to do? */
|
||||||
FILESTAMP
|
FILESTAMP
|
||||||
|
|
||||||
txtpak = NULL;
|
txtpak = NULL;
|
||||||
|
@ -3958,6 +3963,33 @@ FILESTAMP
|
||||||
textcmd[0] += (UINT8)netbuffer->u.textcmd[0];
|
textcmd[0] += (UINT8)netbuffer->u.textcmd[0];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PT_LOGIN:
|
||||||
|
CONS_Printf("I received LOGIN\n");
|
||||||
|
if (client)
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifndef NOMD5
|
||||||
|
if (doomcom->datalength < MD5_LEN)/* ignore partial sends */
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!adminpasswordset)
|
||||||
|
{
|
||||||
|
CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[netconsole]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the final pass to compare with the sent md5
|
||||||
|
D_MD5PasswordPass(adminpassmd5, MD5_LEN, va("PNUM%02d", netconsole), &finalmd5);
|
||||||
|
|
||||||
|
if (!memcmp(netbuffer->u.md5sum, finalmd5, MD5_LEN))
|
||||||
|
{
|
||||||
|
CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[netconsole]);
|
||||||
|
COM_BufInsertText(va("promote %d\n", netconsole)); // do this immediately
|
||||||
|
}
|
||||||
|
else
|
||||||
|
CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[netconsole]);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
case PT_NODETIMEOUT:
|
case PT_NODETIMEOUT:
|
||||||
case PT_CLIENTQUIT:
|
case PT_CLIENTQUIT:
|
||||||
if (client)
|
if (client)
|
||||||
|
@ -4841,3 +4873,29 @@ tic_t GetLag(INT32 node)
|
||||||
{
|
{
|
||||||
return gametic - nettics[node];
|
return gametic - nettics[node];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest)
|
||||||
|
{
|
||||||
|
#ifdef NOMD5
|
||||||
|
(void)buffer;
|
||||||
|
(void)len;
|
||||||
|
(void)salt;
|
||||||
|
memset(dest, 0, 16);
|
||||||
|
#else
|
||||||
|
XBOXSTATIC char tmpbuf[256];
|
||||||
|
const size_t sl = strlen(salt);
|
||||||
|
|
||||||
|
if (len > 256-sl)
|
||||||
|
len = 256-sl;
|
||||||
|
|
||||||
|
memcpy(tmpbuf, buffer, len);
|
||||||
|
memmove(&tmpbuf[len], salt, sl);
|
||||||
|
//strcpy(&tmpbuf[len], salt);
|
||||||
|
len += strlen(salt);
|
||||||
|
if (len < 256)
|
||||||
|
memset(&tmpbuf[len],0,256-len);
|
||||||
|
|
||||||
|
// Yes, we intentionally md5 the ENTIRE buffer regardless of size...
|
||||||
|
md5_buffer(tmpbuf, 256, dest);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -70,6 +70,9 @@ typedef enum
|
||||||
PT_NODETIMEOUT, // Packet sent to self if the connection times out.
|
PT_NODETIMEOUT, // Packet sent to self if the connection times out.
|
||||||
PT_RESYNCHING, // Packet sent to resync players.
|
PT_RESYNCHING, // Packet sent to resync players.
|
||||||
// Blocks game advance until synched.
|
// Blocks game advance until synched.
|
||||||
|
|
||||||
|
PT_LOGIN, // Login attempt from the client.
|
||||||
|
|
||||||
#ifdef NEWPING
|
#ifdef NEWPING
|
||||||
PT_PING, // Packet sent to tell clients the other client's latency to server.
|
PT_PING, // Packet sent to tell clients the other client's latency to server.
|
||||||
#endif
|
#endif
|
||||||
|
@ -398,6 +401,7 @@ typedef struct
|
||||||
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
|
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
|
||||||
filetx_pak filetxpak; // 139 bytes
|
filetx_pak filetxpak; // 139 bytes
|
||||||
clientconfig_pak clientcfg; // 136 bytes
|
clientconfig_pak clientcfg; // 136 bytes
|
||||||
|
UINT8 md5sum[MD5_LEN];
|
||||||
serverinfo_pak serverinfo; // 1024 bytes
|
serverinfo_pak serverinfo; // 1024 bytes
|
||||||
serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...)
|
serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...)
|
||||||
askinfo_pak askinfo; // 61 bytes
|
askinfo_pak askinfo; // 61 bytes
|
||||||
|
@ -526,5 +530,10 @@ void D_ResetTiccmds(void);
|
||||||
tic_t GetLag(INT32 node);
|
tic_t GetLag(INT32 node);
|
||||||
UINT8 GetFreeXCmdSize(void);
|
UINT8 GetFreeXCmdSize(void);
|
||||||
|
|
||||||
|
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest);
|
||||||
|
|
||||||
extern UINT8 hu_resynching;
|
extern UINT8 hu_resynching;
|
||||||
|
|
||||||
|
extern UINT8 adminpassmd5[MD5_LEN];
|
||||||
|
extern boolean adminpasswordset;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,13 +34,13 @@
|
||||||
#include "p_spec.h"
|
#include "p_spec.h"
|
||||||
#include "m_cheat.h"
|
#include "m_cheat.h"
|
||||||
#include "d_clisrv.h"
|
#include "d_clisrv.h"
|
||||||
|
#include "d_net.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "d_main.h"
|
#include "d_main.h"
|
||||||
#include "m_random.h"
|
#include "m_random.h"
|
||||||
#include "f_finale.h"
|
#include "f_finale.h"
|
||||||
#include "filesrch.h"
|
#include "filesrch.h"
|
||||||
#include "mserv.h"
|
#include "mserv.h"
|
||||||
#include "md5.h"
|
|
||||||
#include "z_zone.h"
|
#include "z_zone.h"
|
||||||
#include "lua_script.h"
|
#include "lua_script.h"
|
||||||
#include "lua_hook.h"
|
#include "lua_hook.h"
|
||||||
|
@ -143,7 +143,6 @@ static void Command_Clearscores_f(void);
|
||||||
// Remote Administration
|
// Remote Administration
|
||||||
static void Command_Changepassword_f(void);
|
static void Command_Changepassword_f(void);
|
||||||
static void Command_Login_f(void);
|
static void Command_Login_f(void);
|
||||||
static void Got_Login(UINT8 **cp, INT32 playernum);
|
|
||||||
static void Got_Verification(UINT8 **cp, INT32 playernum);
|
static void Got_Verification(UINT8 **cp, INT32 playernum);
|
||||||
static void Got_Removal(UINT8 **cp, INT32 playernum);
|
static void Got_Removal(UINT8 **cp, INT32 playernum);
|
||||||
static void Command_Verify_f(void);
|
static void Command_Verify_f(void);
|
||||||
|
@ -437,7 +436,6 @@ void D_RegisterServerCommands(void)
|
||||||
|
|
||||||
// Remote Administration
|
// Remote Administration
|
||||||
COM_AddCommand("password", Command_Changepassword_f);
|
COM_AddCommand("password", Command_Changepassword_f);
|
||||||
RegisterNetXCmd(XD_LOGIN, Got_Login);
|
|
||||||
COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin
|
COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin
|
||||||
COM_AddCommand("promote", Command_Verify_f);
|
COM_AddCommand("promote", Command_Verify_f);
|
||||||
RegisterNetXCmd(XD_VERIFIED, Got_Verification);
|
RegisterNetXCmd(XD_VERIFIED, Got_Verification);
|
||||||
|
@ -2652,35 +2650,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
||||||
// Attempts to make password system a little sane without
|
// Attempts to make password system a little sane without
|
||||||
// rewriting the entire goddamn XD_file system
|
// rewriting the entire goddamn XD_file system
|
||||||
//
|
//
|
||||||
#include "md5.h"
|
|
||||||
static void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest)
|
|
||||||
{
|
|
||||||
#ifdef NOMD5
|
|
||||||
(void)buffer;
|
|
||||||
(void)len;
|
|
||||||
(void)salt;
|
|
||||||
memset(dest, 0, 16);
|
|
||||||
#else
|
|
||||||
XBOXSTATIC char tmpbuf[256];
|
|
||||||
const size_t sl = strlen(salt);
|
|
||||||
|
|
||||||
if (len > 256-sl)
|
|
||||||
len = 256-sl;
|
|
||||||
memcpy(tmpbuf, buffer, len);
|
|
||||||
memmove(&tmpbuf[len], salt, sl);
|
|
||||||
//strcpy(&tmpbuf[len], salt);
|
|
||||||
len += strlen(salt);
|
|
||||||
if (len < 256)
|
|
||||||
memset(&tmpbuf[len],0,256-len);
|
|
||||||
|
|
||||||
// Yes, we intentionally md5 the ENTIRE buffer regardless of size...
|
|
||||||
md5_buffer(tmpbuf, 256, dest);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BASESALT "basepasswordstorage"
|
#define BASESALT "basepasswordstorage"
|
||||||
static UINT8 adminpassmd5[16];
|
|
||||||
static boolean adminpasswordset = false;
|
|
||||||
|
|
||||||
void D_SetPassword(const char *pw)
|
void D_SetPassword(const char *pw)
|
||||||
{
|
{
|
||||||
|
@ -2718,7 +2688,6 @@ static void Command_Login_f(void)
|
||||||
// If we have no MD5 support then completely disable XD_LOGIN responses for security.
|
// If we have no MD5 support then completely disable XD_LOGIN responses for security.
|
||||||
CONS_Alert(CONS_NOTICE, "Remote administration commands are not supported in this build.\n");
|
CONS_Alert(CONS_NOTICE, "Remote administration commands are not supported in this build.\n");
|
||||||
#else
|
#else
|
||||||
XBOXSTATIC UINT8 finalmd5[16];
|
|
||||||
const char *pw;
|
const char *pw;
|
||||||
|
|
||||||
if (!netgame)
|
if (!netgame)
|
||||||
|
@ -2738,47 +2707,15 @@ static void Command_Login_f(void)
|
||||||
pw = COM_Argv(1);
|
pw = COM_Argv(1);
|
||||||
|
|
||||||
// Do the base pass to get what the server has (or should?)
|
// Do the base pass to get what the server has (or should?)
|
||||||
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &finalmd5);
|
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &netbuffer->u.md5sum);
|
||||||
|
|
||||||
// Do the final pass to get the comparison the server will come up with
|
// Do the final pass to get the comparison the server will come up with
|
||||||
D_MD5PasswordPass(finalmd5, 16, va("PNUM%02d", consoleplayer), &finalmd5);
|
D_MD5PasswordPass(netbuffer->u.md5sum, MD5_LEN, va("PNUM%02d", consoleplayer), &netbuffer->u.md5sum);
|
||||||
|
|
||||||
CONS_Printf(M_GetText("Sending login... (Notice only given if password is correct.)\n"));
|
CONS_Printf(M_GetText("Sending login... (Notice only given if password is correct.)\n"));
|
||||||
|
|
||||||
SendNetXCmd(XD_LOGIN, finalmd5, 16);
|
netbuffer->packettype = PT_LOGIN;
|
||||||
#endif
|
HSendPacket(servernode, true, 0, MD5_LEN);
|
||||||
}
|
|
||||||
|
|
||||||
static void Got_Login(UINT8 **cp, INT32 playernum)
|
|
||||||
{
|
|
||||||
#ifdef NOMD5
|
|
||||||
// If we have no MD5 support then completely disable XD_LOGIN responses for security.
|
|
||||||
(void)cp;
|
|
||||||
(void)playernum;
|
|
||||||
#else
|
|
||||||
UINT8 sentmd5[16], finalmd5[16];
|
|
||||||
|
|
||||||
READMEM(*cp, sentmd5, 16);
|
|
||||||
|
|
||||||
if (client)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!adminpasswordset)
|
|
||||||
{
|
|
||||||
CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[playernum]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the final pass to compare with the sent md5
|
|
||||||
D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", playernum), &finalmd5);
|
|
||||||
|
|
||||||
if (!memcmp(sentmd5, finalmd5, 16))
|
|
||||||
{
|
|
||||||
CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[playernum]);
|
|
||||||
COM_BufInsertText(va("promote %d\n", playernum)); // do this immediately
|
|
||||||
}
|
|
||||||
else
|
|
||||||
CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[playernum]);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,8 +125,8 @@ typedef enum
|
||||||
XD_ADDPLAYER, // 10
|
XD_ADDPLAYER, // 10
|
||||||
XD_TEAMCHANGE, // 11
|
XD_TEAMCHANGE, // 11
|
||||||
XD_CLEARSCORES, // 12
|
XD_CLEARSCORES, // 12
|
||||||
XD_LOGIN, // 13
|
// UNUSED 13 (Because I don't want to change these comments)
|
||||||
XD_VERIFIED, // 14
|
XD_VERIFIED = 14,//14
|
||||||
XD_RANDOMSEED, // 15
|
XD_RANDOMSEED, // 15
|
||||||
XD_RUNSOC, // 16
|
XD_RUNSOC, // 16
|
||||||
XD_REQADDFILE, // 17
|
XD_REQADDFILE, // 17
|
||||||
|
|
Loading…
Reference in a new issue