The oracle padding attack.
Fix the ASP.NET vulnerability in ASP.NET 4.0 (No workaround)

Update

26-9 Microsoft will release a fix tomorrow

Downloads

What's next

26-9
For asp.net 3.5 and lower I will provide an ISAPI filter or extension which implements the same fix as microsoft. Giving an uniform error and randomizing response time. An advantage of this filter is that it does not reset the application, so adding it to a site is easy.

Comments

Comments/improvements can be sent to captainquery(at)hotmail.com, the code can be improved. I'm in the process of putting up my own website and emailaddresses (www.captainquery.com)

After the 28th of september this page will be purely of academic interest.Microsoft will release an OOB patch

ASP.NET is susceptible to a oracle padding attack. A very good explanation of the mechanism used can be found here.

The problem is that the encrypted content is guessable by repeatedly firing requests at a server to find how data is encrypted.

Microsoft has published a few workarounds which should hold the scriptkiddies at bay. These workarounds do not solve the actual problem , data is still sent out unsigned, and someone with a lot of resources and time could still try to break the encryption.

To solve this we need a new algorithm. This algorithm needs to append a hash to sign the data. This way it is not easily possible to create new valid requests. The hash function will sort out the majority of the requests as being invalid. Even if the attacker has the machine key, the attacker also needs the secret hash key to encrypt custom data.

ASP.NET 4.0

For ASP.NET 4.0 we can build a solution that solves the problem. It is possible to change the algorithm of the encryption to a custom algorithm by changing the machineKey element. Earlier versions did not have this functionality.
Also see machineKey in ASP.NET 4.0

The SymmetricAlgorithm provider

Enclosed with this article are the sources and the binaries for a SymmetricAlgorithm provider which implements the following:

Encryption

  1. encrypt the data with aes
  2. add the secret salt to the encrypted data
  3. compute the SHA256 hash of the encrypted+secret salt
  4. remove the secret salt
  5. add the computed hash

Decryption

  1. get the hash which is appended to the encrypted data (stored hash)
  2. remove the hash from the encrypted data
  3. add the secret salt to the encrypted data
  4. compute the hash of the encrypted+secret salt
  5. compare the computed and stored hash, exit if they don't match
  6. decrypt the encrypted data

The code could need some work to refactor and cleanup, but it does work alright as provided

Recommendations

Do not use

While drinking...

If the internal method EncryptOrDecryptData is used for storing any persistent data. With persistent we mean longer than a user session.
Old data which is encrypted with this method cannot be decrypted by the AESHashed implementation. AES, which is used as default does not have the hash data added to the encrypted data. This will always give an error
EncryptOrDecryptData method is used by ASP.NET building .axd links.

Do not use this implementation to encrypt large amounts (Megabytes) of data. Data is buffered then encrypted and signed at the last step, so it uses slightly more memory than AES. This could be improved upon in the code, but will not be a problem for most sites.

The encryption is not symmetric in byte size.n bytes input gives n rounded up to a multiple of 16+32 bytes of hashdata. The symmetric in SymmetricAlgorithm means that both sides have the same key. Do not expect the same amount of bytes.

This will not

Configuration

Registration of the algorithm

  1. Add the red section to the configsections of the machine.config:

    <configuration>
    	<configSections>
    		<section name="CaptainQuery.CryptoHashProvider" 
    			type="System.Configuration.DictionarySectionHandler,System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 "/>
    		...
    	</configSections>
    
  2. Add the red section to the configuration section of the machine.config after the configSections, the AES_SHA_SECRET is needed to salt the hash. Replace the contents with some random text at least 40 characters long.

    	
    	<mscorlib>
    		<cryptographySettings>
    			<cryptoNameMapping>
    				<cryptoClasses>          
    					<cryptoClass AESHashed="CaptainQuery.CryptoHashProvider.AesHashedCryptoServiceProvider,CaptainQuery.CryptoHashProvider,Culture='neutral',PublicKeyToken=4871efc5953da800"/>
    				</cryptoClasses>       
    				<nameEntry name="AESHashed"
    					class="AESHashed"/>       
    			</cryptoNameMapping>
    		</cryptographySettings>
    	</mscorlib>
    	<CaptainQuery.CryptoHashProvider>
    		<add key="AES_SHA_SECRET" value="Change this to a secret phrase containing at least 40 characters, use proper XML encoding"/>
    	</CaptainQuery.CryptoHashProvider>	
    
  3. Copy the CaptainQuery.CryptoHashProvider.dll into the bin directory of the webapp or install the DLL in the GAC

  4. Add the following machineKey entry to the System.Web entry in the web.config

    	<system.web>
    		<machineKey decryption="alg:AESHashed"/>
    	
    
    If you're feeling adventurous you can add the machineKey entry to the machine.config, I would recommend against that if you don't know what you're doing.

Alternative registration

One cannot always change the machine.config. Next are the steps to configure the algorithm per application

  1. Add the red section to the configuration section of the web.config:

    <configuration>
    	<configSections>
    		<section name="CaptainQuery.CryptoHashProvider" 
    			type="System.Configuration.DictionarySectionHandler,System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 "/>
    		...
    	</configSections>
    
  2. Add the red section to the configuration section of the web.config after the configSections

    <configuration>
    ...
    	<CaptainQuery.CryptoHashProvider>
    		<add key="AES_SHA_SECRET" value="Change this to a secret phrase containing at least 40 characters, use proper XML encoding"/>
    	</CaptainQuery.CryptoHashProvider>	
    	
    	
  3. Add the following code fragment to the Application_Start in the global.asax (C# example)

    void Application_Start(object sender, EventArgs e)
    {
        System.Security.Cryptography.CryptoConfig.AddAlgorithm(
            typeof(CaptainQuery.CryptoHashProvider.AesHashedCryptoServiceProvider), 
            "AESHashed");
    }
    
    
  4. Copy the CaptainQuery.CryptoHashProvider.dll into the bin directory of the webapp or reference it in a project

  5. Add the following machineKey entry to the System.Web entry in the web.config

    	<system.web>
    		<machineKey decryption="alg:AESHashed"/>
    	
    

Links

Disclaimer

Don't use this software blindly, test the software first with the source code on this site

This software is licensed under a MIT license

Copyright (c) 2010 Kees Spoelstra

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.