lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20120328142727.6f1f0a1a@sec-consult.com>
Date: Wed, 28 Mar 2012 14:27:27 +0200
From: SEC Consult Vulnerability Lab <research@...-consult.com>
To: bugtraq <bugtraq@...urityfocus.com>, <full-disclosure@...ts.grok.org.uk>
Subject: SEC Consult SA-20120328-1 :: Microsoft ASP.NET
 Forms Authentication Bypass - follow-up advisory - CVE-2011-3416

SEC Consult Vulnerability Lab Security Advisory < 20120328-1 >
=======================================================================
              title: Microsoft ASP.NET Forms Authentication Bypass
            product: Microsoft .NET Framework
 vulnerable version: Microsoft .NET Framework Version:4.0.30319; 
                     ASP.NET Version:4.0.30319.237 and below
      fixed version: MS11-100
                CVE: CVE-2011-3416
             impact: critical
           homepage: http://www.microsoft.com/net
              found: 2011-10-02
                 by: K. Gudinavicius / SEC Consult Vulnerability Lab 
                     m. / SEC Consult Vulnerability Lab
                     https://www.sec-consult.com 
=======================================================================

Vendor description:
-------------------
".NET is an integral part of many applications running on Windows and
provides common functionality for those applications to run. This
download is for people who need .NET to run an application on their
computer. For developers, the .NET Framework provides a comprehensive
and consistent programming model for building applications that have
visually stunning user experiences and seamless and secure
communication."

Source: http://www.microsoft.com/net



Vulnerability overview/description:
-----------------------------------
This advisory is an update to SEC Consult SA-20111230-0 with a detailed
PoC section.

Furthermore, SEC Consult created a PoC video which can be found here:

https://www.sec-consult.com/files/20120328-1_asp.net_authentication_bypass_MS11_100.mp4



The null byte termination vulnerability exists in the
CopyStringToUnAlingnedBuffer() function of the webengine4.dll library
used by the .NET framework. The unicode string length is determined
using the lstrlenW function. The lstrlenW function returns the length
of the string, in characters not including the terminating null
character. If the unicode string containing a null byte is passed, its
length is incorrectly calculated, so only characters before the null
byte are copied into the buffer.

This vulnerability can be leveraged into an authentication bypass
vulnerability. Microsoft ASP.NET membership system depends on the
FormsAuthentication.SetAuthCookie(username, false) method for certain
functionality. By exploiting this vulnerability an attacker is able to
log on as a different existing user with all the privileges of the
targeted user (e.g. admin).



Proof of concept:
-----------------

If developers are programming the "Microsoft way" then they will use the
standard built-in controls for the membership management, for example,
"CreateUserWizard" and "Login". The interesting one is
"CreateUserWizard", which calls the CreateUser() function of the
System.Web.Security.MembershipProvider class (Assembly:  System.Web (in
System.Web.dll)) with the parameters that the user has submitted to the
form.

The only validation (besides ASP.NET request validation) of the username
parameter is done by the ValidateParameter() function, which basically
checks the username length and if the username contains commas.

Source code excerpt:

    public override MembershipUser CreateUser(string username, string
    password, string email, string passwordQuestion, string
    passwordAnswer, bool isApproved, object providerUserKey, out
    MembershipCreateStatus status) { <...> if
    (!SecUtility.ValidateParameter(ref username, true, true, true,
    0x100)) { status = MembershipCreateStatus.InvalidUserName;
        return null;
      }
	<...>

Source code excerpt:	
	
	internal static bool ValidateParameter(ref string param, bool
checkForNull, bool checkIfEmpty, bool checkForCommas, int maxSize) {
      if (param == null)
      {
        return !checkForNull;
      }
      param = param.Trim();
      return (((!checkIfEmpty || (param.Length >= 1)) && ((maxSize <=
0) || (param.Length <= maxSize))) && (!checkForCommas
|| !param.Contains(","))); }


The new user info is stored in the database and if everything went
successfully (there is no duplicate username) function CreateUser()
returns a MembershipUser object which contains basic user information.

Source code excerpt:

	providerUserKey = new
	Guid(command.Parameters["@UserId"].Value.ToString()); time =
	time.ToLocalTime(); user = new MembershipUser(this.Name,
	username, providerUserKey, email, passwordQuestion, null,
	isApproved, false, time, time, time, time, new DateTime(0x6da,
	1, 1)); Later on, the FormsAuthentication class (Assembly:
	System.Web (in System.Web.dll)) is used, its methods
	SetAuthCookie and GetAuthCookie get called with the username
	taken from the MembershipUser object. The purpose of these
	functions is to create a FormsAuthentication ticket and set the
	cookie which will be used by the ASP.NET form authentication
	mechanism. The cookie is signed and encrypted using the machine
	key.

The encryption function Encrypt() of the FormsAuthentication class
calls the MakeTicketIntoBinaryBlob() function, which converts
FormsAuthentication ticket to the binary data.

Related stack trace:

>	System.Web.dll!System.Web.Security.FormsAuthentication.MakeTicketIntoBinaryBlob(System.Web.Security.FormsAuthenticationTicket
>	ticket = {System.Web.Security.FormsAuthenticationTicket}) Line
>	534	C#
 	System.Web.dll!System.Web.Security.FormsAuthentication.Encrypt(System.Web.Security.FormsAuthenticationTicket
ticket = {System.Web.Security.FormsAuthenticationTicket}, bool
hexEncodedTicket = true) Line 253 + 0x9 bytes	C#
System.Web.dll!System.Web.Security.FormsAuthentication.GetAuthCookie(string
userName = "admin\0AAAAA", bool createPersistentCookie = false, string
strCookiePath = "/", bool hexEncodedTicket = true) Line 309 + 0xd
bytes	C#
System.Web.dll!System.Web.Security.FormsAuthentication.SetAuthCookie(string
userName = "admin\0AAAAA", bool createPersistentCookie = false, string
strCookiePath = "/") Line 810 + 0x62 bytes	C#
System.Web.dll!System.Web.Security.FormsAuthentication.SetAuthCookie(string
userName = "admin\0AAAAA", bool createPersistentCookie = false) Line
799	C#

	
If the parameter's "TicketCompatibilityMode" value is set to
"Framework20" (which is set by default:
http://msdn.microsoft.com/en-us/library/system.web.configuration.ticketcompatibilitymode.aspx)
the native method CookieAuthConstructTicket() from the external library
webengine4.dll is called. The username is passed as the ticket.Name
parameter, the result is returned in the dst buffer.

Source code excerpt:

    private static byte[]
    MakeTicketIntoBinaryBlob(FormsAuthenticationTicket ticket) {
	<...>
	if (TicketCompatibilityMode ==
    System.Web.Configuration.TicketCompatibilityMode.Framework20) {
        num =
    System.Web.UnsafeNativeMethods.CookieAuthConstructTicket(dst,
    dst.Length, ticket.Name, ticket.UserData, ticket.CookiePath,
    pBytes, pDates); } <...>

Source code excerpt:
	
[DllImport("webengine4.dll", CharSet=CharSet.Unicode)]
    internal static extern int CookieAuthConstructTicket(byte[] pData,
int iDataLen, string szName, string szData, string szPath, byte[]
pBytes, long[] pDates); 
 
The disassembly of the CookieAuthConstructTicket() function
(webengine4.dll) shows that the CopyStringToUnAlignedBuffer() function
is used to copy unicode string (Src) into the array (a1).

Pseudocode:

int __stdcall CookieAuthConstructTicket(int a1, int a2, LPCWSTR Src,
const WCHAR *a4, const WCHAR *a5, int a6, int a7) {
  int v7; // eax@8
  int result; // eax@9
  int v9; // ecx@10
  int v10; // eax@11
  int v11; // ecx@12
  int v12; // edi@13
  int v13; // eax@13
  int v14; // edi@14
  int v15; // eax@14

  if ( a1 && a2 >= 18 && Src && a4 && a5 && a6 && a7 )
  {
    *(_BYTE *)(a1 + 8) = *(_BYTE *)a6;
    v7 = CopyStringToUnAlingnedBuffer(Src, (void *)(a1 + 9), a2 - 9);
    if ( v7 < 2
      || (v9 = v7 + 17, v7 + 17 > a2)
      || (*(_DWORD *)(v7 + a1 + 9) = *(_DWORD *)a7,
          *(_DWORD *)(v7 + a1 + 13) = *(_DWORD *)(a7 + 4),
          v10 = v7 + 18,
          v9 + 1 > a2)
      || (*(_BYTE *)(v9 + a1) = *(_BYTE *)(a6 + 1), v11 = v9 + 9, v10 +
  8 > a2) || (*(_DWORD *)(v10 + a1) = *(_DWORD *)(a7 + 8),
          *(_DWORD *)(v10 + a1 + 4) = *(_DWORD *)(a7 + 12),
          v12 = v10 + 8,
          v13 = CopyStringToUnAlingnedBuffer(a4, (void *)(a1 + v11), a2
  - v11), v13 < 2)
      || (v14 = v13 + v12, v15 = CopyStringToUnAlingnedBuffer(a5, (void
  *)(a1 + v14), a2 - v14), v15 < 2) ) result = -2147418113;
    else
      result = v15 + v14;
  }
  else
  {
    result = -2147024809;
  }
  return result;
}


The analysis of the CopyStringToUnAlignedBuffer() function reveals that
the unicode string length is determined using the lstrlenW function.
The function returns the length of the string, in characters not
including the terminating null character. This is the reason why the
authentication bypass occurs. If the unicode string (in our case
username) containing a null byte is passed, its length is incorrectly
calculated, so only characters before the null byte are copied into the
buffer. For example, the string "admin\0AAAAAAA" becomes "admin".

Pseudocode:

signed int __stdcall CopyStringToUnAlingnedBuffer(LPCWSTR Src, void
*Dst, signed int a3) {
  int v3; // eax@4
  int v4; // esi@4
  signed int result; // eax@5

  if ( Src && Dst && a3 >= 2 )
  {
    v3 = lstrlenW(Src);
    v4 = 2 * v3 + 2;
    if ( v4 <= a3 )
    {
      memcpy(Dst, Src, 2 * v3 + 2);
      result = v4;
    }
    else
    {
      result = -1;
    }
  }
  else
  {
    result = 0;
  }
  return result;
}

The data returned by the CookieAuthConstructTicket() function is then
signed and encrypted and set in the FormsAuthentication cookie, which
is issued to the client.




Vulnerable / tested versions:
-----------------------------
The vulnerability has been verified to exist in Microsoft .NET Framework
Version:4.0.30319; ASP.NET Version:4.0.30319.237, which was the most
recent version at the time of discovery.

More information regarding affected versions is available within the
advisory of Microsoft:
http://technet.microsoft.com/en-us/security/bulletin/ms11-100


Vendor contact timeline:
------------------------
2011-10-07: Contacted vendor through secure@...rosoft.com
2011-10-07: Vendor response, MSRC 11838
2011-10-14: Contacted MSRC asking for status
2011-10-15: Answer from case manager: the vulnerability will be
            addressed through a security bulletin, a timeframe is
            unknown.
2011-11-23: Contacted MSRC asking for status
2011-11-23: Answer from case manager: a release date of update is
            unknown, best guess would be a month before or after the
            March (2012) update cycle
2011-12-29: Microsoft publishes out-of-band security patch MS11-100
            which also addresses this vulnerability
2011-12-30: SEC Consult releases redacted version of advisory due to
            criticality of this issue
2012-03-28: SEC Consult releases detailed advisory incl. PoC video in
	    coordination with Microsoft



Solution:
---------
Immediately apply the MS11-100 patch:
http://technet.microsoft.com/en-us/security/bulletin/ms11-100


Workaround:
-----------
In .NET 4.0 the vulnerability can be mitigated by setting the
ticketCompatibilityMode attribute in the application or global
web.config file like this:

<system.web>
  <authentication mode="Forms">
    <forms ticketCompatibilityMode="Framework40" />
  </authentication>
</system.web>



Advisory URL:
-------------
https://www.sec-consult.com/en/advisories.html


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEC Consult Unternehmensberatung GmbH

Office Vienna
Mooslackengasse 17
A-1190 Vienna
Austria

Tel.: +43 / 1 / 890 30 43 - 0
Fax.: +43 / 1 / 890 30 43 - 25
Mail: research at sec-consult dot com
https://www.sec-consult.com

EOF K. Gudinavicius, J. Greil / @2012

_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ