This topic has been locked
RFC: Changes to the A2S_INFO protocol
NOTE: This post contains information that is now out-of-date! To avoid confusion, please see this updated post:

https://steamcommunity.com/discussions/forum/14/2974028351344359625/




Hello!

Over the next couple of months we will be releasing some changes to how servers and clients using steamclent.dll handle the venerable Source engine A2S_INFO message used by the server browser. This includes the Steam client server browser, all Source engine games, and all Steam games using the ISteamMatchmaking API. The purpose of these changes is a long overdue fix for a reflection attack vulnerability.

This email is to let you know what those plans are and to solicit your feedback. Fixing the vulnerability requires changing the protocol and will necessarily break existing third party utilities that speak the protocol.

Currently, the A2S_INFO packet looks like this:

4 bytes: 0xFFFFFFFF
1 byte: 0x54 (A2S_INFO packet type identifier)
20 bytes: "Source Engine Query\0"

UPDATED. After testing it was revealed that padding the packet is triggering some anti-DDoS filters. So we are required to use a challenge.

  • Option 1: Pad the message with zeros, so that the request is larger than the reply. The passes size is TBD, but it will probably be at least 800 bytes, and perhaps as high as 1200. Feedback is requested concerning this size.
  • Option 2: Secure the message using a 4-byte anti-spoofing challenge, similar to the method that exists for the A2S_PLAYER and A2S_RULES messages.

Note that both options produce a packet that is acceptable to the current code in steamclient.dll. However, any custom handlers might have stricter behavior, and will need to be updated to be aware than “extra” data might appear after the end of the magic string in packets from legitimate clients.

  1. First, we will release a new Steam client that knows how to talk to a server that demand a challenge. Since it takes time for Steam client updates to roll out to all Steam users, and for third parties to change their code to make queries in the new format, we will not change the server to require the new format by default. However, the server code will be updated to look for an environment variable that can be used to opt into the new, stricter behavior, and require a challenge. This is so that third parties can test their clients to make sure they are compliant with the new server code.
  2. As more clients upgrade to the new code and third party tools are updated to send queries in the new format, server operators may elect to opt into the new behavior at their discretion using the environment variable.
  3. After some time has passed (and we have posted several warnings on this mailing list), we will ship a new steamclient.dll that has the strict behavior enabled by default. A different environment variable can be used to use the older, more permissive behaviour.

If you have any concerns or feedback about this change, please reply here. After feedback has been collected and details finalized, I’ll post again with more technical details about the changes that are going to be made.
Last edited by FletcherDunnValve; Dec 7, 2020 @ 3:59pm
< >
Showing 1-15 of 20 comments
I think padding 0 bytes is better since this way you can easily filter it even before it reaches srcds.
helloer Nov 17, 2020 @ 1:46am 
Hi Fletcher, thank you very much for doing this!

Originally posted by FletcherDunnValve:
Hello!
Over the next couple of months we will be releasing some changes to how servers and clients using steamclent.dll handle the venerable Source engine A2S_INFO message used by the server browser. This includes the Steam client server browser, all Source engine games, and all Steam games using the ISteamMatchmaking API. The purpose of these changes is a long overdue fix for a reflection attack vulnerability.
Does it also include GoldSrc games such as Counter-Strike 1.6?

Option 1: Pad the message with zeros, so that the request is larger than the reply. The passes size is TBD, but it will probably be at least 800 bytes, and perhaps as high as 1200. Feedback is requested concerning this size.
The more, the better. QUIC uses 1200 bytes for that purpose

If you have any concerns or feedback about this change, please reply here. After feedback has been collected and details finalized, I’ll post again with more technical details about the changes that are going to be made.

Would it be also possible to extend other connectionless packets with padding, for example: "qconnect" in CS:GO and A2S_PLAYER, A2S_RULES? It could help with DoS attacks against the gameservers.

Imagine a CS:GO server that receives 200 thousand "qconnect" spoofed packets per second, from random addresses - it's almost impossible to distinguish these from legit users that want to connect to the gameserver. Blocking or rate-limiting these will just make it unplayable so we implemented our own logic to filter these packets, however, it's still very cheap for attackers to send thousands of such packets because of small payload, by padding them it would require a lot more bandwidth to achieve the same results.


(BTW: Since CS:GO uses GameNetworkingSockets, maybe you could make use of its own challenge system for establishing connections: https://github.com/ValveSoftware/GameNetworkingSockets/blob/56092ec7e73acb32ed18ca99505fb8f3cd160da3/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_udp.cpp#L1308 )

FletcherDunnValve  [developer] Nov 17, 2020 @ 8:59am 
Does it also include GoldSrc games such as Counter-Strike 1.6?

Yes.

A2S_PLAYER, A2S_RULES?

These packets are already protected by an anti-spoofing challenge. Do you think more is needed? I desire to make as few changes as possible, although if there is significant benefit, since we will be forcing all clients to touch code already, requiring a minimum size for these packets would be relatively easy.

Since CS:GO uses GameNetworkingSockets, maybe you could make use of its own challenge system for establishing connections

Eventually we may change the networking code on CSGO so that direct UDP connectivity (not relayed through SDR) goes through GameNetworkingSockets. Right now, we have decided not to do this work.
Last edited by FletcherDunnValve; Nov 17, 2020 @ 9:08am
FletcherDunnValve  [developer] Nov 17, 2020 @ 10:21am 
Based on feedback here and on the hlds mailing list, I have updated the proposal. The new proposal is for all A2S_INFO, A2S_PLAYER, and A2S_INFO packets to be padded by the client with zeros to 1200 bytes. The server (or any middleboxes closer to the edge) will drop any such packets < 1200 bytes.
Last edited by FletcherDunnValve; Nov 17, 2020 @ 10:24am
FletcherDunnValve  [developer] Nov 18, 2020 @ 4:43pm 
A Steam client beta released today has these changes.
https://steamcommunity.com/groups/SteamClientBeta/announcements/detail/2896339990496271925

Not mentioned in those patch notes (because it is only relevant for a small set of people, reading this thread) is that you can activate the new, stricter message handling on the gameserver by setting the environment variable STEAM_GAMESERVER_MIN_CONNECTIONLESS_PACKET_SIZE=1200
Last edited by FletcherDunnValve; Nov 18, 2020 @ 4:44pm
Can someone explain this technical stuff to me in laymans terms?
KarnickelKanone Nov 19, 2020 @ 12:29am 
Originally posted by Abdul Jakul Bulbolosis Salsalani:
Can someone explain this technical stuff to me in laymans terms?
computer makes things and we get internet
xPaw Nov 19, 2020 @ 12:47am 
Will old servers correctly handle being sent 1200 bytes of nulls? E.g if you request info, players and rules from it.

Deco Nov 19, 2020 @ 2:23am 
Originally posted by Abdul Jakul Bulbolosis Salsalani:
Can someone explain this technical stuff to me in laymans terms?
Essentially, the current steamclient.dll package which is used to forge network connection requests is vulnerable to a reflection based attack. The specific attack isn't mentioned, however the most likely candidate is a reflective based DoS attack based on Fletcher's description of the attack usage. This relies on creating spoofed packet requests to a server (fake requests) to flood a connection enough to force it to shutdown.

The change with this will force the client to only send greater than 1200 byte requests (eventually); this is an effective patch, as the spoofed requests rely on sending short form vector attacks to the server to overload it, say, 30 byte or lower requests, and multiple requests stacking on top of each other. This is because servers often times do not have a minimum validation packet floor for various reasons, making them vulnerable to attack. The attack also goes by another name: RangeAmp.



Originally posted by xPaw:
Will old servers correctly handle being sent 1200 bytes of nulls? E.g if you request info, players and rules from it.
This client change will default to sending >1200 bytes, however as noted in the main post, will still allow for sending <1200 byte requests. Once the release goes to the public branch, and has been mass adopted, it will then eventually be forced by the server to only accept >1200 byte packets, rejecting all byte requests under this threshold. This won't be forced till sometime next year, to allow servers to adjust to the change. I would expect this applies to all packet requests, as exceptions allow a route for exploitation.
Last edited by Deco; Nov 19, 2020 @ 2:27am
KarnickelKanone Nov 19, 2020 @ 2:58am 
Originally posted by Deco:
Originally posted by Abdul Jakul Bulbolosis Salsalani:
Can someone explain this technical stuff to me in laymans terms?
Essentially, the current steamclient.dll package which is used to forge network connection requests is vulnerable to a reflection based attack. The specific attack isn't mentioned, however the most likely candidate is a reflective based DoS attack based on Fletcher's description of the attack usage. This relies on creating spoofed packet requests to a server (fake requests) to flood a connection enough to force it to shutdown.

The change with this will force the client to only send greater than 1200 byte requests (eventually); this is an effective patch, as the spoofed requests rely on sending short form vector attacks to the server to overload it, say, 30 byte or lower requests, and multiple requests stacking on top of each other. This is because servers often times do not have a minimum validation packet floor for various reasons, making them vulnerable to attack. The attack also goes by another name: RangeAmp.



Originally posted by xPaw:
Will old servers correctly handle being sent 1200 bytes of nulls? E.g if you request info, players and rules from it.
This client change will default to sending >1200 bytes, however as noted in the main post, will still allow for sending <1200 byte requests. Once the release goes to the public branch, and has been mass adopted, it will then eventually be forced by the server to only accept >1200 byte packets, rejecting all byte requests under this threshold. This won't be forced till sometime next year, to allow servers to adjust to the change. I would expect this applies to all packet requests, as exceptions allow a route for exploitation.
You Sir, are a genius and have a big brain.
FletcherDunnValve  [developer] Nov 19, 2020 @ 10:23am 
Originally posted by xPaw:
Will old servers correctly handle being sent 1200 bytes of nulls? E.g if you request info, players and rules from it.

Yes, I have confirmed by looking at the code (and also actually, you know, *testing* against live servers) that servers accept packets with "extra" data that they do not understand.

If there are middleboxes proxying these requests, or any other custom code, they may be applying more strict rules and could be broken. But the code in steamclient.dll ignores extra data, as far as I can tell.
Koraktor Nov 19, 2020 @ 11:21am 
Originally posted by FletcherDunnValve:
[…] The new proposal is for all A2S_INFO, A2S_PLAYER, and A2S_INFO packets to be padded by the client with zeros to 1200 bytes. […]

This should read A2S_INFO, A2S_PLAYER and A2S_RULES, right?
FletcherDunnValve  [developer] Nov 19, 2020 @ 12:58pm 
Originally posted by Koraktor:
This should read A2S_INFO, A2S_PLAYER and A2S_RULES, right?
Yes, thanks.
less than three Nov 20, 2020 @ 3:21am 
Please update wiki page with new information.
Jessie Nov 20, 2020 @ 1:27pm 
Originally posted by Deco:
Originally posted by Abdul Jakul Bulbolosis Salsalani:
Can someone explain this technical stuff to me in laymans terms?
The change with this will force the client to only send greater than 1200 byte requests (eventually); this is an effective patch, as the spoofed requests rely on sending short form vector attacks to the server to overload it, say, 30 byte or lower requests, and multiple requests stacking on top of each other.

If it's a reflection, it's not the server that gets overloaded - it's the reflected target that is being spoofed who will be overloaded.. the attacker sends small packets spoofed as the target, and the server sends a much larger 'response' to the target - so the attacker both remains anonymous and does not require as much bandwidth.
Having a minimum packet size will prevent / reduce the amplification by the server and render the exploit pretty much useless.
< >
Showing 1-15 of 20 comments
Per page: 15 30 50