DarkyAngel Posted April 29, 2012 Report Posted April 29, 2012 ------------------------------------------------------------------------.NET Framework EncoderParameter integer overflow vulnerability------------------------------------------------------------------------Yorick Koster, September 2011------------------------------------------------------------------------Abstract------------------------------------------------------------------------An integer overflow vulnerability has been discovered in theEncoderParameter class of the .NET Framework. Exploiting thisvulnerability results in an overflown integer that is used to allocate abuffer on the heap. After the incorrect allocation, one or moreuser-supplied buffers are copied in the new buffer, resulting in acorruption of the heap.By exploiting this vulnerability, it is possible for an applicationrunning with Partial Trust permissions to to break from the CLR sandboxand run arbitrary code with Full Trust permissions.------------------------------------------------------------------------Affected versions------------------------------------------------------------------------It has been verified that this vulnerability exists in the .NETFramework versions 2.0, 3.0, 3.5 & 4. Earlier versions of the .NETFramework may or may not be vulnerable as well as the affected class isalso available the .NET Framework versions 1.0 & 1.1.------------------------------------------------------------------------See also------------------------------------------------------------------------- MS12-025 [2]: Vulnerability in .NET Framework Could Allow Remote CodeExecution (2671605)- KB2671605 [3] MS12-025: Vulnerabilities in the .NET Framework couldallow remote code execution: April 10, 2012- SSD: [4] SecuriTeam Secure Disclosure program- MS12-025 [5]: IKVM.NET Weblog------------------------------------------------------------------------Fix------------------------------------------------------------------------This issue was resolved with the release of MS12-025 [6]. It appears thefix was part of a security push for System.Drawing.dll.------------------------------------------------------------------------Introduction------------------------------------------------------------------------The EncoderParameter class (System.Drawing.Imaging.EncoderParameter [7])is used to pass a value, or an array of values, to an image encoder(GDI+). An image encoder can be used to translate an Image or Bitmapobject to a particular file format, for example GIF, JPEG or PNG.EncoderParameter is implemented in the System.Drawing.dll Assembly,which is located in the Global Assembly Cache [8] (GAC). Consequently,the Assembly is trusted by the .NET Framework and therefore thisAssembly will run with Full Trust permissions. In addition, the Assemblyis compiled with the AllowPartiallyTrustedCallers [9] attribute, whichallows it to be called from Assemblies running with Partial Trustpermissions.------------------------------------------------------------------------Integer overflow------------------------------------------------------------------------The EncoderParameter class contains various constructor methods. All ofthese constructors allocate memory on the heap. The size of theallocated buffer depends on the constructor's parameters. Afterallocation, the values of these constructor parameters are copied intothe new buffer. For example the constructor EncoderParameter(Encoder,Int64) accepts a 64-bit (8-byte) long value, thus 8 bytes are allocatedon the heap after which the value of the long parameter is copied intothis heap buffer. The heap buffer is freed by calling the Dispose()method. This method is also called when the EncoderParameter object isdestroyed.Some constructor methods accept one or more arrays. For these methods,the number of allocated bytes is the size of one array member multipliedby the number of members in the array. These methods do not checkwhether the resulting integer value (used for heap allocation)overflows. In some cases it is possible to trigger an integer overflowresulting in the allocation of a buffer that is too small for thesupplied constructor parameters. Not all methods are exploitable as anoverly long array is required to trigger an integer overflow. The .NETFramework limits the number of array members.One constructor method (EncoderParameter(Encoder, Int32[], Int32[],Int32[], Int32[])) appears to be very suitable for exploiting thisvulnerability. The implementation of this method is listed below.public EncoderParameter(Encoder encoder, int[] numerator1, int[] denominator1, int[] numerator2, int[] denominator2){ this.parameterGuid = encoder.Guid; if (numerator1.Length != denominator1.Length || numerator1.Length != denominator2.Length || denominator1.Length != denominator2.Length) { throw SafeNativeMethods.Gdip.StatusException(2); } else { this.parameterValueType = 8; this.numberOfValues = numerator1.Length; int num = Marshal.SizeOf(typeof (int)); this.parameterValue = Marshal.AllocHGlobal(this.numberOfValues * 4 *num); if (this.parameterValue == IntPtr.Zero) { throw SafeNativeMethods.Gdip.StatusException(3); } else { for (int index = 0; index < this.numberOfValues; ++index) { Marshal.WriteInt32(EncoderParameter.Add(this.parameterValue, 4 * index * num), numerator1[index]); Marshal.WriteInt32(EncoderParameter.Add(this.parameterValue, (4 * index + 1) * num), denominator1[index]); Marshal.WriteInt32(EncoderParameter.Add(this.parameterValue, (4 * index + 2) * num), numerator2[index]); Marshal.WriteInt32(EncoderParameter.Add(this.parameterValue, (4 * index + 3) * num), denominator2[index]); } GC.KeepAlive((object) this); } }}This constructor method is interesting for two reasons. First of all,the method accepts four integer arrays. The number of bytes that will beallocated is the number of members in the numerator1 array multipliedby 16 (four times the size of a 32-bit integer). Supplying an arraycontaining 268,435,456 integer values is enough to trigger the overflow.Doing so results in the allocation of a 0-byte buffer. The followingproof of concept code can be used to trigger this vulnerability:using System;using System.Drawing.Imaging;namespace EncoderParameterCrash{ static class Crash { [STAThread] static void Main() { int[] largeArray = new int[0x10000000]; EncoderParameter crash = new EncoderParameter(Encoder.Quality, largeArray, largeArray, largeArray, largeArray); } }}Running this code will cause the application to crash as it tries towrite beyond a heap boundary:The program '[2696] EncoderParameterCrash.vshost.exe: Managed' hasexited with code -1073741819 (0xc0000005).As demonstrated in the proof of concept, copying four large integerarrays into a heap buffer causes the program to crash. The proof ofconcept will try to write 4GB of data onto the heap. Since heap segmentsare a lot smaller than that, copying this amount of data will failearly in the process. This will cause Windows to terminate the program.All constructor methods that handle two or more arrays always check ifall supplied arrays are of the same length. As such, in order to triggerthe integer overflow arrays must at least contain 268,435,456 members.This makes exploitation of this issue difficult.However, the listed constructor method contains a programming mistake.When validating the length of the supplied arrays, the method fails tocheck the length of the numerator2 parameter. Instead it checksnumerator1 twice. The correct check should be numerator2.Length !=denominator2.Length instead of numerator1.Length != denominator2.Length.This is the second reason why this method is interesting - from anattacker's point of view. Due to the missing check, it is possibleto use the numerator2 parameter to control how much data is copied intothe heap buffer. Supplying a small(er) array as numerator2 parameterwill cause an IndexOutOfRangeException exception to be thrown;prematurely ending the while loop. Since the exception is thrown by the.NET Framework, this exception can be handled by the application thuspreventing the application from crashing.Both ingredients provide for an exploitable heap corruption as attackerscontrol how much data is allocated on the heap and also how much datais copied into the allocated buffer. It was possible to successfullyexploit this issue on the following Windows versions:- Windows XP Professional SP3 32-bit (with 4GB RAM)- Windows Vista Home Premium SP2 32-bit- Windows Vista Business SP2 32-bit and 64-bit- Windows 7 Home Premium SP1 64-bit- Windows 7 Professional SP1 64-bit- Windows 7 Enterprise SP1 32-bit and 64-bitBy exploiting this vulnerability, it is possible for an applicationrunning with Partial Trust permissions to to break from the CLR sandbox[10] (CAS) and run arbitrary code with Full Trust permissions. Examplesof Partial Trusted applications include, ClickOnce, XAML BrowserApplications (XBAP), ASP.NET (eg, shared hosting) & SilverLight. Itmust be noted that the affected class is not available for SilverLightapplications.------------------------------------------------------------------------Limitations------------------------------------------------------------------------As noted above, this issue cannot be exploited using a SilverLightapplication.With the release of MS11-044 [11], Microsoft changed the way ClickOnce& XBAP applications are started. In particular, whenever such anapplication is started from the Internet security zone, a dialog isalways shown even if the application does not request elevatedpermissions. Previously the application would just start. See also:Changes coming to ClickOnce applications running in the Internet Zone - .NET Blog - Site Home - MSDN Blogs(It is possible to display a green icon in the dialog by code signingthe manifests. When the manifests aren't signed, a red icon isdisplayed).The dialog is not shown for applications launched from the intranetsecurity zone. In this case the application will start immediately - aslong as it does not request elevated permissions. The intranet zone isonly available when it has been enabled on the target system. This iscommon for corporate networks, but less common for home users.Finally, with the release of Internet Explorer 9 Microsoft chose todisable XBAP applications in the Internet security zone. See also:IE9 - XBAPs Disabled in the Internet Zone - EricLaw's IEInternals - Site Home - MSDN Blogs------------------------------------------------------------------------Windows XP------------------------------------------------------------------------A special note must be made for Windows XP. It seems that Windows XP isa bit picky when handling large arrays. In a lot of cases,OutOfMemoryException exceptions will be thrown when trying to exploitthis issue. Successful exploitation has been achieved on a 32-bitWindows XP system with 4GB of RAM.------------------------------------------------------------------------References------------------------------------------------------------------------[1] .NET Framework EncoderParameter integer overflow vulnerability - Security advisories - Akita Software Security[2] Microsoft Security Bulletin MS12-025 - Critical : Vulnerability in .NET Framework Could Allow Remote Code Execution (2671605)[3] MS12-025: Vulnerabilities in the .NET Framework could allow remote code execution: April 10, 2012[4] SecuriTeam Secure Disclosure[5]IKVM.NET Weblog - MS12-025[6] Microsoft Security Bulletin MS12-025 - Critical : Vulnerability in .NET Framework Could Allow Remote Code Execution (2671605)[7]EncoderParameter Class (System.Drawing.Imaging)[8] Global Assembly Cache[9]AllowPartiallyTrustedCallersAttribute Class (System.Security)[10] Exploring the .NET Framework 4 Security Model[11] Microsoft Security Bulletin MS11-044 - Critical : Vulnerability in .NET Framework Could Allow Remote Code Execution (2538814)--------------------------------------------------------------------------------------------------------------------------------------------------Akita Software Security (Kvk 37144957)Akita Software Security------------------------------------------------------------------------Key fingerprint = 5FC0 F50C 8B3A 4A61 7A1F 2BFF 5482 D26E D890 5A65http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x5482D26ED8905A65 Quote