Recently I was told about Smashing Magazine, which turned out to be a pretty useful site. It is targeted for web developers and web designers and it contains tons of information, tools and freebies for web developers. One of the article on that site was about 10 Steps To Protect The Admin Area in WordPress. In that article step #7 described how to use web server’s built-in authentication to provide an extra protection layer for wp-admin directory, where all WordPress admin scripts are located. The article described how to do that in Apache by using .htaccess file. In this post I will explain how to protect WordPress wp-admin directory on IIS 7.0 by using IIS built-in Forms Authentication.
First thing to make sure is to confirm that IIS Forms authentication and URL authorization modules are installed and enabled on your IIS server. To quickly check that, open an elevated command prompt and run the following commands:
C:\Windows\System32\inetsrv>appcmd list modules | find "FormsAuthentication" MODULE "FormsAuthentication" ( type: System.Web.Security.FormsAuthenticationModule,preCondition: ) C:\Windows\System32\inetsrv>appcmd list modules | find "UrlAuthorization" MODULE "UrlAuthorization" ( type: System.Web.Security.UrlAuthorizationModule, preCondition: managedHandler ) MODULE "UrlAuthorizationModule" ( native, preCondition: )
If the output from the commands look similar to above then the necessary modules are installed.
Another thing to ensure is that the WordPress site is hosted in an Application Pool with Integrated Managed Pipeline Mode. To check that run the following command from elevated command prompt (replace “DefaultAppPool” with the name of your AppPool if necessary):
C:\Windows\System32\inetsrv>appcmd list apppools | find "DefaultAppPool" APPPOOL "DefaultAppPool" (MgdVersion: v2.0,MgdMode: Integrated,state: Started)
The output should contain MgdMode:Integrated.
Download the zip file below:
Extract the two folders – App_Code and App_Data – into the root folder or your WordPress web site. For example if your WordPress files are located in folder C:\inetpub\wwwroot, then there should be two new files present at the following paths:
The CustomProvider.cs file contains an implementation of membership provider for IIS that uses Users.xml file as a storage for usernames and passwords. To learn more about providers refer to the Membership Providers article. The code for CustomProvider.cs was literally copied from that article.
The Users.xml file is a simple credentials storage. Its content looks like below:
<Users> <User> <UserName>your_username_here</UserName> <Password>your_password_here</Password> <EMail>email@example.com</EMail> </User> </Users>
Note that it is important that this file is located in App_Data directory, because this directory, as well as App_Code, is protected by IIS Request Filtering module, which prevents anyone from requesting any files from these folders.
Also it is important to pick a user name and a password different from the ones that are used for the WordPress authentication.
Also extract the Login.aspx file into the root folder of the web site, e.g.:
Now you need to register this custom membership provider and enable Forms authentication. To do that add the following XML configuration element into the <configuration> element inside of the web.config file, located at the root folder of your WordPress site:
<system.web> <authentication mode="Forms" /> <membership defaultProvider="AspNetReadOnlyXmlMembershipProvider"> <providers> <add name="AspNetReadOnlyXmlMembershipProvider" type="ReadOnlyXmlMembershipProvider" description="Read-only XML membership provider" xmlFileName="~/App_Data/Users.xml" /> </providers> </membership> </system.web>
With the custom provider registered and configured, it is time to configure IIS to protect wp-admin folder with extra authentication that uses this custom provider. To do that add the following XML configuration fragment into the <configuration> element inside of the web.config file, located at the root folder of the WordPress site:
<!-- Deny access to wp-admin for anonymous users --> <location path="wp-admin"> <system.webServer> <security> <authorization> <add accessType="Deny" users="?" /> </authorization> </security> </system.webServer> </location> <!-- Allow access to wp-admin/css folder for anonymous users --> <!-- this is needed in order for WordPress login page to display correctly --> <location path="wp-admin/css"> <system.webServer> <security> <authorization> <remove users="?" roles="" verbs="" /> </authorization> </security> </system.webServer> </location> <!-- Allow access to wp-admin/images folder for anonymous users --> <!-- this is needed in order for WordPress login page to display correctly --> <location path="wp-admin/images"> <system.webServer> <security> <authorization> <remove users="?" roles="" verbs="" /> </authorization> </security> </system.webServer> </location>
Last thing you will need to do is to configure IIS modules that are used for Forms Authentication and for URL authorization to run for all kinds of requests. Both those modules are Managed modules (that is they are implemented using .NET Framework) and by default they are configured to run only for requests that are made for ASP.NET content. In order for them to work with PHP content then need to be configured to run for all requests. This can be done by using the following configuration section. Add it inside of <configuration>/<system.webServer> element:
<modules> <remove name="UrlAuthorization" /> <remove name="FormsAuthentication" /> <remove name="DefaultAuthentication" /> <add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" preCondition="" /> <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" preCondition="" /> <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" preCondition="" /> </modules>
At this point the WordPress wp-admin directory is protected by IIS Forms Authentication in addition to the standard WordPress authentication. Update the users.xml file with the username and password of your choice and then try to request http://localhost/wp-admin/. The IIS Forms Authentication logon page will be shown first:
Once you provided the user name and password as specified in users.xml file, the standard WordPress login page will be shown next. In that page you can provide your WordPress logon credentials:
Now the entire content of the wp-admin directory is protected by two different authentication mechanisms, which makes it harder for anyone to hack into it. And the nice thing about this configuration is that it can be done even if your site is hosted on a shared server. All that is necessary is to have ASP.NET and IIS URL authorization enabled on a shared server by a shared hosting provider.
Download all the necessary files as well as an example of web.config file from the link below.
Also check out how this protection actually works by trying to navigate to http://ruslany.net/wp-admin/.