Configuring Security Policy
System Administrators are usually responsible for configuring Security Policy. Since this article is about password filters, I'll use configuring Password Policy as the example.
|Figure 1. The "Local Security Policy" Management Console: This shows the list of security settings that compose your password policy on the local machine.|
As mentioned previously, regular users are involved in composing security settings when they choose their own log-on passwords. However, because a weak password can create vulnerable system and compromise organization security, system administrators need more control over this issue and disallow the use of too simple, short and vulnerable to dictionary attacks passwords. In other words, you need to compose a password policy that meets your organization's security requirements.
To edit security policies, you can use either the secedit.exe
command line utility or the "Domain Security Policy" graphical console available from Control Panel -> Administrative Tools on the domain controller machine. With this tool, you will govern the security policy for all the computers in the Windows domain. Note that in case of workstation machine, only the "Local Security Policy" console is installed (shown in Figure 1
). Local policy affects settings on the local machines and it doesn't override domain policy. Thus, the security settings will be effective for local machine users, but not for domain users. This article uses the graphical tool to alter security settings on the local machine.
|Figure 2. Editing Password Policy Rules: Double-click the "Minimum password length" item to display the dialog window. |
The left pane of the management console contains an Explorer-like tree. Each node represents a different Security Policy. In this example, you'll make modifications to the Password Policy to require users to choose long enough passwords (at least 10 characters). Here's how to do it:
Expand the "Account Policies" node and select "Password Policy." On the right pane of the management console, you should see a list of security settings (rules) that compose the password policy as shown in Figure 1
Double-click the "Minimum password length" item to display the dialog window (Figure 2
Edit the text field, setting the minimum password length to 10 characters, and click OK.
Congratulations! The new rule is ready. From now on, LSA will not allow your users to choose passwords shorter than 10 characters.
An interesting rule from the Password Policy set is "Password must meet complexity requirements." This rule may be either Disabled
. In the Disabled
state it has no effect. Enabling this rule instructs LSA to validate each password against Password Filters. If you don't provide any filter, the default is used (which is considered relatively strong). However, the default allows simple passwords, such as Paris123
. You definitely want more powerful filters and this is where Custom Password Filters
can be helpful.
What Is a Password Filter?
A Password Filter plays a primary role in decision-making regarding user passwords. By definition, a Password Filter is a system DLL that exports three functions with the following prototypes (note the __stdcall
BOOLEAN __stdcall InitializeChangeNotify(void); // (1)
BOOLEAN __stdcall PasswordFilter( // (2)
NTSTATUS __stdcall PasswordChangeNotify( // (3)
How does LSA interact with Custom Password Filters
by means of the above interface? First, assume that the "Password must meet complexity requirements" rule is Enabled
On the system startup, LSA loads all the available Password Filters and calls the InitializeChangeNotify()
function. When LSA receives TRUE
as a return value, this means that the Password Filter loaded successfully and functions properly. Upon this call, LSA also builds a chain of available Password Filters (those that returned TRUE
When you're giving a password to a new user or modifying an existing user's password, LSA assures that every link in Password Filters Chain is satisfied with a new password. LSA invokes the PasswordFilter()
function of each filter in the chain. If one filter in a chain returned FALSE
, LSA does NOT continue calling the next filter. Instead, it asks the user to provide another password. If every call to PasswordFilter
on every filter returns a TRUE
value, a new password is approved and each filter is notified about it through the PasswordChangeNotify()
As you can see, the Password Filter is a handy tool for LSA (or, the Windows Police), acting as a speed trap for highway patrol, helping to collect evidence from the "field." These evidences are useful in the third stage, where policies are enforced.
Before You Implement…
Consider the following issues before you start coding your own Password Filters:
- Treat sensitive data carefully. The PasswordFilter and PasswordChangeNotify functions receive passwords in clear-text format. These passwords should be processed fast and shouldn't leave any trails in your memory for malicious applications to capture. Introduced in Windows 2003, the SecureZeroMemory Win32 API cleans specified memory. Traditional ZeroMemory may be not enough, since "smart" compilers will optimize your code and remove calls to this API. To make sure there are no such "useful" optimizations, read a random byte from a password string after it was filled with zeros.
- Make your filters fast and efficient. When LSA calls into the Password Filter function, most Windows processing stops, so make sure you don't perform any lengthy operations.
- Expect the unexpected. Because LSA loads password filters during start-up, if something goes wrong, your system may become inoperable or go into deadlock. To avoid this, develop and test your DLLs on machines that have at least two operating systems installed. I have Linux and XP on my box and I found it highly useful when preparing this article. When I encountered problems, I booted from Linux and deleted the Password Filter DLL.
- Log your actions. Password Filters run in the context of the lsass.exe process. I don't recommend debugging this process, because after you close the debugger and end the process, your system will shutdown. The best way to debug your already-running filter is to write the log files to disk and follow them to fix the bugs.
- Pre-debug your DLL. While lsass.exe debugging is not recommended, you may test your fresh Password Filter by writing a small unit-test program. In this program, load your DLL with a call to LoadLibrary Win32 API and invoke exported functions (after getting their addresses within GetProcAddress Win 32 API calls). This way, you may check that your filter doesn't crash and functions properly.