Meep

pun rpc security

Jul 28th, 2021 (edited)
425
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Validates whether an RPC is malformed before attempting to run it
  2. // The optional parameter allows a rate limiter to be setup
  3.  
  4. public static bool ValidateRPC(EventData eventData, RateLimit limiter = null)
  5. {
  6.     if (eventData == null)
  7.         return false;
  8.  
  9.     // RPC should always be a Hashtable in unmodified PUN
  10.     // Classic PUN is the same layout as PUN 2.0 for the most part
  11.     if (!(eventData.CustomData is Hashtable tableRPC))
  12.         return false;
  13.  
  14.     // There should only be 3-4 elements in RPC ever
  15.     // One element will be missing if no parameters are sent
  16.     if (tableRPC.Count != 4 && tableRPC.Count != 3)
  17.         return false;
  18.  
  19.     if ((tableRPC.ContainsKey((byte)5) || // RPC code
  20.         tableRPC.ContainsKey((byte)3)) && // Substitute RPC name
  21.         tableRPC.ContainsKey((byte)2)  && // Servertime
  22.         tableRPC.ContainsKey((byte)0))    // PhotonView ID
  23.     {
  24.         // We check whether the data inside of the hashtable matches the required types
  25.         // Remember that if the rpc byte code doesn't exist, the name could be used as a substitute
  26.         if (!(tableRPC.ContainsKey((byte)5) && tableRPC[(byte)5] is byte))
  27.             if (!(tableRPC.ContainsKey((byte)3) && tableRPC[(byte)3] is string))
  28.                 return false;
  29.  
  30.         // This is the name we'll use in the ratelimiter down below
  31.         var name = (tableRPC.ContainsKey((byte)3) ? tableRPC[(byte)3] : tableRPC[(byte)5]).ToString();
  32.  
  33.         if (!(tableRPC[(byte)2] is int))
  34.             return false;
  35.         if (!(tableRPC[(byte)0] is int))
  36.             return false;
  37.  
  38.         // If no params are sent the params key won't exist
  39.         // But if it does exist, we should verify it properly
  40.         if (tableRPC.ContainsKey((byte)4))
  41.             if (!(tableRPC[(byte)4] is object[] param) || param.Length > 10)
  42.                 return false;
  43.  
  44.         // We do anti-spam after it's been validated
  45.         // Validating first might catch out erroneous events quicker
  46.         // If someone sends a malformed event it should warrant a serverlogic disconnect
  47.         if (limiter != null)
  48.             return limiter.IsSafeToRun($"RPC_{name}", eventData.Sender);
  49.  
  50.         return true;
  51.     }
  52.  
  53.     return false;
  54. }
RAW Paste Data