How to Handle IIS Requests with Percent Signs in URL (/% Path) Without 400 Errors


7 views

Many IIS administrators encounter a frustrating scenario where URLs containing a single percent sign (like http://example.com/%) trigger HTTP 400 Bad Request errors. While Microsoft's KB820129 suggests registry modifications, these solutions don't always work for this specific case.

The common approach of setting AllowRestrictedChars=1 and PercentUAllowed=1 in the registry (under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters) typically works for URLs containing % followed by hex digits (like %20), but fails for standalone percent signs.

Here are three effective approaches:

1. URL Rewrite Module Solution

Add this rule to your web.config:

<rule name="Fix Percent Sign" patternSyntax="ExactMatch">
    <match url="%" />
    <action type="Rewrite" url="/errorpages/percenterror.html" />
</rule>

2. Custom Error Page Configuration

Configure your web.config to handle 400 errors:

<httpErrors errorMode="Custom">
    <remove statusCode="400" />
    <error statusCode="400" path="/errorpages/badrequest.html" responseMode="ExecuteURL" />
</httpErrors>

3. Application Request Routing (ARR) Fix

For load-balanced environments, add this to ApplicationHost.config:

<system.webServer>
    <proxy enabled="true" />
    <rewrite>
        <rules>
            <rule name="ARR_percent_fix" stopProcessing="true">
                <match url="^%$" />
                <action type="Rewrite" url="/" />
            </rule>
        </rewrite>
    </rewrite>
</system.webServer>

For persistent cases, create a DWORD (32-bit) value called PercentUEncoding under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters and set it to 1. Then restart HTTP.SYS:

net stop http
net start http

After implementation, verify with PowerShell:

Invoke-WebRequest -Uri "http://yoursite.com/%" -UseBasicParsing

Or using curl:

curl -v http://yoursite.com/%

When working with IIS servers, you might encounter a frustrating scenario where URLs containing a standalone percentage sign (like http://yoursite.com/%) return a raw 400 Bad Request error instead of being handled gracefully. This differs from how other web servers like Apache or Nginx handle such requests.

While Microsoft's KB820129 suggests registry modifications like:


Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters]
"AllowRestrictedChars"=dword:00000001
"PercentUAllowed"=dword:00000001

These often don't solve the /% case specifically. The issue stems from how IIS's URL validation pipeline processes malformed percent-encoded sequences at a fundamental level.

Here's what actually works in production environments:

1. URL Rewrite Module Configuration


<rewrite>
  <rules>
    <rule name="Catch percentage sign" patternSyntax="ECMAScript" stopProcessing="true">
      <match url="^%$" />
      <action type="CustomResponse" statusCode="400" 
              statusReason="Bad Request" 
              statusDescription="Invalid URL encoding" />
    </rule>
  </rules>
</rewrite>

2. Custom Error Page Setup

Configure your web.config to handle 400 errors elegantly:


<httpErrors errorMode="Custom">
  <remove statusCode="400" />
  <error statusCode="400" 
         path="/errors/400.html" 
         responseMode="ExecuteURL" />
</httpErrors>

3. HTTP.sys Deep Dive

For advanced cases, combine registry tweaks with URLScan (for older IIS) or Request Filtering:


<security>
  <requestFiltering allowDoubleEscaping="true">
    <denyUrlSequences>
      <add sequence="%%" />
    </denyUrlSequences>
  </requestFiltering>
</security>

After implementation, verify with:


curl -I http://yoursite.com/%
telnet yoursite.com 80
GET /% HTTP/1.1
Host: yoursite.com

Remember that:

  • Registry changes require HTTP.sys restart (net stop http / net start http)
  • These modifications might affect security scanning tools
  • Always test in staging first