• [PSA] Exploit for servers linked with MySQL
    90 replies, posted
[QUOTE=syl0r;51617851]I really don't see why you would implement this with sockets when (almost) all servers that are affected by this are servers that use a database to sync data. So all of them would have a mysql module. Additionally your socket implementation isn't even safe. You are using UDP when this is clearly a terrible choice in this case. There is literally no guarantee that the UDP packet will ever be received by your server so there is still a way that players can join. (zoox beat me to it...) If you scale this up to more than two servers being linked you'll end up having to ask every other server if the player can join while it is always one transaction in the mysql version. The likelihood of even one of those requests failing is then a problem.[/QUOTE] This and the above are valid points. I never guaranteed that my implementation was safe in its current format and it's also true that UDP doesn't guarantee that the target recipient will indeed receive it. However it works as a general PoC (and UDP is an easier example to provide compared to TCP). [QUOTE=Teddi Orange;51607081]Again, with sockets it's easy That should be[B] enough to get you started.[/B] I'd recommend passing a token around as well as UDP isn't secure enough on its own.[/QUOTE] You also don't need to send a request to ask if the player can join - you just fire out a message saying "x is joining the server, drop them on your end if they're currently there". Again to make this clear as people cannot seem to comprehend - I'm suggesting an alternative here which in its entirety is valid. I'm not stating this as a defacto method. The ideal solution re transactions has been provided already - but this is going to take time to implement across the board for various people therefore short-term solutions (which also give people a reason to branch out and try new things) are required.
Stoned, in my implementation you recommended using CheckPassword. This has a risk: Imagine joining server B "from" server A (i.e. you were in A when starting to join server B). The disconnect query from server A might run [I]after[/I] the check query from server B, causing server B to think the player is still in A. With PlayerAuthed there's quite a bit more time between leaving A and joining B. Could this be a real problem?
I believe you solve that issue by doing something similarly to this addon and keeping timestamps up-to-date and comparing against those as well. Under those circumstances CheckPassword could be better because it'll prevent the player slot from being taken for x amount of time, that's its benefit over PlayerAuthed
[QUOTE=KingofBeast;51618048]I believe you solve that issue by doing something similarly to this addon and keeping timestamps up-to-date and comparing against those as well. Under those circumstances CheckPassword could be better because it'll prevent the player slot from being taken for x amount of time, that's its benefit over PlayerAuthed[/QUOTE] A query every 0.25 seconds is very, [I]very[/I] risky. Some regular amount of gmod lag and you're over the 0.5 mark. I know earlier kicking is generally better, but I'd rather abstain if it causes issues with cross joining.
I am fairly certain there is a race condition in the current version of the addon. If a player joins both servers at exactly the same time the check [URL="https://github.com/SuperiorServers/NoMultirun/blob/master/lua/autorun/server/no_multirun.lua#L24"]here [/URL] should go through without any issues. If they then both enter this [URL="https://github.com/SuperiorServers/NoMultirun/blob/master/lua/autorun/server/no_multirun.lua#L32"]line[/URL] at the same time there is nothing stopping both of them getting in since the updatesession query is only started in the callback. You could very easily solve this issue in one query using an insert with a key. [CODE] INSERT INTO sessions(steamid64, time, server) VALUES(?, UNIX_TIMESTAMP(), ' .. nomr.serverid .. ');') [/CODE] If an error occurs in this statement either something went wrong (which means it's not safe to let the player in anyways) or there is already an entry with that steamid (then they are already in another server). If there is not an error however, the row was inserted successfully and the player couldn't have been on another server. The check sessions query is completely redundant at that point and can probably be removed.
Just wanted to slip in and give props to Stoned & King for taking the time to PSA the exploit and offer a fix. It's really generous/helpful from you guys. People like this keep the Gmod community running and healthy for this long. :) Thanks again.
[QUOTE=MonkeysLP;51620912]Just wanted to slip in and give props to Stoned & King for taking the time to PSA the exploit and offer a fix. It's really generous/helpful from you guys. People like this keep the Gmod community running and healthy for this long. :) Thanks again.[/QUOTE] You guys had a fix for the popular RCON/sv_allowupload exploit for a while before it was widely used to steal server information and spread a virus but you guys never once mentioned how you fixed it. I even added Drew and you when I found out that you guys had an early fix but you never responded to my messages and my friend request was ignored by Drew. I can understand keeping a neat HUD effect or weapon to yourselves to be unique but you clearly weren't putting any effort to help the community there.
[QUOTE=YourStalker;51621580]You guys had a fix for the popular RCON/sv_allowupload exploit for a while before it was widely used to steal server information and spread a virus but you guys never once mentioned how you fixed it. I even added Drew and you when I found out that you guys had an early fix but you never responded to my messages and my friend request was ignored by Drew. I can understand keeping a neat HUD effect or weapon to yourselves to be unique but you clearly weren't putting any effort to help the community there.[/QUOTE] I literally have no idea what you're talking about. We never "discovered" any exploit. Drew developed actively specifically (and almost exclusively) things I designed and requested. He wasn't particularly (and still isn't as far as I know?) active on Facepunch or in the gmod community as a whole. If he ever fixed an exploit for LifePunch, it was because I pointed it to him and if I pointed it to him, it's because I found it on FacePunch. I know I didn't and I certainly doubt Drew found an exploit and actively tried to "hide" it from the community. At worst, maybe he didn't bother sharing it because he didn't particularly care, but it's very doubtfully with any malicious intentions, it wasn't his type.
[QUOTE=YourStalker;51621580]You guys had a fix for the popular RCON/sv_allowupload exploit for a while before it was widely used to steal server information and spread a virus but you guys never once mentioned how you fixed it. I even added Drew and you when I found out that you guys had an early fix but you never responded to my messages and my friend request was ignored by Drew. I can understand keeping a neat HUD effect or weapon to yourselves to be unique but you clearly weren't putting any effort to help the community there.[/QUOTE] All in the past, besides Monkeys has only had the design say-so in LP's gamemodes, hardly any of the technical side of it; Drew might have patched it unbeknownst to him; who told you they might have had a fix anyway? It was only as simple as disabling uploads/downloads.
[QUOTE=YourStalker;51621580]You guys had a fix for the popular RCON/sv_allowupload exploit for a while before it was widely used to steal server information and spread a virus but you guys never once mentioned how you fixed it. I even added Drew and you when I found out that you guys had an early fix but you never responded to my messages and my friend request was ignored by Drew. I can understand keeping a neat HUD effect or weapon to yourselves to be unique but you clearly weren't putting any effort to help the community there.[/QUOTE] That had been around since 2007+ CS:S. Fixes and major exploits involving the bug were floating around in other Source communities for at least five years prior to Garry's Mod's case. Even if they did have a fix that they were "hiding," I can guarantee it was not private in the slightest. [editline]5th January 2017[/editline] [QUOTE=KingofBeast;51629290]All in the past, besides Monkeys has only had the design say-so in LP's gamemodes, hardly any of the technical side of it; Drew might have patched it unbeknownst to him; who told you they might have had a fix anyway? It was only as simple as disabling uploads/downloads.[/QUOTE] That only fixes the spray injection and server cfg stealing -- the cough DLL spreader was a bit more of a complicated fix, which involved having a dupe DLL to make the script think the server already had it.
Maybe I was jumping to conclusions but I know for sure Willox saying that LP was protected already from cough cough and the rcon exploit while still having sprays working, something had to be patched. He ended up having to pick a different server to start the exploit from.
[QUOTE=YourStalker;51629770]Maybe I was jumping to conclusions but I know for sure Willox saying that LP was protected already from cough cough and the rcon exploit while still having sprays working, something had to be patched. He ended up having to pick a different server to start the exploit from.[/QUOTE] sv_allowupload 0 with Spraymon covers one of your points.
[QUOTE=code_gs;51629813]sv_allowupload 0 with Spraymon covers one of your points.[/QUOTE] Well yeah ofc now this isn't an issue considering that Metastruct, Willox, and Metaman all released patches for it and alternatives like Spraymon exist but back then no such thing existed.
To save you all time with potentially wasted effort, I would advise that people in this thread read about and try to understand the "CAP theorem". I hope that doing so will help you understand the hard limitations that exist in regard to what you're all trying to 'solve'. Some of the solutions presented here are not solutions, in some cases, due to the above reality. You might be able to find a way around X, but then what about Y?....................... There are ways of working with CAP to achieve specific results for your particular problem. You'll have to figure that out with the above in mind.
[QUOTE=YourStalker;51630668]Well yeah ofc now this isn't an issue considering that Metastruct, Willox, and Metaman all released patches for it and alternatives like Spraymon exist but back then no such thing existed.[/QUOTE] Spraymon has been around since GM12
[QUOTE=StonedPenguin;51604374] 2. Join two linked servers with pointshop, spend all your points on both servers effectively doubling your points. [/QUOTE] You can actually duplicate pointshop points but you have to be very delicate about it or you could end up accidentally wiping half or all the points you just duped, my assumption is how pointshop/mysql is handling it. I tested out my theory on 3 different community's that had pointshop linked. But if you wish to dupe pointshop points you're going to have to expand on the amount of accounts under your control, you can't just use "Two mulitrun Gmods"
[QUOTE=BigBadWilly;51635916]You can actually duplicate pointshop points but you have to be very delicate about it or you could end up accidentally wiping half or all the points you just duped, my assumption is how pointshop/mysql is handling it. I tested out my theory on 3 different community's that had pointshop linked. But if you wish to dupe pointshop points you're going to have to expand on the amount of accounts under your control, you can't just use "Two mulitrun Gmods"[/QUOTE] Exploit pointshop points by an sql method using 2 different accounts. [B][I][U]2 different accounts[/U][/I][/B] Genius... Also I didn't really follow with everyone arguing on here about how the best way to patch it would be. To me it seems (although I have never used SQL I can guess what you can do in there) the best way would just have a t/f value set to someone's steam id in the SQL and whenever someone joins, set their steam id to True, prevent them from joining any of your other linked servers. Unless of course you are trying to fix the problem at the root, which seems like a waste of time since it is so much easier, and faster dare I say?, to just do it the way I stated. (Btw if someone already made this solution then I wasn't paying attention.)
[QUOTE=Teddi Orange;51606518]A sockets based system would be trivial and solve the problem without any downsides. Player joins server - server queries other servers to check if they have the same player on there - take appropriate action.[/QUOTE] I like this solution the best. Doing this through SQL is just silly. Player joins one server, game.KickID on the others. [QUOTE=FPtje;51608994]Demanding server owners to install and configure socket modules for something that not only can be, but already has been implemented for the things they already have installed and configured is utterly ridiculous.[/QUOTE] They don't have to do anything. If they don't want to use an addon to protect their servers against an exploit, nobody is forcing them. I don't even know why you're trying to solve this in a gamemode. This is something that should be done in an addon. They've already uploaded a .dll and configured their SQL before, they can do the exact same thing with an addon that fixes this exploit.
[QUOTE=sannys;51636064]I like this solution the best. Doing this through SQL is just silly. Player joins one server, game.KickID on the others.[/QUOTE] The socket solution is completely flawed and riddled with things that can go wrong (UDP....). I really don't understand why people here are so amazed by sockets and think that they are a solution to all problems. Using sockets creates more problems than it solves in many cases. If you use mysql on the other hand (which obviously uses sockets internally btw.) you have many guarantees that sockets do not offer by themselves. Why do you want to reimplement things that mysql offers solid solutions for (and probably get it wrong)?
[QUOTE=sannys;51636064] They don't have to do anything. If they don't want to use an addon to protect their servers against an exploit, nobody is forcing them. [/QUOTE] If they don't want to use a socket addon to protect their servers then their servers remain unprotected. That situation is undesirable. I can live with servers that don't [I]update[/I], but I cannot with good conscious demand server owners to install a separate addon with a separate module to fix an exploit that exists in DarkRP. [B]I[/B] have [U]full[/U] responsibility over DarkRP suffering from this exploit. This responsibility [U]cannot[/U] reasonably be shoved to server owners. The reason why DarkRP suffers from this exploit is because it doesn't properly account for concurrent updates. Ideally I should have implemented proper transactions to update money values the moment I decided to provide support for MySQL. The only reason I'm not properly fixing it now is because of the breaking API changes it would bring (ply:canAfford would have to use callbacks).
[QUOTE=syl0r;51636102]The socket solution is completely flawed and riddled with things that can go wrong (UDP....). I really don't understand why people here are so amazed by sockets and think that they are a solution to all problems. Using sockets creates more problems than it solves in many cases. If you use mysql on the other hand (which obviously uses sockets internally btw.) you have many guarantees that sockets do not offer by themselves. Why do you want to reimplement things that mysql offers solid solutions for (and probably get it wrong)?[/QUOTE] Then just use TCP??? Other than complaining about UDP, you haven't actually said anything about sockets. If they are riddled with flaws then maybe you should provide some examples. I didn't say sockets are the perfect solution to the problem, I said I like them best. With sockets you don't have to constantly poll a database, which I find stupid to do. If you want information at a moment's notice, direct and nearly instant communication between the two parties can be done with sockets. Have you heard of the law of the instrument? Where if you work with hammers all day everything looks like a nail? That's you shoehorning SQL here in lieu of another technology that is better suited for the job.
[QUOTE=sannys;51636157 ]If they are riddled with flaws then maybe you should provide some examples. [/QUOTE] Firstly the solution presented doesn't even work. If you tell other servers to kick a player then what happens if that connection fails? Then there's no guarantee that the same player isn't on another server. The correct way is to ask other servers if the player is on another server and then deny the player locally. Now to some of the reasons why sockets suck in this case: [B]1. You need an additional library[/B] Why make people download yet another library even though the problem can be solved (better) using a library they already have. [B]2. All servers need to know all other servers[/B] To add an additional server you have to change the code of all servers involved. Of course you could solve this dynamically by using mysql to share the IP addresses but why the fuck even use sockets at all then. With mysql it would be possible to add a server dynamically without even notifying any of the other servers. No code updates, not even mysql polling necessary. [B]3. You need to open ports (unless they are all on the same machine)[/B] This isn't going to be easy for most people. Especially when it's a server hosted by a a gameserver companly like NFO. I doubt they'd be allowed to use an additional port. With mysql your server never functions as a host so you don't have to open any ports. [B]4. You need additional authentication[/B] Otherwise anyone can kick players from your server. If you just use a secret password then it can still be sniffed because it's not encrypted. So to properly solve this issue you'd have to use encryption, which requires using yet another module. [B]5. It scales poorly[/B] The socket solution requires each server to tell EVERY other server that a player has joined. So if you run 100 servers on the same database you'd need to tell 100 other servers that a player has joined. Now imagine just one of those 100 connections failing, it'd be a disaster. With mysql you have one server that synchronizes all of the others and thus mysql always only requires exactly one query when a player joins and one query when a player leaves. [B]6. Sockets aren't faster than mysql[/B] With sockets you need to ask every other server, which means that you have to wait at least the worst ping time to any of the other servers before you get a response. With mysql you only have to wait the ping time between the game and mysql server. [B]7. What if one of the other servers goes down?[/B] I don't think there's any solution to this. I am sure there are plenty more reasons why the sockets solution is undesirable, but I hope these suffice.
[QUOTE=syl0r;51636239]Firstly the solution presented doesn't even work. If you tell other servers to kick a player then what happens if that connection fails? Then there's no guarantee that the same player isn't on another server. The correct way is to ask other servers if the player is on another server and then deny the player locally.[/QUOTE] No, the correct way would be to kick the player off of all other servers if they're connecting to the local one, which game.KickID accomplishes. [quote]1. You need an additional library Why make people download yet another library even though the problem can be solved (better) using a library they already have.[/quote] What is wrong with that if it does the job better? [quote]2. All servers need to know all other servers To add an additional server you have to change the code of all servers involved. Of course you could solve this dynamically by using mysql to share the IP addresses but why the fuck even use sockets at all then. With mysql it would be possible to add a server dynamically without even notifying any of the other servers. No code updates, not even mysql polling necessary.[/quote] This is the only point you make that has any merit at all. The thing is, most people use only a handful of servers, which makes this very easy to manage. [quote]3. You need to open ports (unless they are all on the same machine) This isn't going to be easy for most people. Especially when it's a server hosted by a a gameserver companly like NFO. I doubt they'd be allowed to use an additional port. With mysql your server never functions as a host so you don't have to open any ports.[/quote] Or you could just use the unused srcds ports? [quote]4. You need additional authentication Otherwise anyone can kick players from your server. If you just use a secret password then it can still be sniffed because it's not encrypted. So to properly solve this issue you'd have to use encryption, which requires using yet another module.[/quote] No, you don't need encryption, and if people are at the point of sniffing packets on your server you already fucked up. [quote]5. It scales poorly The socket solution requires each server to tell EVERY other server that a player has joined. So if you run 100 servers on the same database you'd need to tell 100 other servers that a player has joined. Now imagine just one of those 100 connections failing, it'd be a disaster. With mysql you have one server that synchronizes all of the others and thus mysql always only requires exactly one query when a player joins and one query when a player leaves.[/quote] Completely unrealistic. Why would you even bother using this as an example? Can I say that SQL sucks cause the SQL server could be under extreme load from thousands of clients connecting at the same time? [quote]6. Sockets aren't faster than mysql With sockets you need to ask every other server, which means that you have to wait at least the worst ping time to any of the other servers before you get a response. With mysql you only have to wait the ping time between the game and mysql server.[/quote] Yes, they are. There is no database querying involved. And I don't know why you have this idea that your server needs to [B]ask[/B] other servers if the player is on that server. If they connect to 1 server, you boot them off all of them. There is no asking involved. [quote]7. What if one of the other servers goes down? I don't think there's any solution to this.[/quote] What if the SQL server goes down?
[QUOTE=sannys;51636348]No, the correct way would be to kick the player off of all other servers if they're connecting to the local one, which game.KickID accomplishes. [/QUOTE] Unfortunately you failed to understand the problem. If you kick them from other servers then that relies on the connection to the other servers actually going through. You can't guarantee this at all. Therefore the solution is unreliable and useless. [QUOTE=sannys;51636348] Or you could just use the unused srcds ports? [/QUOTE] I don't know what port you are talking about exactly. 27015 is being used for both tcp and udp. No other tcp port needs to be opened by the hosting company. [QUOTE=sannys;51636348] No, you don't need encryption, and if people are at the point of sniffing packets on your server you already fucked up. [/QUOTE] Just like almost all other points sockets do it [U]worse[/U] than mysql, so why not choose the superior method? [QUOTE=sannys;51636348] Completely unrealistic. Why would you even bother using this as an example? Can I say that SQL sucks cause the SQL server could be under extreme load from thousands of clients connecting at the same time? [/QUOTE] It might be unrealistic that someone would use 100 servers. The point is that it scales badly, even using 3 servers is already much more complex than just using two. If you take mysql in the same example however there is almost no difference between using two or 100 servers. [QUOTE=sannys;51636348] Yes, they are. There is no database querying involved. And I don't know why you have this idea that your server needs to [B]ask[/B] other servers if the player is on that server. If they connect to 1 server, you boot them off all of them. There is no asking involved. [/QUOTE] [URL="https://puu.sh/tejlt/73b43fc2f3.png"]Do you even know how fast database querying is?[/URL] We are talking about microseconds here... The ping time is always the limiting factor when you have really small and simple tables. Maybe you don't have to ask and wait for a response but you'd have to at least massively adjust the PoC then. [QUOTE=sannys;51636348] What if the SQL server goes down?[/QUOTE] The only thing that would happen is that no one can join that server anymore (if the query errors the player gets kicked). That's not an issue since the server needs mysql to run properly anyways
[QUOTE=syl0r;51636467]Unfortunately you failed to understand the problem. If you kick them from other servers then that relies on the connection to the other servers actually going through. You can't guarantee this at all. Therefore the solution is unreliable and useless.[/QUOTE] You can't [B]guarantee[/B] anything, dude. You can't guarantee your SQL server will be up. You keep putting sockets in this position that is guaranteed to fail 100% of the time in these made up scenarios and then you argue that SQL is superior when it would fail just the same. [quote]I don't know what port you are talking about exactly. 27015 is being used for both tcp and udp. No other tcp port needs to be opened by the hosting company.[/quote] Look at the server list and you will see just how many 27xxx ports servers use where xxx is not 015, or an entirely different range is used instead. You are not limited to that 1 port. [quote]Do you even know how fast database querying is? We are talking about microseconds here... The ping time is always the limiting factor when you have really small and simple tables.[/quote] I don't mean the execution of the query, I mean the process of constantly asking the database for changes. The burden is on you to keep asking. The database will not let you know when something has happened. This is not the case with sockets, where data flows freely between the two servers. Just on the page before this there was talks about querying the database every quarter of a second. Lol. I can't respond to your other points because I think this whole conversation is getting nowhere, so I'll leave it at this.
[QUOTE=syl0r;51636467]I don't know what port you are talking about exactly. 27015 is being used for both tcp and udp. No other tcp port needs to be opened by the hosting company.[/QUOTE] Servers also require 27016 and 27017, although, 27017 is unused now that SourceTV no longer exists, so that'd work perfectly.
[QUOTE=sannys;51636539]You can't [B]guarantee[/B] anything, dude. You can't guarantee your SQL server will be up. You keep putting sockets in this position that is guaranteed to fail 100% of the time in these made up scenarios and then you argue that SQL is superior when it would fail just the same. [/QUOTE] That is such a weak argument. I can guarantee many things when using mysql and I know exactly what to do if the mysql server is not up (reject players). [QUOTE=sannys;51636539] Look at the server list and you will see just how many 27xxx ports servers use where xxx is not 015, or an entirely different range is used instead. You are not limited to that 1 port. [/QUOTE] That's irrelevant. You need an additional TCP port or it will not work. Not all hosting companies give you an additional tcp port. I mean why would they. [QUOTE] I don't mean the execution of the query, I mean the process of constantly asking the database for changes. The burden is on you to keep asking. The database will not let you know when something has happened. This is not the case with sockets, where data flows freely between the two servers. Just on the page before this there was talks about querying the database every quarter of a second. Lol. [/QUOTE] Then you misunderstand the concept of this addon. It requires one query when a player joins and one query when a player leaves (the addon currently requires a bit more than that but it could be done in one). Even if you did poll the database constantly though, that's not a problem at all with mysql servers. This just shows that the socket solution is worse overall than the mysql solution. You have yet to name a single argument as to why the mysql solution is bad or wouldn't work except for queries taking a long time, which is false. [QUOTE=code_gs;51636547]Servers also require 27016 and 27017, although, 27017 is unused now that SourceTV no longer exists, so that'd work perfectly.[/QUOTE] [URL="https://developer.valvesoftware.com/wiki/Source_Dedicated_Server"]No they don't.[/URL]
[QUOTE=syl0r;51636596]That is such a weak argument. I can guarantee many things when using mysql and I know exactly what to do if the mysql server is not up (reject players). That's irrelevant. You need an additional TCP port or it will not work. Not all hosting companies give you an additional tcp port. I mean why would they. Then you misunderstand the concept of this addon. It requires one query when a player joins and one query when a player leaves (the addon currently requires a bit more than that but it could be done in one). Even if you did poll the database constantly though, that's not a problem at all with mysql servers. This just shows that the socket solution is worse overall than the mysql solution. You have yet to name a single argument as to why the mysql solution is bad or wouldn't work except for queries taking a long time, which is false. [URL="https://developer.valvesoftware.com/wiki/Source_Dedicated_Server"]No they don't.[/URL][/QUOTE] That page is incorrect. Try starting up a server with only 27015 forwarded and you'll see the message. It could be 27017 or 27021 -- can't recall.
I don't think no one is actually stupid enough to implement the sockets idea. That or some were and they figured out the problems with it before we heard of them.
[QUOTE=code_gs;51636653]That page is incorrect. Try starting up a server with only 27015 forwarded and you'll see the message. It could be 27017 or 27021 -- can't recall.[/QUOTE] From what I have seen in the past, only the port your server uses (27015 etc) and between 26900:27000 are used for VAC Authentication.
Sorry, you need to Log In to post a reply to this thread.