ClientTicket property extracted from a 2016 joinscript:
"ClientTicket":"5/14/2016 11:39:03 AM;hxgfjpUzqqdYH+A32XmSIUYQD0YIB6uw1+msiEq8A1Ymxv69JEkpqa0f4ppko6gN8gsQbOduUE/S0Wpu1+aNltDWzzyeNsULRuvpbePLzlKs5xrajpGGosjYB9wuXUa4WoBzMrvZ8mr4Takg107piXCCtFtnoBw1pn2CNIv+Fs8=;hwl1N/ApxZ+tNf9ccMmocz7VqeIfwWd4hZ8tR60Wyph3UXj+qjOt3IlYNq6+9jOB5+jY1pspSoh/3Xs863O+Ifo55b/RO2yL7g6Sk4Evqhn2/ImoXUSYQD5XjbKm3INa2Hd6oJFO2l1u1NaYvu+4shP6JMIBL8GMeRQYFEvJX2Q="
Snippet of code which handles grabbing signature from ticket/ClientTicket (on rccsecurity) after received from client (after received from joinscript request):
std::vector<std::string> s;
boost::split(s, ticket, boost::is_any_of(";"));
std::string signature = s[1]; // or s[2] if at second stage of ticket verifying
Crypt().verifySignatureBase64(signature);
Shortened version of Crypt::verifySignatureBase64()
:
bool Crypt::verifySignatureBase64(std::string signatureBase64)
{
bool result = false;
HCRYPTHASH hash;
if (!CryptCreateHash(context, CALG_SHA1, NULL, 0, &hash))
{
int signatureLen = Base64DecodeGetRequiredLength(signatureBase64.size());
BYTE* signature = (BYTE*)alloca(signatureLen);
ATL::Base64Decode(signatureBase64.c_str(), signatureBase64.size(), signature, &signatureLen);
BYTE signatureRev[10240];
for (int i=0; i<signatureLen; ++i)
signatureRev[i] = signature[signatureLen - i - 1];
if (CryptVerifySignature(hash, signatureRev, signatureLen, key, NULL, 0))
result = true;
}
::CryptDestroyHash(hash);
return result;
}
signatureRev[10240]
uses a fixed-size buffer, which lets you write over buffer if the given signature derived from the client exceeds the size.
exploiting this could lead to gaining access & control over the server running rcc.
One thing you could do is check if signatureLen
is beyond the allocated array size limit.
Alternatively, you could use a dynamically allocated array system like vectors:
std::vector<BYTE> signatureRev(signatureLen);
for (int i = 0; i < signatureLen; ++i)
signatureRev[i] = signature[signatureLen - i - 1];
todo.