chrisdempsey
8/13/2015 - 10:43 AM

web.config for Wordpress by SAOTN

web.config for Wordpress by SAOTN

<!-- source: https://www.saotn.org/my-wordpress-web-config/ -->

<?xmlversion="1.0"encoding="UTF-8"?>
<configuration>
  <configSections>
    <!--
      Load HttpBL assembly to keep suspicious and malicious web robots
      out. Get your Access Key @ https://www.projecthoneypot.org/create_account.php
    -->
    <section name="HttpBL" type="HttpBL.Settings" />
  </configSections>
  <appSettings/>

  <!--
    Configure HttpBL settings, choose what is best for your situation
  -->
  <HttpBL
    Enabled="true"
    AlwaysAllow=""
    AlwaysDeny=""
    AccessKey="xyzabc"
    QueryDomain="dnsbl.httpbl.org"
    MaxAge="30"
    MaxScore="40"
    CacheTTL="7200"
    CacheWhite="true"
    RedirectOnHit="false"
    RedirectURL="/denied.aspx?ip=$IP&amp;result=$RESULT"
    Logging="false"
    LogPath="\path\to\HttpBL\logfile"
    LogHits="false" />

  <system.webServer>
  <modules>
    <!--
      If installed (server wide), remove the Helicon Ape module because 
      the module can eat quite a bit of RAM per worker process
    -->
    <remove name="Helicon.Ape" />

    <!--
      Add the HttpBL .NET module
    -->
    <add name="HttpBL" type="HttpBL.HttpBL" />

    <!--
      IIS caching modules for URI-, file- and authentication tokens
    -->
    <add name="UriCacheModule" />
    <add name="FileCacheModule" />
    <add name="TokenCacheModule" />
  </modules>

  <!--
    We need to set a mimeType for javascript there, so configure some 
    other types too. Notice minFileSizeForComp, this specifies the 
    minimum number of kilobytes a file must contain in order to use 
    on-demand compression
  -->
  <httpCompression minFileSizeForComp="0">
    <scheme
      name="gzip"
      dll="%Windir%\system32\inetsrv\gzip.dll"
      staticCompressionLevel="7" />
    <dynamicTypes>
      <clear/>
      <add mimeType="text/*" enabled="true" />
      <add mimeType="message/*" enabled="true" />
      <add mimeType="application/x-javascript" enabled="true" />
      <add mimeType="*/*" enabled="false" />
      <add mimeType="image/svg+xml" enabled="true" />
      <add mimeType="application/font-woff" enabled="true" />
      <add mimeType="application/x-font-ttf" enabled="true" />
      <add mimeType="application/octet-stream" enabled="true" />
    </dynamicTypes>
    <staticTypes>
      <clear/>
      <add mimeType="text/*" enabled="true" />
      <add mimeType="message/*" enabled="true" />
      <add mimeType="application/x-javascript" enabled="true" />
      <add mimeType="application/atom+xml" enabled="true" />
      <add mimeType="application/xaml+xml" enabled="true" />
      <add mimeType="*/*" enabled="false" />
      <add mimeType="image/svg+xml" enabled="true" />
      <add mimeType="application/font-woff" enabled="true" />
      <add mimeType="application/x-font-ttf" enabled="true" />
      <add mimeType="application/octet-stream" enabled="true" />
    </staticTypes>
	
    <!--
      urlCompression can give issues under certain circumstances
    -->
    <urlCompression
      doStaticCompression="true"
      doDynamicCompression="true"
      dynamicCompressionBeforeCache="true" />
  </httpCompression>
  
  <!--
    Browser cache (or client cache), and mimeMappings for IIS
  -->
  <staticContent>
    <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="28.00:00:00" />
    <remove fileExtension=".html" />
    <mimeMap fileExtension=".html" mimeType="text/html;charset=UTF-8" />
    <remove fileExtension=".css" />
    <mimeMap fileExtension=".css" mimeType="text/css" />
    <remove fileExtension=".htm" />
    <mimeMap fileExtension=".htm" mimeType="text/html;charset=UTF-8" />
    <remove fileExtension=".woff" />
    <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
    <remove fileExtension=".js" />
    <mimeMap fileExtension=".js" mimeType="application/x-javascript;charset=UTF-8" />
    <remove fileExtension=".svg" />
    <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
  </staticContent>

  <!--
    Remove all in IIS configured defaultDocuments, and
    add the ones that are necessary. This speeds up finding the defaultDocument.
  -->
  <defaultDocument>
    <files>
      <clear/>
      <add value="index.php" />
      <add value="index.html" />
    </files>
  </defaultDocument>

  <!--
    Remove and add some response headers
  -->
  <httpProtocol>
    <customHeaders>
      <remove name="X-Powered-By" />
      <remove name="Vary" />
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="X-UA-Compatible" value="IE=Edge,chrome=1" />
    </customHeaders>
  </httpProtocol>

  <handlers>
    <!--
      Remove the existing PHP fastCgi handler, so we can add our own
    -->
    <remove name="PHP" />
  
    <!--
      My PHP5.5 WinCache PHP handler in IIS, the scriptProcessor path is 
      specific to my environment. Due to a file system cache bug in 
      WinCache v1.3.7.4 for PHP 5.6, PHP 5.5/WinCache is my fallback until I 
      have found the time to test a newer WinCache version for PHP 5.6.
      
      See @ https://www.saotn.org/php-wincache-on-iis/ for more
      PHP WinCache configuration information
    -->
    <add name="PHP"
      path="*.php"
      verb="*"
      modules="FastCgiModule"
      scriptProcessor="\path\to\php55\php-cgi.exe|-c \path\to\php55\php.wincache.ini"
      resourceType="File"
      allowPathInfo="true"
      requireAccess="Script"
      responseBufferLimit="0" />
  </handlers>

  <!--
    Here we configure URL rewrites. For example, we can block referers,
    block access to wp-comments-post.php or wp-login.php, and all our WordPress 
    rewrites go here.
  -->
  <rewrite>

      <!--
        Block out some known spam referrers
      -->
      <rule name="block_spam_referrers" stopProcessing="true">
        <matchurl="(.*)" ignoreCase="true" />
        <conditions logicalGrouping="MatchAny">
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?make-money-online\.7makemoneyonline\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?buttons-for-your-website\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?buttons-for-website\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?ranksonic\.info.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?youmaydownloadthem\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?o-o-6-o-o\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?realforexgeminicodereviews\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://s\.click\.aliexpress\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?androidfirmware\.science.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?best-seo-offer\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?best-seo-solution\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?cenoval\.ru.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?pornhub-forum\.ga.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?buy-cheap-online\.info.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?get-free-traffic-now\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?hulfingtonpost\.com.*" negate="false" />
          <add input="{HTTP_REFERER}" pattern="https?://(www\.)?semalt\.semalt\.com.*" negate="false" />
        </conditions>
        <action type="CustomResponse"
          statusCode="403"
          statusReason="Forbidden: Access is denied."
          statusDescription="Access to this website from the site you came from is prohibited!" />
      </rule>

      <!--
        Start WordPress Multisite rewrite rules
      -->
      <rule name="WordPress RewriteRule 1" stopProcessing="true">
        <match url="^index\.php$" ignoreCase="false" />
        <action type="None" />
      </rule>
      <rule name="WordPress RewriteRule 2" stopProcessing="true">
        <match url="^wp-admin$" ignoreCase="false" />
        <action type="Redirect" url="wp-admin/" redirectType="Permanent" />
      </rule>
      <rule name="WordPress RewriteRule 3" stopProcessing="true">
        <match url="^" ignoreCase="false" />
        <conditions logicalGrouping="MatchAny">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" />
        </conditions>
       <action type="None" />
      </rule>
      <rule name="WordPress RewriteRule 4" stopProcessing="true">
        <match url="^(wp-(content|admin|includes).*)" ignoreCase="false" />
        <action type="Rewrite" url="{R:1}" />
      </rule>
      <rule name="WordPress RewriteRule 5" stopProcessing="true">
        <match url="^([_0-9a-zA-Z-]+/)?(.*\.php)$" ignoreCase="false" />
        <action type="Rewrite" url="{R:2}" />
      </rule>
      <rule name="WordPress RewriteRule 6" stopProcessing="true">
        <match url="." ignoreCase="false" />
        <action type="Rewrite" url="index.php" />
      </rule>
      <!--
        WordPress Permalinks URL Rewrite
        Disabled in favor of WordPress Multisite
      -->
      <!--
      <rule name="wordpress" patternSyntax="Wildcard">
        <match url="*" />
        <conditions>
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="index.php" />
      </rule>
      -->
    </rules>

    <outboundRules>
      <!--
        Remove Server response header
      -->
      <rule name="Remove Server header">
        <match serverVariable="RESPONSE_Server" pattern=".+" />
        <action type="Rewrite" value="" />
      </rule>
      <!--
        Configure HSTS for HTTPS
      -->
      <rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
        <match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
        <conditions>
          <add input="{HTTPS}" pattern="on" ignoreCase="true" />
        </conditions>
        <action type="Rewrite" value="max-age=31536000" />
      </rule>
    </outboundRules>
  </rewrite>

  <!-- 
    Block out some known offending IP addresses. Unfortunately, it is almost
    impossible to keep this up-to-date
  -->
  <security>
    <ipSecurity>
      <add ipAddress="193.201.224.96" allowed="false" />
      <add ipAddress="185.19.92.163" allowed="false" />
      <add ipAddress="37.128.149.238" allowed="false" />
      <add ipAddress="37.59.151.190" allowed="false" />
      <add ipAddress="176.10.104.96" allowed="false" />
      <add ipAddress="202.6.19.50" allowed="false" />
      <add ipAddress="178.162.209.133" allowed="false" />
      <add ipAddress="178.162.205.23" allowed="false" />
      <add ipAddress="155.133.18.127" allowed="false" />
      <add ipAddress="190.172.12.239" allowed="false" />
      <add ipAddress="195.154.235.59" allowed="false" />
      <add ipAddress="195.154.232.169" allowed="false" />
      <add ipAddress="62.210.140.103" allowed="false" />
      <add ipAddress="87.66.111.150" allowed="false" />
      <add ipAddress="175.126.100.17" allowed="false" />
      <add ipAddress="103.23.201.170" allowed="false" />
      <add ipAddress="202.164.234.1" allowed="false" />
    </ipSecurity>

    <!--
      IIS Request Filtering rules.
      Block out some requests to known backdoors (or vulnerable scripts). 
      Watch out: names can vary...
    -->
    <requestFiltering>
      <denyUrlSequences>
        <add sequence="ofc_upload_image.php" />
        <add sequence="timthumb.php" />
        <add sequence="img.php" />
        <add sequence="img_x.php" />
        <add sequence="thumb.php" />
        <add sequence="phpthumb.php" />
        <add sequence="kontol.php" />
        <add sequence="magic.php.png" />
        <add sequence="food.php" />
        <add sequence="ph.php" />
        <add sequence="fragile.php" />
        <add sequence="3xp.php" />
        <add sequence="explore.php" />
        <add sequence="petx.php" />
        <add sequence="dl-skin.php" />
        <add sequence="direct_download.php" />
        <add sequence="getfile.php" />
        <add sequence="vito.php" />
        <add sequence="upload_settings_image.php" />
        <add sequence="saint.php" />
        <add sequence="lunar.php" />
        <add sequence="nyet.gif" />
        <!-- /& URI -->
        <add sequence="/&amp;" />
        <add sequence="/login.php" />
        <add sequence="magmi.php" />
      </denyUrlSequences>

      <!--
        Yes, even your WordPress site can get scanned for Joomla com_jce vulnerabilities..
      -->
      <denyQueryStringSequences>
        <add sequence="option=com_jce&amp;task=plugin&amp;plugin=imgmanager&amp;file=imgmanager&amp;version=1576&amp;cid=20" />
        <!--
          You can add Query String sequences below, for example to (try to) block some SQL injection
          or Cross Site Scripting attacks, but only through HTTP GET:
        -->
        <add sequence="action=revslider_show_image&amp;img=../wp-config.php" />
      </denyQueryStringSequences>

      <!--
        Block SQL injection attacks through IIS Request Filtering filtering Rules.
        These are merely examples to show you the power of IIS and Request Filtering
        http://www.iis.net/configreference/system.webserver/security/requestfiltering/filteringrules
      -->
      <filteringRules>
        <filteringRule name="prevent SQL injection"
          scanUrl="true"
          scanQueryString="true">
          <appliesTo>
            <clear />
            <add fileExtension=".php" />
          </appliesTo>
          <denyStrings>
            <add string="@" />
            <add string="select" />
            <add string="table" />
            <add string="update" />
            <add string="--" />
            <!-- ... -->
            <!-- ... -->
          </denyStrings>
      </filteringRules>
    </requestFiltering>
  </security>
</system.webServer>

  <!--
    WordPress wp-login.php security: IP address whitelist,
    all IP addresses not listed below are denied access to /wp-login.php
  -->
  <location path="wp-login.php">
    <system.webServer>
      <security>
        <ipSecurityallowUnlisted="false">
          <add ipAddress="111.11.111.1" allowed="true" />
          <add ipAddress="111.111.1.111" allowed="true" />
        </ipSecurity>
      </security>
    </system.webServer>
  </location>

  <!--
    Disable PHP execution in WordPress uploads folder, for extra security.
  -->
  <location path="wp-content/uploads">
    <system.webServer>
      <handlers accessPolicy="Read"/>
    </system.webServer>
  </location>
</configuration>