I am trying to harden an Apache 2.4 Web server running 2 wordpress sites with separate vhost settings. Deployed on Windows 2012 r2. I was hacked a few weeks ago and the server was completely lost. On the new server they are still trying to hack the site with post request injections/code executions. I'm having trouble trying to block all POST request that are not sent by the server on submission.

Things I have tried include

  • <Location>, <Directory>, <Limit> tags with their attributes like GET,PUT, POST PUT DELETE trying varied combos with various Require statements ie. local, ip, host, and order allow, deny patterns. Allow all from

  • <Directory "/">, <Location >,<LimitExcept > Tags including attributes such as GET,POST and combos.

  • Various <if > statements

  • AllowMethod Statements

  • Whitelisting Directories in the .htacess

Placing attempts in different file context. Such as httpd.conf, Vhost.conf, .htaccess. Any file I found referenced in Apache docs related to the directive context. Even placed it where it should not work for giggles. Nothing, I read in the docs or on stack overflow seemed to work.

All auth Modules loaded like mod_auth, mod_host etc. Just assume Modules are fine.

What I would like to achieve is to deny or <Limit POST> request. Strictly allowing them in a dynamic <Directory "/.*"> or ` being responded to only when the server submits the Request using the server IP. Therefore the IP:port of the request should be the "remote address" because the apache local service sends the request method via PHP. I believe this to be correct logic.

The last thing I had time to try before leaving work, is the below code attempting a dynamic `<Directory "/.*"> tag I do not want to dig through Wordpress for every form and create a tag for each directory.

Thank you for the help, please include a code example with your answer.

<Directory "/.*">
<if "%{REQUEST_METHOD} == 'POST'">
Require req, http %{REMOTE_ADDR} == 'xx.xx.xx.xx:xx'

Now I tried

<Directory "/"> 
<if "($_SERVER['%{REMOTE_ADDR}'] == 'xx.xx.xx.xx'">
<Limit POST>
allow from all
<Directory "/"> 
<if "($_SERVER['REMOTE_ADDR'] == 'xx.xx.xx.xx'">
<Limit POST>
allow from all

No plugin, No nginx,E xpress, Or IIS Suggestions. Only relevant solutions to this config.

  • Can you explain what you mean by "all POST request that are not sent by the server on submission." ? – Gerard H. Pille Jul 8 at 8:44
  • Sure, I do NOT want any POST request. With ONE exception. The exception is Request ORIGINATED by the internal local httpd or php service. That way request can only come from forms being submitted. Since at the time of the request it is the server making the POST request vs URI Injections, API Clients, or CLI Request. – Bama Jul 8 at 14:18
  • So, if one of your pages contains a form using the POST method, the POST will no longer be accepted? One of the consequences would be that no one could log on to the Wordpress applications. – Gerard H. Pille Jul 8 at 14:38
  • Yes, I understand. for admins I can disable it manually as needed. Now, I may be wrong. From what I am observing some type of setting such as <Directory "/login"> <LimitExcept GET POST> in client directors solves that issue. While <Limit POST> and Require ip x.x.x on a global space allows for forms to still work? – Bama Jul 8 at 14:57
  • I just can not seem to wrap my head around why the Post Request would be denied. The Request in dev tools & apache logs comes up as the server IP meaning it should be granted by allow from, require local , require ip or require user Apache Or something right? Could you explain why that is incorrect thinking? Because I have been trying to understand why logs show the severe. I thought on the Submit the server ip is requesting the data be POSTED – Bama Jul 8 at 15:25

The POST is done by the user's browser. If Apache's access logs show you that the request is coming from the same system, then maybe some other software is the first in line on that system, like eg. a webcache as Varnish, or HaProxy. Check if the header X-Forwarded-For contains the user's IP address. If you want to protect Wordpress from hacking, which is not easy, you need to work on Wordpress itself. Change the name of the login page, give admin a password, impossible to guess or brute force, and last but not least, keep Wordpress up to date, so the known vulnerabilities are patched.

| improve this answer | |
  • 1
    Thank you for explaining Why I keep seeing the POST IP in the log. I was pretty sure the POST was done by the USER browser. It makes much more sense now. It was hard to find that that with a google search or in any documentation. Because apache show conn_addr and request_addr it was super unclear.WP-admin is changed, Passwords generated via 1pass. I hate WP because the abstractions and exploitability it was a company choice. Yet they never have time to do it right lol. I will try to stay onto of updates. Thanks for the info I'll count this as the answer – Bama Jul 9 at 21:37
  • I feel your pain ;-) as I've been in that situation. – Gerard H. Pille Jul 10 at 8:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.