Function at fault: FSocketSteam::RecvFrom (https://github.com/EpicGames/UnrealEngine/blob/c3caf7b6bf12ae4c8e09b606f10a09776b4d1f38/Engine/Plugins/Online/OnlineSubsystemSteam/Source/Private/SocketsSteam.cpp#L157)
This function returns the 'MessageSize' argument from ISteamNetworking ::ReadP2PPacket - This is the total size of the packet even if the input buffer was too small for the received data and it was truncated. The function which calls FSocketSteam::RecvFrom will then use this returned size value to perform it's respective action on the buffer. For example, if a game client has a maximum packet buffer size of 1200 bytes but receives a 950000 byte packet, only 1200 bytes of that packet will be copied to the buffer by ISteamNetworking::ReadP2PPacket, but 'MessageSize' will be returned as 950000.
The result of this will be out-of-bounds read and subsequent crash from the calling function when it attempts to process the received data using the returned size from FSocketSteam::RecvFrom which is potentially much greater than the actual maximum buffer size.
(Note 950000 bytes is just for the sake of example, as long as the size exceeds the maximum input buffer size the exploit will occur)
This exploit is very straightforward to reproduce, it’s as simple as sending a very large packet via ISteamNetworking::SendP2PPacket with an P2PSendType of “k_EP2PSendReliable”, a large cubData argument, and a large enough buffer.
The contents of the packet do not matter in this instance, as it’s the size alone that causes the game to crash. Also note that k_EP2PSendReliable has a maximum size of 1MB, whereas k_EP2PSendUnreliable only has a maximum size of 1200 bytes.
The following will send a 950,000 byte packet to a user targeted by their Steam ID, and reproduce the exploit described in this report.
SteamNetworking()->SendP2PPacket(SteamIDTarget, &Buffer, 0xE7EF0, k_EP2PSendReliable, iChannel);
([Link Removed]) ([Link Removed])
The attacker will crash the game of the person who receives the packet if the out-of-bounds read is significant enough to read inaccessible memory.
This exploit will exist in all Unreal Engine games that use this function.
1) Add code as shown in Example to somewhere in the Steam socket code
2) Run game and connect to a client
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-117500 in the post.
1 |
Component | UE - Online |
---|---|
Target Fix | 4.27.1 |
Created | Jun 7, 2021 |
---|---|
Resolved | Sep 28, 2021 |
Updated | Dec 1, 2022 |