How to encrypt URLs in ASP.NET MVC?

I need to encrypt URLs in my ASP.NET MVC application.

Do I need to write code on the Global Page in the route collection to encrypt all URLs?

+3
source share
3 answers

Bad idea to encrypt URL. Period.

You may wonder why I say this.

I was working on an application for a company that encrypted its URLs. This was a web form application. From a single URL, it was almost impossible to tell which part of the code I clicked to cause this problem. Because of the dynamic nature of invoking web form controls, you just needed to know how the software would work. It was very unpleasant.

Add to this that there was no role-based authorization in the application. All of this was based on URL encryption. If you can decrypt the URL (which, if it can be encrypted, you can decrypt it), then you could enter another encrypted URL and impersonate another user. I do not say this simply, but it can happen.

, URL-? , ? . URL- . , , URL ( ).

, , , . SSN , -.

, , , , .

, URL-, , [Authorize], ASP.NET MVC.

+7

URL, , . URL-? .

/ URL- ( ), Mads Kristensen " HttpModule .

context_BeginRequest, MVC. if, , url "aspx".

, ( VB) .

, , jQuery/Ajax. , , .

+4

, BTW, , MVC, , , II7 II6. .

II6

-, web.config (root, , View).

 <system.web>
    <httpModules>
      <add name="URIHandler" type="URIHandler" />
    </httpModules>

II7

web.config (root, , View).

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="URIHandler" />
      <add name="URIHandler" type="URIHandler" />
    </modules>

. .

. , , , - URIHandler.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Diagnostics.CodeAnalysis;

public class URIHandler : IHttpModule
    {
        #region IHttpModule members
        public void Dispose()
        {
        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
        }
        #endregion

        private const string PARAMETER_NAME = "enc=";
        private const string ENCRYPTION_KEY = "key";

        private void context_BeginRequest(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            //if (context.Request.Url.OriginalString.Contains("aspx") && context.Request.RawUrl.Contains("?"))
            if (context.Request.RawUrl.Contains("?"))
            {
                string query = ExtractQuery(context.Request.RawUrl);
                string path = GetVirtualPath();

                if (query.StartsWith(PARAMETER_NAME, StringComparison.OrdinalIgnoreCase))
                {
                    // Decrypts the query string and rewrites the path.
                    string rawQuery = query.Replace(PARAMETER_NAME, string.Empty);
                    string decryptedQuery = Decrypt(rawQuery);
                    context.RewritePath(path, string.Empty, decryptedQuery);
                }
                else if (context.Request.HttpMethod == "GET")
                {
                    // Encrypt the query string and redirects to the encrypted URL.
                    // Remove if you don't want all query strings to be encrypted automatically.
                    string encryptedQuery = Encrypt(query);
                    context.Response.Redirect(path + encryptedQuery);
                }
            }
        }

        /// <summary>
        /// Parses the current URL and extracts the virtual path without query string.
        /// </summary>
        /// <returns>The virtual path of the current URL.</returns>
        private static string GetVirtualPath()
        {
            string path = HttpContext.Current.Request.RawUrl;
            path = path.Substring(0, path.IndexOf("?"));
            path = path.Substring(path.LastIndexOf("/") + 1);
            return path;
        }

        /// <summary>
        /// Parses a URL and returns the query string.
        /// </summary>
        /// <param name="url">The URL to parse.</param>
        /// <returns>The query string without the question mark.</returns>
        private static string ExtractQuery(string url)
        {
            int index = url.IndexOf("?") + 1;
            return url.Substring(index);
        }

        #region Encryption/decryption

        /// <summary>
        /// The salt value used to strengthen the encryption.
        /// </summary>
        private readonly static byte[] SALT = Encoding.ASCII.GetBytes(ENCRYPTION_KEY.Length.ToString());

        /// <summary>
        /// Encrypts any string using the Rijndael algorithm.
        /// </summary>
        /// <param name="inputText">The string to encrypt.</param>
        /// <returns>A Base64 encrypted string.</returns>
        [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
        public static string Encrypt(string inputText)
        {
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            byte[] plainText = Encoding.Unicode.GetBytes(inputText);
            PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(ENCRYPTION_KEY, SALT);

            using (ICryptoTransform encryptor = rijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16)))
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(plainText, 0, plainText.Length);
                        cryptoStream.FlushFinalBlock();
                        return "?" + PARAMETER_NAME + Convert.ToBase64String(memoryStream.ToArray());
                    }
                }
            }
        }

        /// <summary>
        /// Decrypts a previously encrypted string.
        /// </summary>
        /// <param name="inputText">The encrypted string to decrypt.</param>
        /// <returns>A decrypted string.</returns>
        [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
        public static string Decrypt(string inputText)
        {
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            byte[] encryptedData = Convert.FromBase64String(inputText);
            PasswordDeriveBytes secretKey = new PasswordDeriveBytes(ENCRYPTION_KEY, SALT);

            using (ICryptoTransform decryptor = rijndaelCipher.CreateDecryptor(secretKey.GetBytes(32), secretKey.GetBytes(16)))
            {
                using (MemoryStream memoryStream = new MemoryStream(encryptedData))
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                    {
                        byte[] plainText = new byte[encryptedData.Length];
                        int decryptedCount = cryptoStream.Read(plainText, 0, plainText.Length);
                        return Encoding.Unicode.GetString(plainText, 0, decryptedCount);
                    }
                }
            }
        }
        #endregion
    }

NameSpace.

URL, '?'. "enc", .

, App_Start App_Code, " ".

.

Credits:

https://www.codeproject.com/questions/1036066/how-to-hide-url-parameter-asp-net-mvc

https://msdn.microsoft.com/en-us/library/aa719858(v=vs.71).aspx

HttpModule Init

# ,

https://stackoverflow.com/questions/1391060/httpmodule-with-asp-net-mvc-not- being called

+1
source

Source: https://habr.com/ru/post/1780749/


All Articles