Skip to content

Commit

Permalink
Merge pull request from GHSA-qjj3-q32v-fgqm
Browse files Browse the repository at this point in the history
PublishEndpoints: Verify GUIDs used as textures are valid texture GUIDs
  • Loading branch information
Beyley authored Dec 23, 2023
2 parents f472795 + af501a9 commit c20e6af
Show file tree
Hide file tree
Showing 10 changed files with 54,201 additions and 13 deletions.
21 changes: 15 additions & 6 deletions Refresh.GameServer/Endpoints/Game/Levels/PublishEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ public class PublishEndpoints : EndpointGroup
/// <param name="body">The level to verify</param>
/// <param name="user">The user that is attempting to upload</param>
/// <param name="logger">A logger instance</param>
/// <param name="guidChecker">The associated GuidCheckerService with the request</param>
/// <param name="game">The game the level is being submitted from</param>
/// <returns>Whether or not validation succeeded</returns>
private static bool VerifyLevel(GameLevelRequest body, GameUser user, Logger logger)
private static bool VerifyLevel(GameLevelRequest body, GameUser user, Logger logger, GuidCheckerService guidChecker, TokenGame game)
{
if (body.Title.Length > 256)
{
Expand All @@ -43,15 +45,22 @@ private static bool VerifyLevel(GameLevelRequest body, GameUser user, Logger log
return false;
}

//If the icon hash is a GUID hash, verify its a valid texture GUID
if (body.IconHash.StartsWith('g'))
{
if (!guidChecker.IsTextureGuid(game, long.Parse(body.IconHash.AsSpan()[1..])))
return false;
}

return true;
}

[GameEndpoint("startPublish", ContentType.Xml, HttpMethods.Post)]
[NullStatusCode(BadRequest)]
public SerializedLevelResources? StartPublish(RequestContext context, GameUser user, GameDatabaseContext database, GameLevelRequest body, CommandService command, IDataStore dataStore)
public SerializedLevelResources? StartPublish(RequestContext context, GameUser user, GameDatabaseContext database, GameLevelRequest body, CommandService command, IDataStore dataStore, GuidCheckerService guidChecker, Token token)
{
//If verifying the request fails, return null
if (!VerifyLevel(body, user, context.Logger)) return null;
if (!VerifyLevel(body, user, context.Logger, guidChecker, token.TokenGame)) return null;

List<string> hashes = new();
hashes.AddRange(body.XmlResources);
Expand All @@ -74,11 +83,11 @@ private static bool VerifyLevel(GameLevelRequest body, GameUser user, Logger log
}

[GameEndpoint("publish", ContentType.Xml, HttpMethods.Post)]
public Response PublishLevel(RequestContext context, GameUser user, Token token, GameDatabaseContext database, GameLevelRequest body, CommandService command, IDataStore dataStore)
public Response PublishLevel(RequestContext context, GameUser user, Token token, GameDatabaseContext database, GameLevelRequest body, CommandService command, IDataStore dataStore, GuidCheckerService guidChecker)
{
//If verifying the request fails, return null
if (!VerifyLevel(body, user, context.Logger)) return BadRequest;

if (!VerifyLevel(body, user, context.Logger, guidChecker, token.TokenGame)) return BadRequest;
GameLevel level = body.ToGameLevel(user);
level.GameVersion = token.TokenGame;

Expand Down
28 changes: 24 additions & 4 deletions Refresh.GameServer/Endpoints/Game/UserEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public SerializedUserList GetMultipleUsers(RequestContext context, GameDatabaseC

[GameEndpoint("updateUser", HttpMethods.Post, ContentType.Xml)]
[NullStatusCode(BadRequest)]
public string? UpdateUser(RequestContext context, GameDatabaseContext database, GameUser user, string body, IDataStore dataStore, Token token)
public string? UpdateUser(RequestContext context, GameDatabaseContext database, GameUser user, string body, IDataStore dataStore, Token token, GuidCheckerService guidChecker)
{
SerializedUpdateData? data = null;

Expand Down Expand Up @@ -96,10 +96,30 @@ public SerializedUserList GetMultipleUsers(RequestContext context, GameDatabaseC
return null;
}

if (data.IconHash != null && !data.IconHash.StartsWith("g") && !dataStore.ExistsInStore(data.IconHash))
if (data.IconHash != null)
{
database.AddErrorNotification("Profile update failed", "Your avatar failed to update because the asset was missing on the server.", user);
return null;
//If the icon is a GUID
if (data.IconHash.StartsWith('g'))
{
//Parse out the GUID
long guid = long.Parse(data.IconHash.AsSpan()[1..]);

//If its not a valid GUID, block the request
if(data.IconHash.StartsWith('g') && !guidChecker.IsTextureGuid(token.TokenGame, guid))
{
database.AddErrorNotification("Profile update failed", "Your avatar failed to update because the asset was an invalid GUID.", user);
return null;
}
}
else
{
//If the asset does not exist on the server, block the request
if (!dataStore.ExistsInStore(data.IconHash))
{
database.AddErrorNotification("Profile update failed", "Your avatar failed to update because the asset was missing on the server.", user);
return null;
}
}
}

if (data.PlanetsHash != null && !dataStore.ExistsInStore(data.PlanetsHash))
Expand Down
7 changes: 7 additions & 0 deletions Refresh.GameServer/Refresh.GameServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,11 @@
<OutputItemType>Analyzer</OutputItemType>
</ProjectReference>
</ItemGroup>

<ItemGroup>
<None Remove="Resources\lbp3.txt" />
<EmbeddedResource Include="Resources\lbp3.txt" />
<None Remove="Resources\lbpv.txt" />
<EmbeddedResource Include="Resources\lbpv.txt" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions Refresh.GameServer/RefreshGameServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ protected virtual void SetupServices()
this._server.AddService<MatchService>();
this._server.AddService<ImportService>();
this._server.AddService<DocumentationService>();
this._server.AddService<GuidCheckerService>();
this._server.AddAutoDiscover(serverBrand: $"{this._config!.InstanceName} (Refresh)",
baseEndpoint: GameEndpointAttribute.BaseRoute.Substring(0, GameEndpointAttribute.BaseRoute.Length - 1),
usesCustomDigestKey: true,
Expand Down
12 changes: 12 additions & 0 deletions Refresh.GameServer/Resources/ResourceHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Reflection;

namespace Refresh.GameServer.Resources;

public static class ResourceHelper
{
public static Stream StreamFromResource(string name)
{
Assembly assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceStream(name)!;
}
}
Loading

0 comments on commit c20e6af

Please sign in to comment.