HOWTO: Synchronize User Credentials in IIS

Question:

Hello,

I recently had to modify a domain administrator account on my system and as a result parts of my web site are no longer operational.  I keep getting a 401.1 error whenever my web pages attempt to execute a Perl script that dynamically builds web pages.  Regular HTML pages execute with no problem.

I've checked the error logs and the perl scripts POST entries show a "401 1 0 ".

I've re-installed PERL on the server and gave the language permissions to execute.  I've run the scripts manually at the DOS prompt, and they execute.

I believe that the domain account password is not synchronized the account in IIS.  Is there a way I can force the synchronization to occur?

Any help would be GREATLY appreciated.

Answer:

Ok, let me first get over the security shock of you configuring the domain administrator to be the anonymous user that ANY user account can wield to run Perl. You basically have a gun pointed to your head and you might as well pull the trigger now... ;-) but let's ignore that outrage for the moment and get back to your question...

Yes, it is likely that the cached username/password in IIS configuration is no longer in sync with reality. However, there is no way to "force" the synchronization to occur for two reasons:

  1. Your custom user account is not "owned" by IIS, so there is no way for IIS to just change its password.
  2. There is no way to recover the password given just a username. That would be a security vulnerability.

In other words, you should find the cached username/password in IIS configuration and hand-synchronize it yourself. There are a couple of ways to do this:

  1. cscript %SYSTEMDRIVE%\inetpub\adminscripts\adsutil.vbs FIND AnonymousUserPass
  2. Within the IIS Manager UI, navigate to the "Websites" or "Global" node, right click properties and navigate to the security node to change the anonymous username/password. When you change this value and OK out of the dialog box, the UI will pop up another dialog box telling you all other nodes which have Anonymous username/password custom configured.

These methods all come back with a list of locations where the Anonymous User password is customized. All you need to do is check if the associated Anonymous user name is your Domain Administrator and if so, synchronize that password.

I suspect that your vdir containing the Perl scripts has a customized Anonymous user account (so they are affected), while the directory containing your HTML pages do not have such customizations.

i.e.

 C:\Inetpub\adminscripts>cscript adsutil.vbs FIND AnonymousUserName
Property AnonymousUserName found at:
  W3SVC
  W3SVC/1/Root

C:\Inetpub\adminscripts>cscript adsutil.vbs GET W3SVC/AnonymousUserName
AnonymousUserName               : (STRING) "IUSR_MACHINENAME"

C:\Inetpub\adminscripts>cscript adsutil.vbs GET W3SVC/1/Root/AnonymousUserName
AnonymousUserName               : (STRING) "Administrator"

C:\Inetpub\adminscripts>cscript adsutil.vbs SET W3SVC/1/Root/AnonymousUserPass NewPass

I found that AnonymousUserName was customized at two locations in my IIS configuration. The first one was not set to Administrator so I do not care about it; the second one was set to Administrator so I changed its password to synchronize with reality.

Script to Selectively Synchronize IIS User Accounts

Of course, all of this is scriptable with a little "glue" code since all the basic build blocks are already there. I have an example batch script at the end of this entry which does exactly that. You can copy it into a file named "SyncIISUser.bat" and call:

 SyncIISUser.bat Anonymous "Administrator" "New Password"

This command searches the local IIS configuration for all Anonymous user accounts named "Administrator" (the quotes are required, even for user names without spaces) and changes their cached password to "New Password" (the quotes are not considered part of the password).

The script currently has a safety-lock in that it ECHOs what it will do. You can inspect the output to see if it is OK and then copy/paste the commands yourself, or you can remove SET DEBUG=ECHO to have the script take action.

I always recommend backing up IIS configuration file prior to making such automated changes so that you can recover in the worst case scenario, and I cannot take any responsibility for whether the script works or not. It should work, but you should remember that all blog content is published "as-is with no warranties, and confers no rights." :-)

Enjoy.

//David

 @IF ?%_ECHO%?==?? ECHO OFF
SETLOCAL
SET CMD_ADSUTIL=CSCRIPT %SYSTEMDRIVE%\Inetpub\AdminScripts\adsutil.vbs
SET DEBUG=ECHO

IF ?%1? EQU ?? GOTO :Help
IF ?%2? EQU ?? GOTO :Help

IF /I ?%1? EQU ?Anonymous? SET PROPERTY_TO_FIND=AnonymousUserName& SET PROPERTY_TO_CHANGE=AnonymousUserPass
IF /I ?%1? EQU ?WAM?       SET PROPERTY_TO_FIND=WAMUserName&       SET PROPERTY_TO_CHANGE=WAMUserPass
IF /I ?%1? EQU ?UNC?       SET PROPERTY_TO_FIND=UNCUserName&       SET PROPERTY_TO_CHANGE=UNCPassword

SET USERNAME_TO_MATCH=%2
SET NEW_PROPERTY_VALUE=%3

FOR /F "usebackq skip=1 tokens=*" %%I IN ( `%CMD_ADSUTIL% FIND %PROPERTY_TO_FIND%` ) DO (
    FOR /F "usebackq tokens=3,* delims= " %%J IN ( `%CMD_ADSUTIL% GET "%%I/%PROPERTY_TO_FIND%"` ) DO (
        IF /I ?%USERNAME_TO_MATCH%? EQU ?%%K? (
            %DEBUG% %CMD_ADSUTIL% SET "%%I/%PROPERTY_TO_CHANGE%" %NEW_PROPERTY_VALUE%
        )
    )
)

ENDLOCAL

GOTO :EOF



REM
REM Display syntax
REM
:Help
ECHO %~n0 {Anonymous^|WAM^|UNC} "UserName" [Password]
ECHO.
ECHO Find all [Anonymous^|WAM^|UNC] user accounts matching "UserName" in
ECHO IIS configuration and change its password to [Password]
ECHO.