ASP.NET Misconfiguration: Use of Identity Impersonation

Description

ASP.NET Misconfiguration: Use of Identity Impersonation is a vulnerability where an ASP.NET application is configured to run with impersonated credentials, potentially granting it unnecessary or excessive privileges. Identity impersonation allows the application to execute operations under a different security context than its default, which can be the client's identity or a specifically configured account. When misconfigured, this can result in the application having access to resources beyond what is required, violating the principle of least privilege.

Risk

Impersonation misconfiguration creates significant security risks. When applications impersonate clients, each user request executes with that user's full permissions, potentially accessing resources the application shouldn't use. If impersonating a highly privileged account, any vulnerability in the application becomes a path to system compromise. Attackers exploiting application vulnerabilities inherit the impersonated identity's permissions. Misconfigured impersonation can also lead to privilege escalation attacks where low-privilege users gain access to administrative resources. Audit logging becomes complicated as actions are attributed to the impersonated identity rather than the application.

Solution

Apply the principle of least privilege when configuring ASP.NET application identity. Avoid using identity impersonation unless specifically required by the application architecture. If impersonation is necessary, ensure the impersonated account has only the minimum permissions required. Use specific service accounts with limited privileges rather than impersonating administrative accounts. Configure impersonation at the most granular level possible—per action rather than application-wide. Implement proper authorization checks in application code regardless of impersonation settings. Regularly audit impersonated account permissions and application configuration.

Common Consequences

ImpactDetails
Access ControlScope: Access Control

Gain Privileges or Assume Identity - Misconfigured impersonation can allow attackers to escalate privileges or access resources beyond the application's intended scope by inheriting the impersonated identity's permissions.

Example Code

Vulnerable Code

<!-- Vulnerable: web.config with impersonation enabled -->
<configuration>
    <system.web>
        <!-- Vulnerable: Impersonating a highly privileged account -->
        <identity impersonate="true"
                  userName="DOMAIN\Administrator"
                  password="AdminPassword123!" />

        <!-- This grants the application full administrator privileges -->
    </system.web>
</configuration>
<!-- Vulnerable: Impersonating client identity -->
<configuration>
    <system.web>
        <authentication mode="Windows" />

        <!-- Vulnerable: Impersonating all client identities -->
        <identity impersonate="true" />

        <!-- Each request runs with the caller's full permissions -->
        <!-- If a domain admin browses, the app has admin rights -->
    </system.web>
</configuration>
// Vulnerable: Code-level impersonation with excessive privileges
using System.Security.Principal;

public class VulnerableFileService
{
    // Vulnerable: Impersonating an admin account for file operations
    public void ProcessFile(string filePath)
    {
        // Vulnerable: Hardcoded admin credentials
        const string domain = "COMPANY";
        const string username = "FileAdmin";
        const string password = "FileAdmin123!";

        using (WindowsImpersonationContext context = ImpersonateUser(domain, username, password))
        {
            // Vulnerable: All file operations run as admin
            // Even if user shouldn't have access to these files
            File.ReadAllText(filePath);
            File.WriteAllText(filePath + ".processed", "...");
            File.Delete(filePath);
        }
    }

    // Vulnerable: Impersonation helper
    private WindowsImpersonationContext ImpersonateUser(string domain, string username, string password)
    {
        IntPtr token = IntPtr.Zero;

        // LogonUser - vulnerable: using admin credentials
        if (LogonUser(username, domain, password,
            LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token))
        {
            WindowsIdentity identity = new WindowsIdentity(token);
            return identity.Impersonate();
        }

        throw new Exception("Impersonation failed");
    }

    [DllImport("advapi32.dll")]
    private static extern bool LogonUser(string userName, string domain,
        string password, int logonType, int logonProvider, ref IntPtr token);
}
// Vulnerable: Controller using impersonation without proper checks
public class VulnerableAdminController : Controller
{
    [HttpGet]
    public ActionResult ReadSystemFile(string path)
    {
        // Vulnerable: Impersonating admin to bypass file permissions
        using (var impersonation = new ImpersonationHelper("SYSTEM"))
        {
            // User-controlled path + system impersonation = vulnerability
            string content = System.IO.File.ReadAllText(path);
            return Content(content);
        }
    }

    [HttpPost]
    public ActionResult ModifyConfig(string setting, string value)
    {
        // Vulnerable: Admin impersonation for any config change
        using (var impersonation = new ImpersonationHelper("Administrator"))
        {
            // User can modify any system configuration
            Registry.SetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\MyApp", setting, value);
            return Ok();
        }
    }
}
<%-- Vulnerable: Page with impersonation for database access --%>
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Security.Principal" %>

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        // Vulnerable: Impersonating database admin for queries
        WindowsIdentity dbAdmin = new WindowsIdentity("DOMAIN\\DBAdmin");
        using (dbAdmin.Impersonate())
        {
            // All database operations run as DBAdmin
            // Even for low-privilege users
            string userInput = Request.QueryString["query"];
            ExecuteQuery(userInput);  // SQL injection + admin access = disaster
        }
    }
</script>

Fixed Code

<!-- Fixed: web.config with minimal privileges -->
<configuration>
    <system.web>
        <authentication mode="Windows" />

        <!-- Fixed: No impersonation - run as application pool identity -->
        <!-- Application pool configured with minimal service account -->
        <identity impersonate="false" />

        <authorization>
            <!-- Fixed: Explicit authorization rules -->
            <deny users="?" />
            <allow users="*" />
        </authorization>
    </system.web>

    <!-- Fixed: Specific folders with targeted access -->
    <location path="admin">
        <system.web>
            <authorization>
                <allow roles="COMPANY\AppAdmins" />
                <deny users="*" />
            </authorization>
        </system.web>
    </location>
</configuration>
// Fixed: Service using proper authorization instead of impersonation
using System.Security.Principal;

public class SecureFileService
{
    private readonly IAuthorizationService _authService;
    private readonly ILogger _logger;

    public SecureFileService(IAuthorizationService authService, ILogger logger)
    {
        _authService = authService;
        _logger = logger;
    }

    public void ProcessFile(string filePath, IPrincipal user)
    {
        // Fixed: Check authorization before processing
        if (!_authService.CanAccessFile(user, filePath))
        {
            _logger.LogWarning("Unauthorized file access attempt: {User} -> {Path}",
                user.Identity.Name, filePath);
            throw new UnauthorizedAccessException("Access denied to file");
        }

        // Fixed: Validate file path
        if (!IsValidFilePath(filePath))
        {
            throw new ArgumentException("Invalid file path");
        }

        // Fixed: Run with application identity (least privilege)
        // Application pool identity has only necessary folder access
        File.ReadAllText(filePath);
        File.WriteAllText(filePath + ".processed", "...");
    }

    private bool IsValidFilePath(string path)
    {
        // Fixed: Whitelist allowed directories
        string fullPath = Path.GetFullPath(path);
        string allowedDir = Path.GetFullPath(@"C:\AppData\Processing");

        return fullPath.StartsWith(allowedDir, StringComparison.OrdinalIgnoreCase);
    }
}
// Fixed: Limited impersonation only when absolutely necessary
public class SecureResourceService
{
    private readonly SecureString _servicePassword;
    private readonly string _serviceDomain = "COMPANY";
    private readonly string _serviceUsername = "LimitedServiceAccount";

    // Fixed: Service account with minimal permissions
    // Only has read access to specific network share

    public byte[] ReadNetworkResource(string resourcePath, IPrincipal requestingUser)
    {
        // Fixed: Validate user authorization first
        if (!IsAuthorizedToAccessResource(requestingUser, resourcePath))
        {
            throw new UnauthorizedAccessException();
        }

        // Fixed: Validate resource path is within allowed scope
        if (!IsAllowedResourcePath(resourcePath))
        {
            throw new ArgumentException("Invalid resource path");
        }

        // Fixed: Limited impersonation with minimal service account
        using (var impersonation = CreateLimitedImpersonation())
        {
            // Service account can only read from specific share
            return File.ReadAllBytes(resourcePath);
        }
    }

    private IDisposable CreateLimitedImpersonation()
    {
        // Fixed: Use a specific, limited service account
        // Not Administrator, not client identity
        return new NetworkCredential(
            _serviceUsername,
            _servicePassword,
            _serviceDomain
        ).Impersonate();
    }

    private bool IsAllowedResourcePath(string path)
    {
        // Fixed: Only allow access to specific network share
        return path.StartsWith(@"\\fileserver\approved-share\",
            StringComparison.OrdinalIgnoreCase);
    }

    private bool IsAuthorizedToAccessResource(IPrincipal user, string path)
    {
        // Fixed: Check user's role and resource permissions
        return user.IsInRole("ResourceReaders") &&
               CheckResourcePermission(user.Identity.Name, path);
    }
}
// Fixed: Controller with proper authorization
[Authorize]
public class SecureAdminController : Controller
{
    private readonly IFileService _fileService;
    private readonly IConfigService _configService;

    // Fixed: No impersonation - use proper authorization
    [HttpGet]
    [Authorize(Roles = "AppAdmins")]  // Fixed: Role-based access
    public ActionResult ReadConfigFile()
    {
        // Fixed: Application reads its own config
        // No impersonation needed
        string configPath = Server.MapPath("~/App_Data/config.xml");
        string content = System.IO.File.ReadAllText(configPath);
        return Content(content);
    }

    [HttpPost]
    [Authorize(Roles = "AppAdmins")]
    [ValidateAntiForgeryToken]  // Fixed: CSRF protection
    public ActionResult ModifyConfig(string setting, string value)
    {
        // Fixed: Validate input
        if (!IsValidSetting(setting) || !IsValidValue(value))
        {
            return BadRequest("Invalid configuration");
        }

        // Fixed: Use application's configuration service
        // No registry access, no impersonation
        _configService.UpdateSetting(setting, value, User.Identity.Name);

        return Ok();
    }

    private bool IsValidSetting(string setting)
    {
        // Fixed: Whitelist allowed settings
        var allowedSettings = new[] { "Theme", "Language", "PageSize" };
        return allowedSettings.Contains(setting);
    }

    private bool IsValidValue(string value)
    {
        // Fixed: Validate value format
        return !string.IsNullOrEmpty(value) && value.Length <= 100;
    }
}
<!-- Fixed: Application pool configuration (IIS) -->
<!--
Configure the application pool with:
1. Custom service account with minimal permissions
2. No "Load User Profile" unless required
3. Limited file system access via ACLs
4. No administrative group membership
-->

<!-- Example applicationHost.config snippet -->
<applicationPools>
    <add name="SecureAppPool"
         autoStart="true"
         managedRuntimeVersion="v4.0"
         managedPipelineMode="Integrated">
        <processModel
            identityType="SpecificUser"
            userName="COMPANY\WebAppService"
            password="[encrypted]"
            loadUserProfile="false" />
    </add>
</applicationPools>

CVE Examples

No specific CVEs are listed in the MITRE database for this CWE. However, impersonation misconfigurations have contributed to privilege escalation in various ASP.NET applications.


References

  1. MITRE Corporation. "CWE-556: ASP.NET Misconfiguration: Use of Identity Impersonation." https://cwe.mitre.org/data/definitions/556.html
  2. Microsoft. "ASP.NET Impersonation."
  3. OWASP. "Authorization Cheat Sheet."