We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now

x

Checking Window accounts with blank passwords using LogonUser in .Net

pnicklos
pnicklos asked
on
Medium Priority
671 Views
Last Modified: 2008-01-09
Hi all

Using VB .NET, I am attempting to see if the current user has logged onto the local system with a password using a call to the LogonUser function in the  Lib "advapi32.dll". My code works fine for accounts that have a password ( I test this by creating a local XP account, assign a non-blank passwd and attempt to logon with the user using the aforementioned command). This is confirmed by auditing on logon events in the event viewer.

My issue is that when I create a user with a Blank passwd (i.e no assigned passwd), the LogonUser function with a blank Passwd does not logon successfully and fails. Again, the logon failure is reflected in Event Viewer.

The call syntax I'm using is

BLANKPASSWD = ""
Dim returnValue As Boolean = LogonUser(strUserName, strDomainName, BLANKPASSWD, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle)

Why can't I get LogonUser to accept a blank Passwd (3rd field)? Please respond in VB .NET terms.

Thanks
Comment
Watch Question

At the command prompt, type the following:

  net accounts

You will see the minimum allowed password length. You can change this setting to allow blank passwords using the command:

  net accounts /minpwlen:0

I guess this solves your problem.

_______________

  Nayer Naguib

Commented:
...hummmm

Did you try the "Nothing" keyword (meaning NULL) instead of an empty (null) string?

Dim returnValue As Boolean = LogonUser(strUserName, strDomainName, Nothing, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle)

Author

Commented:
Hi guys

I have tried all combinations of NULL I can think of including sending Nothing and String.empty etc. No joy unfortunately. Same applies to the Extended version of this command - LogonUserEx

Sorry Nayer, I can logon manually with a blank password on that account - it is when I attempt to programmatically logon using the ADAVPI32.dll LogonUser that I get this issue. I am not attempting to change user account settings on someones system, I am running a security tool that tests to see that the local user doesn't have a blank password and the only way I can do that, as far as I can gather, is by physically trying to logon, via the LogonUser Api, with a blank passwd. Naturally, I did test that I could logon with a blank password manually.

Any other suggestions ?
I know that you can log in manually using a blank password. Still, if you check for the MINPWLEN value, you will see that it is greater than zero (default=6).

I think you *must* change this setting before trying to *programmatically* log in to Windows using a blank password. I suggest that you read the stored value first, change it *just* before calling LogonUser() (to zero), and then changing it back after calling LogonUser().

_______________

  Nayer Naguib

Commented:
The fix to this issue is a bit strange...  you'll have to temporarily modify the registry before running the LogonUser function.

The key to change is HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\limitblankpassworduse  it must be set to 0 before you make the API call, and then reset back to 1 afterwards.

Author

Commented:
Thanks Graye, little bit of a bugger this one is - what you suggested is the reason for the LogonUser to fail on a blank password.

My code does work once the RegKey is changed. Unfortunately this leaves me with another issue, I can't guarantee that the logged on user has Local Admin rights and therefore won't be able to guarantee that I can modify the registry in HKLM back and forth as required.

Nayer - thanks for your input however, one of the first things I did was ensure that all password and logon limitations were removed and MinPwd length was set to 0 thus allowing me to change account passwds to any length. So in all my tests, the MinPwdLen was 0. As mentioned above, Graye has discovered the reason for my dilemna.

Is there any other method for a Logged on user to "test" that his account has a blank password programmatically ?

Commented:
I'd consider using Windows Management Instrumentation (WMI) to pull data about the local accounts (we are just talking about local accounts, right?)
The field in particular is called "PasswordRequired".   If set to false, then the account has a blank password.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/win32_useraccount.asp

Here is an example to demonstrate the concepts

' Remember to add a Reference to System.Management !!!
Imports System
Imports System.Management
Imports System.Windows.Forms

Namespace WMISample

    Public Class MyWMIQuery

        Public Overloads Shared Function Main() As Integer

            Try
                Dim searcher As New ManagementObjectSearcher( _
                    "root\CIMV2", _
                    "SELECT * FROM Win32_UserAccount where Domain='Your_PC_Name_Goes_Here'")

                For Each queryObj As ManagementObject in searcher.Get()

                    Console.WriteLine("-----------------------------------")
                    Console.WriteLine("Win32_UserAccount instance")
                    Console.WriteLine("-----------------------------------")
                    Console.WriteLine("AccountType: {0}", queryObj("AccountType"))
                    Console.WriteLine("Caption: {0}", queryObj("Caption"))
                    Console.WriteLine("Description: {0}", queryObj("Description"))
                    Console.WriteLine("Disabled: {0}", queryObj("Disabled"))
                    Console.WriteLine("Domain: {0}", queryObj("Domain"))
                    Console.WriteLine("FullName: {0}", queryObj("FullName"))
                    Console.WriteLine("InstallDate: {0}", queryObj("InstallDate"))
                    Console.WriteLine("LocalAccount: {0}", queryObj("LocalAccount"))
                    Console.WriteLine("Lockout: {0}", queryObj("Lockout"))
                    Console.WriteLine("Name: {0}", queryObj("Name"))
                    Console.WriteLine("PasswordChangeable: {0}", queryObj("PasswordChangeable"))
                    Console.WriteLine("PasswordExpires: {0}", queryObj("PasswordExpires"))
                    Console.WriteLine("PasswordRequired: {0}", queryObj("PasswordRequired"))
                    Console.WriteLine("SID: {0}", queryObj("SID"))
                    Console.WriteLine("SIDType: {0}", queryObj("SIDType"))
                    Console.WriteLine("Status: {0}", queryObj("Status"))
                Next
            Catch err As ManagementException
                MessageBox.Show("An error occurred while querying for WMI data: " & err.Message)
            End Try
        End Function
    End Class
End Namespace
As far as I know, the PasswordRequired field shows whether a password is *required* or not. Having a password required implies that a user cannot have a blank password. However, having a password not required does *not* imply that the user's password is blank. It just means that the user can *choose* whether or not to set a password.

_______________

  Nayer Naguib
Commented:
Nayer, I just did a quick test, and you're right...   The PasswordRequired field does NOT detect a null password.

I think this is gonna be practically impossible to do if the current user is not an administrator.   For example, digging into the SAM database would not be a viable option.

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Author

Commented:
Should have mentioned I went through the WMI stuff and have also code around the ADS_UF_PASSWD_NOTREQD in the USERACCOUNTCONTROL cn, which is the AD equivalent of above mentioned WMI control - and unfortunately as you guys have figured out, this only allows a user to select a NULL passwd but doesnt determine whether he has or not.

Just for interest, there is another WMI control - Win32_NetworkLoginProfile that contains FLAGS which is a BIT mask field which, if you do a Binary Anding with Hex 20 (decimal 32) you get the same result as in the Win32_UserAccount instance.

Graye, as you surmised, the SAM database hack won't cut it for me as the users may not be local admins.

As you boys have been really helpful, I'll assign points for this query and open another with the next part.

Sorry Nayer but Graye figured out my initial problem with why the blank doesnt work.

Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.