0

I'm looking at ways to "harden" WordPress installations and recently came across some code to place in the site .htaccess file. However, it had no explanation as to what it does, and I'm trying to figure it out, but with little success.

The code / rule is:

RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ ///.*\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\?\=?(http|ftp|ssl|https):/.*\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\?\?.*\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(asp|ini|dll).*\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(htpasswd|htaccess|aahtpasswd).*\ HTTP/ [NC]
RewriteRule .? - [F,NS,L]

I can see this this comes into play when any of the pages in the first line are called, but beyond that I'm in the dark. What can I try next?

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Phill Healey
  • 3,084
  • 2
  • 33
  • 67
  • 1
    Did you take a look at Apache manuals on mod_rewrite module? All those directives along with all those flags like `NC`, `OR` are described. – revo Apr 02 '18 at 21:03
  • This is all it says about 'THE_REQUEST': The full HTTP request line sent by the browser to the server (e.g., "GET /index.html HTTP/1.1"). This does not include any additional headers sent by the browser. This value has not been unescaped (decoded), unlike most other variables below. – Phill Healey Apr 02 '18 at 21:33
  • The manual also doesn't explain what the REGEX's do, for obvious reasons. – Phill Healey Apr 02 '18 at 21:34
  • That is all because that is all really. Regexes are not helpful. They don't harden any thing. They check if in current http request some words exist or not e.g. `htpasswd`. `[a-z]{3,9}` tries to match an http verb. – revo Apr 03 '18 at 02:22

1 Answers1

2

The mentioned rules, in short, boost a security by blocking specific Requests as follow :

RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]

The line above to exclude a URI start with any of these /(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/ from the next rules.

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ ///.*\ HTTP/ [NC,OR]

This line above to prevent an request has more than two slashes // at the beginning of URI and actually that will prevent Path Equivalence https://cwe.mitre.org/data/definitions/50.html

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\?\=?(http|ftp|ssl|https):/.*\ HTTP/ [NC,OR]

This above line to prevent a type of Cross-site Scripting (XSS) , there is example here http://cwe.mitre.org/data/definitions/79.html The following code displays a welcome message on a web page based on the HTTP GET username parameter:

$username = $_GET['username'];
echo '<div class="header"> Welcome, ' . $username . '</div>';

Because the parameter can be arbitrary, the url of the page could be modified so $username contains scripting syntax, such as:

http://trustedSite.example.com/welcome.php?username=<Script Language="Javascript">alert("You've been attacked!");</Script>

This results in a harmless alert dialogue popping up.

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\?\?.*\ HTTP/ [NC,OR]

The above line will prevent a request coming with question marks twice like this ?? because of some cases this vulnerability may be exploited with a web browser , you can read more here https://www.securityfocus.com/bid/4876/exploit and here https://httpd.apache.org/docs/current/misc/security_tips.html

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(asp|ini|dll).*\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(htpasswd|htaccess|aahtpasswd).*\ HTTP/ [NC]

The two lines above will prevent any request with given extensions like .dll or .htaccess etc..

RewriteRule .? - [F,NS,L]

The last line will causes the server to return a 403 Forbidden status code for all captured requests .

Mohammed Elhag
  • 4,272
  • 1
  • 10
  • 18
  • It should be noted though that matching on ``REQUEST_URI`` and ``THE_REQUEST`` is generally a bad idea. These are the raw request values from the client. They haven't been cleaned up by Apache and so stuff like ``%`` escapes, or use of ``../`` haven't been removed. You should not use these variables as part of stuff which is meant to block stuff as it isn't a safe way of doing things. – Graham Dumpleton Apr 03 '18 at 06:49
  • @GrahamDumpleton Just to clarify... Are you saying that it would be a bad idea to actually use the OP content in .htaccess or do you mean that it's not perfect but still useful and safe??? – Phill Healey Apr 03 '18 at 10:11
  • I would regard anything that uses ``THE_REQUEST`` as unsafe as they are the raw values and have not been processed. People could use % escapes in the URLs and bypass your checks and potentially access things they shouldn't. Imagine you had a condition that said block access to ``/secret`` listed in ``REQUEST_URI``. Someone could request instead ``/%73ecret`` or ``/subdir/../secret``. Your condition wouldn't block it if it checks exactly for ``/secret``. – Graham Dumpleton Apr 03 '18 at 10:35
  • Note the issue is with ``THE_REQUEST`` in particular. I wrongly put ``REQUEST_URI`` in first comment but was too late to edit it when came back to it. – Graham Dumpleton Apr 03 '18 at 10:45
  • As already mentioned by someone else, for ``THE_REQUEST``, the docs say "This value has not been unescaped (decoded), unlike most other variables below.". – Graham Dumpleton Apr 03 '18 at 10:46
  • And reference to ``REQUEST_URI`` in latter comment is also wrong. So meant 'listed in ``THE_REQUEST``'. Just don't rely on ``THE_REQUEST``. – Graham Dumpleton Apr 03 '18 at 11:12