Operating System - OpenVMS

Weak Password Testing

Go to solution
John Gillings
Honored Contributor

Re: Weak Password Testing

just to clarify Jur's post, SYS$UPDATE:VMS$CHECKPWD checks a string to see if it passes some VERY basic tests. It doesn't appear to consult the password dictionary, or even minimum length rules.

Based on my simple experiments I wouldn't trust it for anything serious:

$ mcr sys$update:vms$chkpwd password
%SYSTEM-E-PWDWEAK, password is too easy to guess; please choose another string
$ mcr sys$update:vms$chkpwd test
%SYSTEM-E-PWDWEAK, password is too easy to guess; please choose another string
$ mcr sys$update:vms$chkpwd secret
$ mcr sys$update:vms$chkpwd aaa
$ mcr sys$update:vms$chkpwd aa
$ mcr sys$update:vms$chkpwd a

It might be interesting if anyone with access to the sources can post exactly what this program does. From its size, and behaviour, I suspect not much!
A crucible of informative mistakes
Hein van den Heuvel
Honored Contributor

Re: Weak Password Testing

John is correct. It is a trivial test. I happened to look at its listing a few weeks back. It tests for a few dynamic strings, (username, username reversed, nodename,..) and simple list of suspect password words:


$ strings sys$update:vms$chkpwd

Jon Pinkley
Honored Contributor

Re: Weak Password Testing

I suppose we should then make sure that the VMS password dictionary has all the words that John the Ripper tries...

Has anyone actually done a comparison?

I just did a search of SYS$LIBRARY:VMS$PASSWORD_DICTIONARY.DATA;1 for "ABC123" and that isn't there, so I assume there are probably other "commonly used passwords" that aren't in the stock dictionary.

it depends
Peter Weaver_1
Frequent Advisor

Re: Weak Password Testing

> I suppose we should then make sure that the VMS password dictionary has all the words that John the Ripper tries...
>Has anyone actually done a comparison?

Back when I first heard of John the Ripper I added all the words to the data file and I modified VMS$PASSWORD_POLICY to do some of the other checks that John did. It did not take me very long, a couple of hours at most. But the people I did the work for decided that the VMS systems were far enough behind the firewalls to not worry about. That company doesn't really exist anymore.
Honored Contributor

Re: Weak Password Testing

The password dictionary article, including how to use dictionaries to extend the password dictionary:
Honored Contributor

Re: Weak Password Testing

ps: consider acquiring a heap or three of your site-specific and local document files and text databases, and pull all of the words out of those, eliminate the duplicates, and use the results as site-local additions to the dictionary.

This might seem silly, but it's a common technique used by an attacker. The generic defensive dictionaries invariably miss the site-local terms and acronyms, which means that they're potentially in play as passwords.
Richard W Hunt
Valued Contributor

Re: Weak Password Testing

I'm at a USA Dept. of Defense site and trust me, my government managers are so overboard on the paranoia scale as to make Batman's friend the Joker look sane. I've got them satisfied after a LOT of hard work. Here's what I had to do, not necessarily in any order.

First, I implemented a password policy module. It's not that hard - look at SYS$EXAMPLES for a couple of example modules named VMS$PASSWORD_POLICY. You have two entry points for functions that return a status code. A hash entry and a cleartext entry. Your inbound parameters are, for the hashed entry, a username by descriptor and a quadword-by-reference of the hash code. For the plaintext entry, two strings by descriptor of the username and actual input password. When you implement this, OpenVMS calls your entry points for each attempt to change a password. NOT for each use of an existing password. ONLY for changes of passwords.

You don't need to do anything for the policy_hash function entry point except return SS$_NORMAL as a status. I've yet to figure out why ANYONE would want to look at the hash code for anything. If the PURDY_S algorithm is in use, then any value of the hash is equally possible and equally valid - if you use PWD_MINIMUM as something other than zero.

For the policy_plaintext function entry, you only need to scan, categorize, and count character classes. For me, classes were uppercase, lowercase, digit, and punctuation characters. Define lower limits for each to whatever is the site policy, and then if the string doesn't meet criteria, return an error code of SS$_PWDWEAK (= %x0E7A if you want it as -E- severity.)

While I was working on this little jewel, I also checked for a minimum password age, which is another DOD requirement. You build a SYS$GETUAI call to include UAI$_PWD_DATE and UAI$_FLAGS. Get back those two values.

If the user has the PwdMix flag set, require the complexity as noted above. If not (which for me occurs as a public-key-only login case), you don't care about the passwords 'cause they never get used, so just return SS$_NORMAL and go away.

For the password date, which is a quadword, get the current time of day. For the high-order quad-time components only, subtract the password change date from the current time of day. Ignore the low-order date portion.

If the two dates differ in the high-order longword of the date-quad by less than 201 (decimal) then the password is less than about 24 hours old. (OK, if you do the math, the exact number is 23:58:48.84 old). Reject it because it is too young. I returned an error of SS$_PWDSYNTAX for this one rather than try to define my own system error code, but I made the module write a message to SYS$OUTPUT saying "password too young" so the user understood what was going on with that.

OK, using the standard password and other security thingies, I set the SYSGEN LGI stuff like this: LGI_PWD_TMO 30, _RETRY_LIM 3, _RETRY_TMO 20, BRK_LIM 3, _BRK_TMO 3600, HID_TIM 1800. My site also requires me to set LGI_BRK_DISUSER to 1, which I hate but cannot prevent.

Then for each user you set their minimum password size to at least two more characters than the sum of the minimum requirements for complexity. We have a requirement for 2 each of the four classes, so my min password is 10 - and if the user is privileged at all, we up that to 14. Max password age for my site is 60 days, per DoD requirements.

Here's a crazy thought, and it doesn't matter really, but if you implement password complexity, you don't need the password dictionary for those accounts - because I guarantee you that the passwords won't be in the dictionary. But password history still makes sense. I computed the numbers and set these system-wide logicals:

SYS$PASSWORD_HISTORY_LIFETIME = "305" and SYS$PASSWORD_HISTORY_LIMIT = "50" - which effectively prevents password churning, the technique whereby someone resets a password often enough to push old passwords out of the history list so he can reset his favorite password.

Now, the $64,000 question: How do you know that someone doesn't have a weak password right now? Answer: You cannot tell without more trouble than it is worth. The only thing you can see after-the-fact is the hashed password. You can get the hash quadword with a SYS$GETUAI function. You can then do repeated probes by calling function SYS$HASH_PASSWORD with the appropriate parameters for the given user, including their username, SALT value, the algorithm code, and the password you wanted to compare against the stored password hash.

I.e. You have a hash, you take your "weak" password and compute a hash for that user. Compare the hashes. If they match, the user MIGHT have a weak password. However, since the hash output by SYS$HASH_PASSWORD depends on three user-specific parameters, you have to repeat this probe once for each user for each "weak" password you wanted to test. That very quickly mounts up based on the size of the "weak" password list.

So here is how you assure that you have no weak passwords.

First, implement the password policy module, assert all users to have the PWDMIX flag and the minimum password size according to site policy.

The password policy module requires you do define the location of the module with a system-wide logical VMS$PASSWORD_POLICY = "{location/name of module}}" - by default, SYS$LIBRARY:VMS$PASSWORD_POLICY.EXE You also have to do something with SYSGEN at system startup - you use the ACTIVE parameters (NOT the CURRENT ones) and use SET LOAD_PWD_POLICY 1, then WRITE ACTIVE.

You must install the policy module, THEN define the system-level pointer, THEN update the SYSGEN parameter - in that order.

Next, send out a warning regarding password policy issues and immediately expire all user passwords.

Now, run a report after a few days showing those users who have updated their passwords since the policy module went into effect. Those folks DO NOT have weak passwords. Everyone else? Their passwords are expired. They won't log in until they reset their passwords - with the policy module in place.

Now, having done the above, you can honestly report to the big bosses that nobody has any weak passwords. Sound like a lot of work? Yep, you got it right. But it meets DoD specs in every way.
Sr. Systems Janitor
Galen Tackett
Valued Contributor

Re: Weak Password Testing

Testing for weak passwords:

Using your best "coach voice" tell the password, "OK, password, gimme 50," and see how many push ups it can do. You could also make the password do some chin ups as an extra level of testing for weakness.

Hein van den Heuvel
Honored Contributor

Re: Weak Password Testing

Richard, super writeup. Well done.

If I were to support a password module for a customer, then I would add one more test:

Look for any number character in the NEW password, add one and try against the old password, also subtract one and try.
If any of those work as prior password, then return and error and send an Email reminder to go spank the user with a wet noodle or two. Clearly one-on-one education about the intent of the passwords requirements is required for such case.



Re: Weak Password Testing

A lot of emphasis on complexity here. But it seems to me that requiring multiple character sets doesn't help nearly as much as increased length. Especially case. You don't gain much with case sensitivity compared to increased length. Check the number of possible passwords: X^L. L buys you a lot more than X. (X is number of characters, L is length.) [As an aside: Imagine if your check bounced because you used the wrong case!}




I suppose that complexity issues such as repeated characters, anagrams, company names, and history and such, are still helpful. But multiple requiring character sets seems counterproductive to me. They're too predictable and many users will use the "obvious" format of "Ulower#," for their passwords. I don't think it's very helpful to require this kind of complexity, esp. as it increases the odds that the password will be written down on a post-it note.

Stratus VOS has some interesting options that can be added to what has already been discussed here:

-forbid_vowels: yes/no
-forbid_repeating_chars: yes/no
-forbid_user_name: yes/no
-forbid_repeat_password: yes/no
-forbid_frequent_changes: yes/no
-num_hours_between_changes: 24
-forbid_passwords_in_table: yes/no
-forbid_reverse: yes/no
-forbid_anagram: yes/no
-req_alpha_numeric: yes/no
-forbid_begin_end_numeric: yes/no

(I've changed all the yes/no values to "yes/no".)

Thoughts? Comments?