Decrypt WebResource.axd URL generated on HTTPS instance

2.3k views Asked by At

I have below mentioned code:

string urlEncodedData = URL.Text;

byte[] encryptedData = HttpServerUtility.UrlTokenDecode(urlEncodedData);

Type machineKeySection = typeof(System.Web.Configuration.MachineKeySection);
Type[] paramTypes = new Type[] { typeof(bool), typeof(byte[]), typeof(byte[]), typeof(int), typeof(int) };
MethodInfo encryptOrDecryptData = machineKeySection.GetMethod("EncryptOrDecryptData", BindingFlags.Static | BindingFlags.NonPublic, null, paramTypes, null);

try
{
     byte[] decryptedData = (byte[])encryptOrDecryptData.Invoke(null, new object[] { false, encryptedData, null, 0, encryptedData.Length });
     string decrypted = Encoding.UTF8.GetString(decryptedData);

     decryptedLabel.BackColor = Color.Lime;
     decryptedLabel.Text = decrypted;
}
catch (TargetInvocationException)
{
     decryptedLabel.BackColor = Color.Red;
     decryptedLabel.Text = "Error decrypting data. Are you running your page on the same server and inside the same application as the web resource URL that was generated?";
}

It Decrypts and tell me details about webresource. locally it works fine. enter image description here

But on production it always gives me below message from catch block

Error decrypting data. Are you running your page on the same server and inside the same application as the web resource URL that was generated?

The only difference I have is production being on HTTPS. Is above code valid for HTTPS also, or do I have to make change(s) to it?

1

There are 1 answers

0
yezior On

I also was using this code snippet to decrypt webresource.axd parameter, but lately it stopped working.

Maybe it's change of framework to 4.5, because I found this comment in .net sources - Page class, method DecryptString http://referencesource.microsoft.com/#System.Web/UI/Page.cs,18cf7b1fe99faea6

if (AspNetCryptoServiceProvider.Instance.IsDefaultProvider) {
            // ASP.NET 4.5 Crypto DCR: Go through the new AspNetCryptoServiceProvider
            // if we're configured to do so.
            ICryptoService cryptoService = AspNetCryptoServiceProvider.Instance.GetCryptoService(purpose, CryptoServiceOptions.CacheableOutput);
            clearData = cryptoService.Unprotect(protectedData);
        }
        else {
            // If we're not configured to go through the new crypto routines,
            // fall back to the standard MachineKey crypto routines.
#pragma warning disable 618 // calling obsolete methods
            clearData = MachineKeySection.EncryptOrDecryptData(fEncrypt: false, buf: protectedData, modifier: null, start: 0, length: protectedData.Length, useValidationSymAlgo: false, useLegacyMode: false, ivType: IVType.Hash);
#pragma warning restore 618 // calling obsolete methods
        } 

Are you sure the only difference is http and https, maybe framework version also?

Nevertheless I used method DecryptString instead EncryptOrDecryptData and below code is working for me. You can check if this working for you too :)

private static string Decrypt(string webResourceParameter)
    {
        var purposeType = Type.GetType("System.Web.Security.Cryptography.Purpose, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");

        if (purposeType == null)
            return null;

        try
        {
            var purpose = Activator.CreateInstance(purposeType, "AssemblyResourceLoader.WebResourceUrl");

            const BindingFlags decryptFlags = BindingFlags.NonPublic | BindingFlags.Static;
            var decryptString = typeof (Page).GetMethod("DecryptString", decryptFlags);

            var decrypt = decryptString.Invoke(null, new[] {webResourceParameter, purpose}) as string;
            return decrypt;
        }
        catch (Exception ex)
        {
            return null;
        }
    }