IIS Audit Forms-Based Authentication

Hi, how are you?
I made a relevance query in order to check if the line: exists or if it exists but has another value after requireSSL= or if the line does not exist in the web files or if there are no web files in the subdirectories of the directory \inetpubwwwroot. The problem is that in the bigfix console I get value for some servers and in other cases I can see that it says . The query is as follows:

(if (exists lines whose (it as lowercase contains “forms” and it as lowercase contains “requiressl” and it as lowercase contains “true”) of files whose (name of it as lowercase starts with “web”) of folders of folder “\inetpub\wwwroot”) then (lines whose (it as lowercase contains “forms” and it as lowercase contains “requiressl” and it as lowercase contains “true”) of files whose (name of it as lowercase starts with “web”) of folders of folder “\inetpub\wwwroot”) else if (exists lines whose (it as lowercase contains “forms” and it as lowercase contains “requiressl=%22”) of files whose (name of it as lowercase starts with “web”) of folders of folder “\inetpub\wwwroot”) then (pathnames of files whose (name of it as lowercase starts with “web” and exists lines whose (it as lowercase contains “forms” and it as lowercase contains “requiressl=%22” and it as lowercase does not contain “true”) of it) of folders of folder “\inetpub\wwwroot”) else if (not exists lines whose (it as lowercase contains “forms” and it as lowercase contains “requiressl=%22”) of files whose (name of it as lowercase starts with “web”) of folders of folder “\inetpub\wwwroot”) then (pathnames of files whose (name of it as lowercase starts with “web” and not exists lines whose (it as lowercase contains “forms” and it as lowercase contains “requiressl=%22”) of it) of folders of folder “\inetpub\wwwroot”) else (“N/A”))

Você pode postar alguns arquivos de amostra para ilustrar os diferentes casos que deseja detectar?

Acho que a análise deles com os inspetores XML funcionará melhor do que a pesquisa de strings, mas será necessário ver qual esquema esperar.

O nome do arquivo será sempre “web.config”?

Jason how are you, I need to verify if in the web.config files of the subdirectories of the directory \inetpub\wwwroot have the line: forms requireSSL=“true”, to comply, if they have it I want to return the line, in the case that the value of “requireSSL=” is other it would be in non-compliance and I would need to return the files directories where the line have the other value or if the line does not exist I need to to return the files directories where the line is not there.

1 Like

You are trying to check this? https://learn.microsoft.com/en-us/dotnet/api/system.web.security.formsauthentication.requiressl?view=netframework-4.8

1 Like

Yes, in this case if the value of requireSSL equals “true”, but there are 4 possible situations:

  1. Exist the line with the value of requireSSL equals “true” - The good scenario

  2. Exist the line with another value for requireSSL - Bad scenario

  3. Not exists the line in the web.config files - Bad scenario

  4. Not exists web.config in the subfolders of the directory - Bad scenario

Thanks a lot for the help

1 Like

Another comment, it is possible that with the qna the query works but in the console it retrives an none value?

Possible but very unlikely. You could have different results based on SYSTEM privilege, such as the Debugger not displaying process launched by another user. If you set the debugger to “Evaluate using client” the results should be the same.
I have the query in mind and should post in 2hours or so.

Thank you very much, i will waiting and i promise you i will buy you a beer as gift haha

Allow me to preface this by saying I am not an expert on IIS, but this is how I think the setup works based on reverse-engineering one of my own setups with multiple Sites/Applications, and I’ll step through my assumptions as I explain this query.

First I don’t want to assume the Sites are located as c:\inetpub\wwwroot or its subdirectories. I know for a fact IIS sites can be in other paths, as I have many instances of that myself. So instead of assuming c:\Inetpub\wwwroot, I’ll look up the application server path from the Registry:

q: value "InstallPath" of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp" of native registry
A: %25windir%25\system32\inetsrv%00

That directory, based on the environment variable %windir%, cannot be used as a folder directly, but we can use the ‘expand environment string’ to resolve the variable and find that path:

q: (expand environment string of (it as string) of value "InstallPath" of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp" of native registry)
A: C:\windows\system32\inetsrv

Next, I know that path will have an ‘applicationHost.config’ file, which is an XML document describing all the IIS Sites on the host. I can use the XML inspectors and xpaths to pull data from the XML file.
Here, I assume that we only need to find the web.config files from the root directory of each Site. Some of my sites have multiple virtual directories, if we expect web.config files in each virtual directory we would modify this query, but for now I’m assuming we only need the root directory of each Site.
You should run this query on some of your test machines to determine whether this retrieves all the Sites you expect:

// Root folders of all Sites
q: node values of attributes "physicalPath" of xpaths "/configuration/*/sites/site/application/virtualDirectory[@path='/']" of xml documents of files "applicationHost.config" of folders "config" of native folder (expand environment string of (it as string) of value "InstallPath" of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp" of native registry)
A: %25SystemDrive%25\inetpub\wwwroot
A: C:\Program Files\Microsoft Configuration Manager\Client
A: C:\Program Files\Microsoft Configuration Manager\CCM\Incoming
A: C:\Program Files\SMS_CCM\ServiceData\System
A: C:\Program Files\SMS_CCM\ServiceData\System
A: C:\Program Files\SMS_CCM\ServiceData\System
A: C:\Program Files\SMS_CCM\CCM_STS
A: C:\Program Files\SMS_CCM\CMUserService
A: C:\Program Files\SMS_CCM\CMUserServiceWindowsAuth
A: C:\Program Files\SMS_CCM\SMS_MP
A: C:\Program Files\SMS_CCM\SMS_MP
A: C:\Program Files\SMS_CCM\SMS_BGB
A: C:\SCCMContentLib
A: C:\SMSSIG$
A: C:\Program Files\Update Services\WebServices\Root\
A: C:\Program Files\Update Services\WebServices\ReportingWebService
A: C:\Program Files\Update Services\WebServices\ClientWebService
A: C:\Program Files\Update Services\WebServices\SimpleAuthWebService
A: C:\Program Files\Update Services\WebServices\ServerSyncWebService
A: C:\Program Files\Update Services\WebServices\DssAuthWebService
A: C:\Program Files\Update Services\Inventory
A: C:\Program Files\Update Services\WebServices\ApiRemoting30
A: C:\inetpub\wwwroot\test

Notice again my first result references an environment variable in the result A: %25SystemDrive%25\inetpub\wwwroot, so we’ll again use the folders (expand environment string of it) inspector to resolve that variable to a physical path:

q: (native folders (expand environment string of it)) of node values of attributes "physicalPath" of xpaths "/configuration/*/sites/site/application/virtualDirectory[@path='/']" of xml documents of files "applicationHost.config" of folders "config" of native folder (expand environment string of (it as string) of value "InstallPath" of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp" of native registry)
A: C:\inetpub\wwwroot
A: C:\Program Files\Microsoft Configuration Manager\Client
A: C:\Program Files\Microsoft Configuration Manager\CCM\Incoming
...

Next is to check for each case in those root folders -

  • Does a web.config exist ?
  • Is the web.config a valid XML document ?
  • Does the web.config define Forms-Based Authentication?
  • Does the web.config require SSL for Forms-Based Authentication?

Again this is a series of XML xpath queries

q: (it, exists files "web.config" of it, exists xml documents of files "web.config" of it, exists xpaths "/configuration/system.web/authentication[@mode='Forms']" of xml documents of files "web.config" of it, exists xpaths "/configuration/system.web/authentication[@mode='Forms']/forms[@requireSSL='true']" of xml documents of files "web.config" of it) of (folders (it)) of (expand environment string of (it as string) ) of node values of attributes "physicalPath" of xpaths "/configuration/*/sites/site/application/virtualDirectory[@path='/']" of xml documents of files "applicationHost.config" of folders "config" of native folder (expand environment string of (it as string) of value "InstallPath" of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp" of native registry)
A: C:\inetpub\wwwroot, True, True, False, False
A: C:\Program Files\Microsoft Configuration Manager\Client, False, False, False, False
A: C:\Program Files\Microsoft Configuration Manager\CCM\Incoming, False, False, False, False
A: C:\Program Files\SMS_CCM\ServiceData\System, False, False, False, False
A: C:\Program Files\SMS_CCM\ServiceData\System, False, False, False, False
A: C:\Program Files\SMS_CCM\ServiceData\System, False, False, False, False
A: C:\Program Files\SMS_CCM\CCM_STS, True, True, False, False
A: C:\Program Files\SMS_CCM\CMUserService, True, True, False, False
A: C:\Program Files\SMS_CCM\CMUserServiceWindowsAuth, True, True, False, False
A: C:\Program Files\SMS_CCM\SMS_MP, False, False, False, False
A: C:\Program Files\SMS_CCM\SMS_MP, False, False, False, False
A: C:\Program Files\SMS_CCM\SMS_BGB, False, False, False, False
A: C:\SCCMContentLib, False, False, False, False
A: C:\SMSSIG$, False, False, False, False
A: C:\Program Files\Update Services\WebServices\Root, False, False, False, False
A: C:\Program Files\Update Services\WebServices\ReportingWebService, True, True, False, False
A: C:\Program Files\Update Services\WebServices\ClientWebService, True, True, False, False
A: C:\Program Files\Update Services\WebServices\SimpleAuthWebService, True, True, False, False
A: C:\Program Files\Update Services\WebServices\ServerSyncWebService, True, True, False, False
A: C:\Program Files\Update Services\WebServices\DssAuthWebService, True, True, False, False
A: C:\Program Files\Update Services\Inventory, False, False, False, False
A: C:\Program Files\Update Services\WebServices\ApiRemoting30, True, True, False, False
A: C:\inetpub\wwwroot\test, True, True, True, True

In my system, only the ‘test’ site (the last result) allows Forms-Based Authentication, and that site has requireSSL set on it. Several (but not all) of my sites even have a web.config. I’m not sure what happens with the Sites that have no web.config, but I assume they must inherit from the top-level web.config of the default site? Not sure…

In any case, now that all the data is retrieved I can use the values of each of these items to print a result. I think you can just change the messages here to be whatever you like for reporting

q: (item 0 of it, (if not item 1 of it then "No web.config" else if not item 2 of it then "web.config not readable" else if not item 3 of it then "No Forms Auth Configured" else if item 4 of it then "SSL Enabled for Forms auth" else "SSL Disabled for Forms auth") ) of (it, exists files "web.config" of it, exists xml documents of files "web.config" of it, exists xpaths "/configuration/system.web/authentication[@mode='Forms']" of xml documents of files "web.config" of it, exists xpaths "/configuration/system.web/authentication[@mode='Forms']/forms[@requireSSL='true']" of xml documents of files "web.config" of it) of (folders (it)) of (expand environment string of (it as string) ) of node values of attributes "physicalPath" of xpaths "/configuration/*/sites/site/application/virtualDirectory[@path='/']" of xml documents of files "applicationHost.config" of folders "config" of native folder (expand environment string of (it as string) of value "InstallPath" of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp" of native registry)
A: C:\inetpub\wwwroot, No Forms Auth Configured
A: C:\Program Files\Microsoft Configuration Manager\Client, No web.config
A: C:\Program Files\Microsoft Configuration Manager\CCM\Incoming, No web.config
A: C:\Program Files\SMS_CCM\ServiceData\System, No web.config
A: C:\Program Files\SMS_CCM\ServiceData\System, No web.config
A: C:\Program Files\SMS_CCM\ServiceData\System, No web.config
A: C:\Program Files\SMS_CCM\CCM_STS, No Forms Auth Configured
A: C:\Program Files\SMS_CCM\CMUserService, No Forms Auth Configured
A: C:\Program Files\SMS_CCM\CMUserServiceWindowsAuth, No Forms Auth Configured
A: C:\Program Files\SMS_CCM\SMS_MP, No web.config
A: C:\Program Files\SMS_CCM\SMS_MP, No web.config
A: C:\Program Files\SMS_CCM\SMS_BGB, No web.config
A: C:\SCCMContentLib, No web.config
A: C:\SMSSIG$, No web.config
A: C:\Program Files\Update Services\WebServices\Root, No web.config
A: C:\Program Files\Update Services\WebServices\ReportingWebService, No Forms Auth Configured
A: C:\Program Files\Update Services\WebServices\ClientWebService, No Forms Auth Configured
A: C:\Program Files\Update Services\WebServices\SimpleAuthWebService, No Forms Auth Configured
A: C:\Program Files\Update Services\WebServices\ServerSyncWebService, No Forms Auth Configured
A: C:\Program Files\Update Services\WebServices\DssAuthWebService, No Forms Auth Configured
A: C:\Program Files\Update Services\Inventory, No web.config
A: C:\Program Files\Update Services\WebServices\ApiRemoting30, No Forms Auth Configured
A: C:\inetpub\wwwroot\test, SSL Enabled for Forms auth
T: 38.068 ms
I: plural ( folder, string )

We could also filter on our five items, if we only wish to show non-compliant ones - but you need to determine whether a missing web.config, or a web.config that doesn’t allow Forms-based authentication, is really non-compliant. By that standard, only my test site (the only one with Forms authentication enabled and SSL required on it) would be compliant. Here’s the query in the more-readable “expanded” form with filters added:

(
  item 0 of it
  , (if not item 1 of it then "No web.config" 
 else if not item 2 of it then "web.config not readable" 
 else if not item 3 of it then "No Forms Auth Configured" 
 else if item 4 of it then "SSL Enabled for Forms auth" 
 else "SSL Disabled for Forms auth"
 )
) of (
it
, exists files "web.config" of it
, exists xml documents of files "web.config" of it
, exists xpaths "/configuration/system.web/authentication[@mode='Forms']" of xml documents of files "web.config" of it
, exists xpaths "/configuration/system.web/authentication[@mode='Forms']/forms[@requireSSL='true']" of xml documents of files "web.config" of it
) whose ( 
     not item 2 of it /*web.config missing or not XML */ 
  or not item 3 of it /* Forms authentication not configured */ 
  or not item 4 of it /* SSL not required for Forms authentication */ 
  ) of 
 (folders (it)) of (expand environment string of (it as string) ) 
of node values of attributes "physicalPath" of xpaths "/configuration/*/sites/site/application/virtualDirectory[@path='/']" 
of xml documents of files "applicationHost.config" of folders "config" of native folder (expand environment string of (it as string)
of value "InstallPath" of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp" of native registry)


A: C:\inetpub\wwwroot, No Forms Auth Configured
A: C:\Program Files\Microsoft Configuration Manager\Client, No web.config
A: C:\Program Files\Microsoft Configuration Manager\CCM\Incoming, No web.config
A: C:\Program Files\SMS_CCM\ServiceData\System, No web.config
A: C:\Program Files\SMS_CCM\ServiceData\System, No web.config
A: C:\Program Files\SMS_CCM\ServiceData\System, No web.config
A: C:\Program Files\SMS_CCM\CCM_STS, No Forms Auth Configured
A: C:\Program Files\SMS_CCM\CMUserService, No Forms Auth Configured
A: C:\Program Files\SMS_CCM\CMUserServiceWindowsAuth, No Forms Auth Configured
A: C:\Program Files\SMS_CCM\SMS_MP, No web.config
A: C:\Program Files\SMS_CCM\SMS_MP, No web.config
A: C:\Program Files\SMS_CCM\SMS_BGB, No web.config
A: C:\SCCMContentLib, No web.config
A: C:\SMSSIG$, No web.config
A: C:\Program Files\Update Services\WebServices\Root, No web.config
A: C:\Program Files\Update Services\WebServices\ReportingWebService, No Forms Auth Configured
A: C:\Program Files\Update Services\WebServices\ClientWebService, No Forms Auth Configured
A: C:\Program Files\Update Services\WebServices\SimpleAuthWebService, No Forms Auth Configured
A: C:\Program Files\Update Services\WebServices\ServerSyncWebService, No Forms Auth Configured
A: C:\Program Files\Update Services\WebServices\DssAuthWebService, No Forms Auth Configured
A: C:\Program Files\Update Services\Inventory, No web.config
A: C:\Program Files\Update Services\WebServices\ApiRemoting30, No Forms Auth Configured

edit: I didn’t mention it above, but each time I reference a folder I used the native folders inspector, to make sure that 32-bit redirection didn’t block the result. Otherwise checking for folder "c:\windows\system32" would be silently redirected to “c:\windows\syswow64”.

1 Like

Thank you very much for the explanation Jason, it was perfectly understood. So with this query I could check the following checks in the web.config files, right? :

Name of check: Ensure ‘forms authentication’ is set to use cookies

Line: forms cookieless=“UseCookies” requireSSL=“true” timeout=“30”

Name of check: Ensure ‘cookie protection mode’ is configured for forms authentication

Line: forms cookieless=“UseCookies” protection=“All”

Name of check: Ensure ‘passwordFormat’ is not set to clear

Line: credentials passwordFormat=“SHA1”

Name of check: Ensure ‘debug’ is turned off

Line: compilation debug=“false”

Name of check: Ensure custom error messages are not off

Line: customErrors mode=“RemoteOnly” or customErrors mode=“On”

Name of check: Ensure IIS HTTP detailed errors are hidden from displaying remotely

Line: httpErrors errorMode=“DetailedLocalOnly”

Name of check: Ensure ASP-NET stack tracing is not enabled

Line: trace enabled=“true”

Name of check: Ensure ‘httpcookie’ mode is configured for session state

Line: sessionState cookieless=“UseCookies”

Name of check: Ensure ‘cookies’ are set with HttpOnly attribute

Line: httpCookies httpOnlyCookies=“true”

Name of check: Ensure ‘maxURL request filter’ is configured

Line: maxURL=“4096”

Name of check: Ensure ‘MaxQueryString request filter’ is configured

Line: maxQueryString=“2048”

Name of check: Ensure non-ASCII characters in URLs are not allowed

Line: allowHighBitCharacters=“false”

Name of check: Ensure Double-Encoded requests will be rejected

Line: allowDoubleEscaping=“false”

Name of check: Ensure ‘HTTP Trace Method’ is disabled

Line: add verb=“TRACE” allowed=“false”

Name of check: Ensure Unlisted File Extensions are not allowed

Line: fileExtensions allowUnlisted=“false”

Yes, as long as these are expected in the web.config I think you can use the same patterns for each check.