Three tips to protect your WordPress installation
Here are three easy but important ways to protect yourself if you run a WordPress blog:
- Secure your /wp-admin/ directory. What I’ve done is lock down /wp-admin/ so that only certain IP addresses can access that directory. I use an .htaccess file, which you can place directly at /wp-admin/.htaccess . This is what mine looks like:
AuthUserFile /dev/null
AuthGroupFile /dev/null
AuthName “Access Control”
AuthType Basic
order deny,allow
deny from all
# whitelist home IP address
allow from 64.233.169.99
# whitelist work IP address
allow from 69.147.114.210
allow from 199.239.136.200
# IP while in Kentucky; delete when back
allow from 128.163.2.27I’ve changed the IP addresses, but otherwise that’s what I use. This file says that the IP address 64.233.169.99 (and the other IP addresses that I’ve whitelisted) are allowed to access /wp-admin/, but all other IP addresses are denied access. Has this saved me from being hacked before? Yes.
- Make an empty wp-content/plugins/index.html file. Otherwise you leak information on which plug-ins you run. If someone wanted to hack your blog, they might be able to do it by discovering that you run an out-of-date plugin on your blog and then they could exploit that.
- Subscribe to the WordPress Development blog at http://wordpress.org/development/feed/ . When WordPress patches a security hole or releases a new version, they announce it on that blog. If you see a security patch released, you need to upgrade or apply the patch. You leave yourself open to being hacked if you don’t upgrade.
And here’s a bonus tip: in the header.php file for your theme, you might want to check for a line like
<meta name=”generator” content=”WordPress <?php bloginfo(’version’); ?>” /> <!-– leave this for stats please -->
I’d just go ahead and delete that line or at least the bloginfo(’version’). If you’re running an older version of WordPress, anyone can view source to see what attacks might work against your blog.
Hat tip to Reuben Yau and Shoe.
Update: In the comments, Joshua Slive pointed out that the .htaccess file shouldn’t have a <LIMIT GET> around the IP addresses. That would have allowed IP addresses to POST, for example. Joshua, thanks for the pointer to the Apache docs on this point.
Brajeshwar Said,
January 17, 2008 @ 10:45 pm
1. Why would this IP restriction be more effective than a password protection using the similar .htaccess and .htpasswd method which offers the same level of protection sans the changing of IPs when you move/travel. And let your browser/keychain remember you password so you can just hit enter when prompted.
2. I’m pretty sure most web host have directory browsing turn-off by default and in that case, won’t it show a 404 page thus going to that location makes no sense. However for those not doing that, I’m pretty sure they have a reason and if they’re to follow your steps, they must have been smart enough to do a directory browsing off through their Web Host Panel or through .htaccess.
3. This is the least updated feed and we’re talking about Wordpress, you’ll definitely hear about new releases within days unless you’re on an extended vacation.
Bob Said,
January 17, 2008 @ 10:56 pm
And don’t let Google know you are doing paid blog postings on your Wordpress blog….
Multi-Worded Adam Said,
January 17, 2008 @ 11:00 pm
LMAO!
Dude, I love the reverse DNS on those IPs. That’s some classic geek humor right there.
http://whois.domaintools.com/64.233.169.99
http://whois.domaintools.com/69.147.114.210
http://whois.domaintools.com/199.239.136.200
Gotta love the conflict of interest between “home” and “work”. But the NYT moonlighting…you gonna start writing freelance op-ed SEO articles?
Gary Jones :: BlueFur.com Said,
January 17, 2008 @ 11:06 pm
If your the root user on the server set the ownership of the file to root so only the root user can modify it.
travis lane Said,
January 17, 2008 @ 11:12 pm
Just out of curiousity–if the IP address trick prevented the hack–how did you know it would’ve been successful otherwise?
Lots of people do random scans on the wp-admin directory.
Johannes Said,
January 17, 2008 @ 11:20 pm
Security through obscurity, great tip
Vlad - Small Business and Web Design Said,
January 17, 2008 @ 11:37 pm
I tried to password protect /wp-admin/, but my WordPress took it seriously and instead of asking for login/password combo it dumps me straight to the index page. Never seen this before.
marty Said,
January 17, 2008 @ 11:52 pm
Rather than creating a blank index.html in the plugins directory to prevent directory browsing, you can disable it by adding the following to your .htaccess file, and the webserver will return a 403:
# prevent directory browsing
Options -Indexes
Alvaro Said,
January 18, 2008 @ 12:14 am
Hi Matt,
you could replace the 2nd point with another configuration of the .htaccess file:
Options FollowSymLinks
AllowOverride None
(You should put the right path to the plugins directory)
or
Options -Indexes
Boring Market Said,
January 18, 2008 @ 12:51 am
Great tips!
Iliyan Darganov Said,
January 18, 2008 @ 1:28 am
Hi, Matt
thanks for the great tips.
Another way to protect your wp-content folder is again with .htaccess:
Order Allow,Deny
Deny from all
Allow from all
Dean Clatworthy Said,
January 18, 2008 @ 1:29 am
Nice bit of irony with your work IP address there Matt
Iliyan Darganov Said,
January 18, 2008 @ 1:33 am
Ops, the htaccess content did not visualise correct. Here is a screenshot: http://img339.imageshack.us/img339/7439/htaccess1dp4.gif
Also have in mind that the version of Wordpress is not shown only in the meta tag. You can find it in the rss feed for example and in several other places.
Youssef CHAOUI Said,
January 18, 2008 @ 1:42 am
Great post, for those who run under linx and have cpanel, you can just lock the wp-admin via the interface “Password Protect Directories” it’s more simple.
leafduo Said,
January 18, 2008 @ 2:29 am
I think “Deny from all” is better.
(2nd point)
Jeff Said,
January 18, 2008 @ 3:13 am
Now that you’ve told the world your IP addresses, won’t hackers be able to spoof theirs to yours to gain access?
Tim Wintle Said,
January 18, 2008 @ 3:35 am
lol, thanks Dean Clatworthy, I wouldn’t have even looked at it otherwise
@Matt Cutts - I think that this post will probably help webmasters in general more than any of the specific tips you give to site owners.
I’d have assumed that wordpress would have come with .htaccess files to secure the plugins directory. Perhaps you should suggest it to the wordpress developers?
btw, WEBSPAM-UK2007 is out. Sure you’ll be having lots of fun with it
- I was thinking of playing with it myself at home to test the [tiny] hadoop cluster I’ve just set up, but I’ve got another plan for that so it may have to wait … (I don’t have anything like the “infinate” number of processors Google seems to have, so running both jobs is out of the question)
@travis lane - if anyone tries to see my admin pages I class it as trying to hack in - perhaps with no damage, but it’s still something I would like to stop.
Oh, and some of you may be interested in a study I did recently on the growth of online video - see my blog for a link to it.
joshnunn Said,
January 18, 2008 @ 3:39 am
What might someone use if they don’t have a reliably stable IP address?
Tim Wintle Said,
January 18, 2008 @ 3:57 am
@ joshnunn - I don’t have that much experience with wordpress, but I would try one of the following if you really want lock-down:
- ssh tunnel in through a reliable ip address if you know how to do that
- rename your wordpress admin directory (not sure if this causes any problems with wordpress)
- set the wordpress admin directory to require a secure password and username
but not many of us will have as many people trying to hack our sites as I guess Matt does
Case Stevens Said,
January 18, 2008 @ 4:27 am
Hi Matt.
Great tips.
I also took the vulnerable MYSQL settings out of the wp-config file, uploaded them in a separate file which I include in the wp-config.
Would that be an extra safety lock in your opinion?
Regards and thanks for the tips.
Case
Free WordPress Templates Said,
January 18, 2008 @ 4:37 am
Instead of limiting the /wp-admin/ directory to only IPs via your .htaccess file, I just password protected the /wp-admin/ at the directory level. Then you can access it from anywhere in the world on a per user-level.
~David
PhotoTiki Chris Said,
January 18, 2008 @ 5:08 am
As mentioned above, I think Options -Indexes is a better option for point 2 and can be added to point 1.
This way if you have an open directories in your installation they will be protected.
Lee Said,
January 18, 2008 @ 6:25 am
Wow what a coincidence I wrote about these on Jan 9.
http://www.epiblogger.net/5-wordpress-security-essentials/
Amazing how things go around.
If you don’t have a static IP address you can use a range in the htaccess file for your ISP than at least it is narrowed down to just IP’s from your ISP. Check out Login Lockdown as well. It bans people by IP address if they enter the wrong user name and password after so many attempts.
Brian Said,
January 18, 2008 @ 6:33 am
joshnunn’s and Tim Wintle’s comments have got me pondering now. Can anyone come up with a script that can ping a FQDN, translate it to an IP, and replace an old IP in an .htaccess file with the new one? This might be an elegant solution to my dynamic IP issue.
Another thought occurs - this would make for a great WordPress plugin! [aligns black candles in a pentagram] Joost De Valk, I invoke you…
Joshua Slive Said,
January 18, 2008 @ 6:49 am
Your Apache httpd configuration is not secure. You need to delete the and lines. With these lines in place, you are explicitly ALLOWING access with any other method (POST, PUT, DELETE, etc). And many applications will be happy to serve requests using arbitrary methods (BLAH, for example). If you delete those two lines, all methods will be restricted, which is what you want.
The fact that this incorrect and dangerous configuration has persisted so long on the web (it hasn’t been correct since the NCSA days over 10 years ago) is an interesting phenomenon in itself. You obviously copy-pasted it from somebody else, who copy-pasted it from sombody else, etc. Nobody bothered to check the Apache httpd docs.
Also, less importantly, all the Auth* directives should be deleted since you aren’t using user authentication.
Joshua Slive Said,
January 18, 2008 @ 6:51 am
Hmmm… your blog ate the most important part of my comment because it was between angle brackets. Seems kind of lame.
You need to delete the
Limit GET
and
/Limit
lines (with angle brackets).
Omar Yesid Mariño Said,
January 18, 2008 @ 6:54 am
Thank you very much, Matt. This is really useful for me. Security on Internet is never enough.
Brian McDowell Said,
January 18, 2008 @ 7:00 am
Thank you for this write up Matt. I am sure this quick post will help many people (myself included). I run multiple blogs and am in the process of implementing this.
Much respect.
Ben Rabicoff Said,
January 18, 2008 @ 7:18 am
Great tips Matt. I’m more than sure this could save people from a great deal of headaches!
Maurice Said,
January 18, 2008 @ 7:26 am
I hope the ip adresses are fakes did you realy mean to give out your home ip address
Brian Said,
January 18, 2008 @ 7:37 am
Try browsing his “home address” on port 80.
Maurice Said,
January 18, 2008 @ 7:57 am
I have seen some boo boos where people have left things in they should’t have the cc/dd ap that had “passwd” as the password for example they had for got to change the example code that the gate way provider provided.
Matt Cutts Said,
January 18, 2008 @ 8:19 am
travis lane, thanks to a kind person, I saw an attack against my blog before it got widely noticed.
Brian, I like the “require username and password” as the simplest option compared to writing that script.
Matt Cutts Said,
January 18, 2008 @ 8:20 am
Dean Clatworthy, I picked the IP addresses as a little inside joke for the detail-oriented.
Matt Cutts Said,
January 18, 2008 @ 8:21 am
Tim Wintle, thanks for the tip. I’ll have to check how we did.
Colin Smillie Said,
January 18, 2008 @ 8:26 am
I’m suprised Akismet wasn’t mention with regards to spam prevention or even Defensio. I think most WP installations are plagued by comment spam now…
Garry Conn Said,
January 18, 2008 @ 8:30 am
Matt,
That’s great stuff man… more awareness about WordPress security is definitely needed. There are so many people out there who are discovering blogging for the first time. They don’t know anything about programming, php, MySQL, etc… they are just merely creative people and writers who want to broadcast their writing on the Internet.
This is an awesome tip, because I think it is something that many installers can automatically include for their clients when they design, install, configure WordPress. I know that I’ll use it. Thanks for the great article.
Best Regards,
Garry Conn
Michael Clark Said,
January 18, 2008 @ 9:03 am
Matt, your bonus tip isn’t enough. WordPress publishes your WP version number in lots of public places, such as in your feed. Use the noversion plugin found at http://blogsecurity.net/wordpress/bs-wp-noversion/ to hide your WP version number.
Tim Linden Said,
January 18, 2008 @ 9:11 am
Is there a reason it’s only limiting GET and not POST also?
Nick-R Said,
January 18, 2008 @ 9:40 am
Cheers for the post Matt,
i use wordpress a lot, its a great way of installing RSS into a site and a simple content management system for people who are non-computer literate .
Please keep us posted with any other faults that may be present.
Cheers
Nick R
Nick - I think the original Nick here. Said,
January 18, 2008 @ 9:59 am
Great tips mat. You can also put -Indexes in the .htaccess file to block all open folders on the site.
Mich Said,
January 18, 2008 @ 12:14 pm
More gold Matt, I swear from now on I’m reading your feed first thing every day. I would have never thought to use an ht lockout just for admin section. This was an awsome idea and I am going to setup some clients like this if I can think of a way to script an auto update to match dynamic ip changes.
I always just drop an index.htm in if I wanted to keep people out. But that is just to keep out the casual hacker, i ummmm.. errrr… ah hem, am pretty sure most of us know a determined foe will get in if they really want to.
This one great, wow(yes again with the WOW) it will effectively lock out almost anyone even those who really know their stuff will choke on that.
As always my friend Peace and thanks
Mich D.
Kshitij Said,
January 18, 2008 @ 12:51 pm
That aint gonna work with dyna IPs. Perhaps if one could rename the directory or move it somewhere else :).
Ben Said,
January 18, 2008 @ 2:26 pm
I would also put out there keeping your installation of Wordpress up to date very good for security.
Dan Said,
January 18, 2008 @ 2:32 pm
When I created the .htaccess file, I was blocked from my admin directory. I double-checked, and I know that I entered the correct IP address, and I know that my ISP doesn’t change my IP address. When I go to login, the login page appears unstyled (meaning the css for the page has been blocked) and then it sends me to the “Page not found” message on my blog. Any idea what might be causing the problem?
Robert Said,
January 18, 2008 @ 3:02 pm
> allow from 64.233.169.99
So WordPress is the REAL technology behind Google? Unbelievable! Waiting for the other Matt to confirm this…
louis w Said,
January 18, 2008 @ 3:19 pm
why don’t you just put a password on the admin dir using htaccess. if your password is strong enough its just as good as ip restriction. i doubt a spammer is going to try to crack a pw.
g1smd Said,
January 18, 2008 @ 5:21 pm
When you protect a folder from access using the methods above, the URL returns a 403 error.
That still shows that viewer that the folder does actually exist, if they want to go dig a bit deeper.
If you internally rewrite the bare folder-only URL (both with and without a trailing slash) to an internal pathname that really does not exist, then you will serve a 404 error - just like all the other URLs on the site that do not exist.
RewriteRule ^protected/?$ /thisdoesnotexist [NC]
Fun with .htaccess and rewrites.
Erek Dyskant Said,
January 18, 2008 @ 5:31 pm
Really neat ideas. Not just for wordpress, but everyone should limit the administrative functions of their web applications to known trusted IP addresses. It’s really amazing how much damage can be done with a little social engineering or packet sniffing for passwords.
Just one comment on your implmentation. the lime still allows POST requests, so I was still able to access your wp-admin page by creating a small html file:
and clicking the submit button.
You shouldn’t even need a directive. If you really want one: it should be:
order deny,allow
deny from all
# whitelist home IP address
allow from 64.233.169.99
# whitelist work IP address
allow from 69.147.114.210
allow from 199.239.136.200
# IP while in Kentucky; delete when back
allow from 128.163.2.27
deny from all
Erek Dyskant Said,
January 18, 2008 @ 5:38 pm
My previous comment got garbled by the cross site scripting protection.
Here it is reproduced, except with parentheses instead of greater than and less than signs:
Really neat ideas. Not just for wordpress, but everyone should limit the administrative functions of their web applications to known trusted IP addresses. It’s really amazing how much damage can be done with a little social engineering or packet sniffing for passwords.
Just one comment on your implmentation: The (Limit GET) directive still allows POST requests, so I was still able to access your wp-admin page by creating a small html file and clicking the submit button, so my browser requests the page as a POST instead of a GET:
(form method=POST ACTION=http://www.mattcutts.com/blog/wp-admin/)
(input type=submit)
(/form)
Your system should work fine without the (Limit) and (/Limit) lines, but if you really want them it should look like:
(Limit GET POST PUT)
order deny,allow
deny from all
# whitelist home IP address
allow from 64.233.169.99
# whitelist work IP address
allow from 69.147.114.210
allow from 199.239.136.200
# IP while in Kentucky; delete when back
allow from 128.163.2.27
(/limit)
(LimitExcept GET POST PUT)
deny from all
(/LimitExcept)
spamhound Said,
January 18, 2008 @ 5:57 pm
I go one step further and password protect the wp-admin directory in the control panel.
You can also turn indexing off for that plugin folder as added security.
Dave Said,
January 18, 2008 @ 6:30 pm
LOL at those IP’s!!!
Afriend Said,
January 18, 2008 @ 7:02 pm
To determine which content to display you have trusted ip’s,non trusted,and identified abuse ips then you vary the dispay of content as follows…….
1.Trusted ip (all content)
2.Non trusted ip (frame content or ajax content)
3.Ip abuse Ajax content only
Please delete
Afriend Said,
January 18, 2008 @ 8:25 pm
Knowing enemy: Heres the list of 3 advertisers that support of spam sites the most.
1. Googleadsense and Doubleclick.
2. Yahoo
3. Ask
ganes | gadget Said,
January 18, 2008 @ 8:32 pm
matt, about point 2. If i know the name of exploitable plugins, I can still access the plugins file. This if you only add index.html file to protect it.
I think it’s better to add
Options All -Indexes
into htaccess file in the root directory.
what say you, matt?
Ajit Gaddam Said,
January 19, 2008 @ 8:25 am
Excellent Tips Matt. I added some more WordPress Security Tips to go along with those you listed out here
Kaloyan K. Tsvetkov Said,
January 19, 2008 @ 11:08 am
I’d just go ahead and delete that line or at least the bloginfo(’version’). If you’re running an older version of WordPress, anyone can view source to see what attacks might work against your blog.
This is useless. Even if you hide the Wordpress version from the header file of your theme, it will still show itself on the login page (wp-login.php). Here is an example with this blog, which I got from here:
…link rel=’stylesheet’ href=’http://www.mattcutts.com/blog/wp-admin/wp-admin.css?version=2.3.2‘ type=’text/css’ …
See, the WP version pops up in the CSS declaration (in bold).
Kaloyan K. Tsvetkov Said,
January 19, 2008 @ 11:19 am
Make an empty wp-content/plugins/index.html file. That’s fine and easy, but using .htaccess for the plugins is what I do and it works better then the index.html file before even with the index.html file the “hackers” can probe you to see if you have the plugin that they want to exploit. This is because hardly anyone changes the name of the plugin files or the folders the plugins file are stored in (plus there are a lot of sloppy WP plugins that will not work unless they have the “original” filename and location). Here’s an example: imagine there is an exploit in the akismet plugin, so you need to see if it is installed. There are several things you can do:
* try to load the URL for the folder where “akismet” should be - in the case of this blog it is accessible:
http://www.mattcutts.com/blog/wp-content/plugins/akismet/
You can see that it is accessible, and you can see the date it is uploaded, so you can figure out what could be the latest version of it (knowing the date of the latest release for the plugin in question).
* the above is not the case with all the blogs - some of them got the “index” option of the webserver disabled so they got 403 Forbidden error when they try to load the index for the “akismet” folder. In that scenario just try to load the plugin file itself - like this:
http://www.mattcutts.com/blog/wp-content/plugins/akismet/akismet.php
If the file is there you will see something like:
Fatal error: Call to undefined function add_action() in /usr/www/users/cutts/blog/wp-content/plugins/akismet/akismet.php on line 25
Those two “probing” scenarios are the reason I prefer to use .htaccess for my plugins folder, cutting off all web access to it.
Kaloyan K. Tsvetkov Said,
January 19, 2008 @ 11:22 am
Make an empty wp-content/plugins/index.html file.
Another thing about this matter - you should fo this index.html thing to the /themes/ folder as well. Nowadays the themes are full of extra functionality, and soon there will be exploits for them as well, and an extra index.html prevention there will be OK.
Bruce Keener Said,
January 19, 2008 @ 11:33 am
Excellent tips!
Took me a while to remember though that the quote marks do not copy properly when copying code directly from your post … it is necessary to edit to ensure real quote marks are used.
I’ve noted it before, but I am delighted you are in one of your “tech moods.” I enjoy all of your posts, but especially enjoy you breaking out of the mold from time to time.
Amit Said,
January 19, 2008 @ 11:40 am
Hi Matt, some nice tips there.
Just want to let you know that on your blog why do u display the meta details that is links to the wordpress admin ? that is also a security hole.
Also locking the wp-admin file with a password protected .htaacess file will be best option. Please correct me If i am wrong.
shawn Said,
January 19, 2008 @ 11:52 am
You know Matt, I never thought of or even knew that information. Please put me on your e-mail subscription list and keep me updated. I’d really appreciate that, because:
http://www.Drewryonline.net
are all WordPress blogs….:-)
Thanks again,
Shawn
Kenji Said,
January 19, 2008 @ 12:41 pm
Does anyone else loose the dashboard contents after uploading their .htaccess in wp-admin ?
Dave (The Other One) Said,
January 19, 2008 @ 2:02 pm
Overkill alert !!!
FYI…
#1 - There’s a little thing called “Apache Web Server” and it comes default with directory indexing turned off. 90% of all hosting companies have it turned off even on Windoze servers.
#2 - If you’re using Permalink’s with Wordpress, the .htaccess in your root directory should already cover this.
ahem *cough* *cough*, excuse me Mr. Cutts, but do I see you passing Pagerank to the two links at the end of your article. Did you forget your nofollow tag??? I know things have to be hurting over at the GooglePlex with GOOG stock down by almost 20% but really Matt, I never thought you’d be caught selling text links or writing sponsored blog posts
Bruce Keener Said,
January 19, 2008 @ 3:38 pm
Has anyone had trouble getting the Google Sitemaps Generator plugin to update a sitemap after restricting /wp-admin to your own IP address? I did the htaccess mod (thanks again, Matt) and just tried running the sitemap plugin a few minutes ago. It runs but does not seem to be updating the sitemap.
I could work around it by temporarily deleting my htaccess file in the wp-admin directory, but I wonder instead if it is just time to part with using a sitemap. Thoughts? I know it is a bit off topic, but the security updates resulted in me rethinking it. All of my pages have been indexed for sometime, so I do not know that the sitemap really adds any value.
Joshua Slive Said,
January 19, 2008 @ 4:08 pm
I’m very surprised you haven’t corrected this entry yet, and disturbed by the number of people who are copy-pasting your broken example. This configuration has one of the most dangerous kinds of security problems: one which does not show up in a basic test, but is easily exploitable by someone who knows what is going on. Your site may or may not be exploitable at the moment; it depends on the details of your wordpress configuration. But in any case, why would you recommend an incorrect and possibly exploitable configuration when the correct and secure configuration is simpler than the incorrect one.
If you don’t believe me that your use of Limit is wrong, just read the bold print in the apache httpd docs:
http://httpd.apache.org/docs/2.2/mod/core.html#limit
SEO Tracker Said,
January 19, 2008 @ 4:52 pm
WOW! I would not have thought of this! Thanks Matt!
Tony Said,
January 19, 2008 @ 5:44 pm
Matt how do you modify the htaccess if you a dynamic ip address?
IncrediBILL Said,
January 20, 2008 @ 2:29 am
I had WordPress on one of my servers and I found the easiest way to protect nyself was to get rid of WordPress.
Robert Accettura Said,
January 20, 2008 @ 10:14 am
Because I’m a nice guy, I’ll throw you a few more good mods:
Use Admin SSL to force SSL for your blog’s login, otherwise your password is plain text and anyone can sniff it out.
Add to your .htaccess file:
IndexIgnore *
To never show indexes. That way someone can’t browse subdirectories in wp-content/plugins.
Kenji Said,
January 20, 2008 @ 1:09 pm
A follow-up on my problem with the dashboard.
It does show-up if I access it through the …wp-admin/ but does not if I click on the dashboard button (url ends in wp-admin/admin.php?page=index.php).
This might not be a side-effect of the .htaccess after all.
I have also checked the Sitemap plugin and it failed to write the sitemap file.
David Saunders Said,
January 20, 2008 @ 2:07 pm
I’d be happy if I could find a nice WP host that could set up a template I have ready and exclude the date part plus add the title, description tag in and add Google Analytics, Verification……
Plus all the nifty plug ins with no hassle….. Feel free to mail me if you know a really good, reasonable host that can get it right - please don’t say the Y! word…….
HELP!!!!
Tom Forrest Said,
January 20, 2008 @ 4:33 pm
I own several WordPress based sites.
Does anyone know of a good consultant I could hire to do this for me? Matt, thank you for this very useful post, and excellent examples of exactly what needs to be done.
Tom
Matt Cutts Said,
January 20, 2008 @ 10:53 pm
Joshua Slive, I’ve updated the post — thanks for pointing that out.
Multi-Worded Adam Said,
January 21, 2008 @ 8:01 am
This is a WordPress thing, Joshua. It’s done (at least such is my understanding) to prevent people from arbitrarily putting in things like iframes and Javascripts that lead to other sites. The way around it is to explicitly type the < and > , rather than the < and > signs.
So…in the case of your example, you’d type <LIMIT GET> . It’s messed up, but it does work.
William Said,
January 21, 2008 @ 8:52 am
I did not see this mentioned, I apologize if I am repeating a previous post, but thought you might find it interesting…
One other thing you may wish to consider is a little header trickery. Simply using allow/deny does not effectively hide the files and folders in question. The user will see a 403 Forbidden message. A determined attacker could still gain access to the protected files once that attacker has determined the files exist. Yes, it would be difficult and unlikely, but not entirely impossible. You can more effectively hide these files by adding the following lines outside of the folder section of your .htaccess file:
ErrorDocument 403 whatever/youuse/for404.errors
Then, in your error handling document (guessing you use PHP) add the following line at the top:
header(’HTTP/1.1 404 Not Found’);
To a would-be attacker searching for hidden files, they would not be able to distinguish a blocked area of your site from a folder that does not actually exist. Another benefit is that the content would appear to be non-existent to search engines and other automated processes such as malbots.
Xianhong Said,
January 21, 2008 @ 7:39 pm
Wordpress should release a security patch for their blog. I used to installed 1 wordpress, i never know that. i will make some changes to the blog.
LoLo Said,
January 21, 2008 @ 11:19 pm
That bonus tip won’t prevent your version from being leaked. All a person has to do is view the source of any of your feeds to get the same info. Even with FeedBurner cranked up, I can see your category feeds
Just edit your wp-includes/version.php to change it across the board.
I’d also suggest hiding your entire WordPress install. I just posted info on how to do that along with some other thoughts about your post and put $20 up for grabs for the first person who finds my wp-admin directory.
Allan Stewart Said,
January 22, 2008 @ 4:01 am
Matt,
This is very useful, thanks very much. Can I add another tip. If you have a dynamic IP you might consider setting up a proxy script from your webserver and then only allow connections to your WP via the IP associated with the proxy script. You should also .htaccess passwd protect the proxy site.
I find this very useful.
Ta
Allan
Peter Westwood Said,
January 22, 2008 @ 6:07 am
You’ll be able to do that with a simple plugin or code in your themes functions.php in the next major version of WordPress - more info on the changes to the WordPress generator generation can be found over on my blog.
Peter Said,
January 22, 2008 @ 8:17 am
http://www.josiahcole.com/2007/07/11/almost-perfect-htaccess-file-for-wordpress-blogs/
Don Melton Said,
January 22, 2008 @ 9:21 am
Matt,
Kaloyan K. Tsvetkov is correct that just removing the WordPress version from the header file in your theme does not prevent it from being visible in the style sheet inclusion from the source of the login page.
However, there are other places where the WordPress version is visible. All of your feeds and OMPL file contain the version. And these are not easily removed without modifying the WordPress source files themselves. Also, the “readme.html” file at the root of your WordPress installation contains the major and minor version number, although the specific revision is not there.
Terinea Weblog Said,
January 22, 2008 @ 4:01 pm
Hey by protecting the wp-admin, does this not stop programs like Windows Live Writer from working?
Jamie
Peter Said,
January 22, 2008 @ 7:26 pm
Nice article, I just finished my little take on the .htaccess file setup for general security. Besides the Options All -indexes, I also added a few lines to stop browsing the wp-content and wp-include directories.
You can check it out on:
http://blog.avirtualhome.com/2008/01/17/securing-wordpress-part-2/
but make sure you also read the addendum
http://blog.avirtualhome.com/2008/01/22/securing-wordpress-part-2-addendum/
Amit Bhawani Said,
January 22, 2008 @ 8:22 pm
Excellent tips there matt, especially hiding the plugins page which currently has helped me access my competitors sites and analyze their plugins
I have written a complete wordress security guide @ http://www.amitbhawani.com/blog/wordpress-security-guide-securing-your-wordpress-blogs-from-hackers/
Regards
Amit
Matt Cutts Said,
January 23, 2008 @ 12:15 am
Peter Westwood, that’s great news — thanks! On removing the version number, I know that it stays in places like your feeds, but unless you’re facing a determined attacker (which can happen), often just lowering your profile a little bit makes someone lose interest and move on to an easier target.
Colin Joss Said,
January 24, 2008 @ 2:04 pm
As I am quite a newbie at wordpress, I really am glad found this article. I don’t think I understand much of it, but doesn’t seem difficult to apply at all.
Colin Joss
East Lothian, Haddington
United Kingdom
Andrei Said,
January 25, 2008 @ 4:11 am
But first you should consider validating your page.
http://validator.w3.org/check?uri=http%3A%2F%2Fwww.mattcutts.com%2Fblog%2F
http://jigsaw.w3.org/css-validator/validator?uri=http%3A%2F%2Fwww.mattcutts.com%2Fblog%2F
There are errors in both the xhtml and css
Ash Said,
January 25, 2008 @ 12:02 pm
Hi Matt
Thank you for the great tip. My WordPress site was hacked recently and I am going to implement your tips.
Ash
Sherif Elsisi Said,
January 25, 2008 @ 7:44 pm
Great tips, thanks. I have been trying for a while to find out about security issues with wordpress after being hacked and never came across your tip about hiding you plugins directory. This is a good one!
Most hacks I experienced with my customers sites were due to having the default table prefix installed. I strongly recommend that you add changing the table prefix on your wordpress tables to a difficult one. Wordpress is popular and everyone knows the table names.
To learn more check out http://blogsecurity.net. They did a great job at addressing topics on wordpress security.
Colin Joss Said,
January 25, 2008 @ 8:29 pm
I just come back again to copy this and apply this on my wordpress..
I can “hide” the plugins, but can’t really put the .htacess right.. How to know or determine the deny IP address? Any criteria?
Thank you
Webguard Said,
January 27, 2008 @ 9:56 am
I made it easy and protected my /wp-admin dic just with a unusually name and password… i think thats nearly enough in that case
jonathon Said,
January 28, 2008 @ 1:35 am
i been using this very same protecting for about a year now and have to say it works very well, apart from sometimes block working files.
Files ~ “.(css|jpe?g|png|gif|js|flv|swf)$”
ZAFER Said,
January 28, 2008 @ 9:34 am
How dow WP work with zen cart?
Singapore SEO Said,
January 28, 2008 @ 10:43 am
Ah, nice set of tips. Just about to implement it. Anyway, seeing that you love Wordpress alot (I should think you do), any chance Google might just be buying them? :p
Anyway, cant you just deny access to the wp-admin folder except to yourself? I mean, I thought its possible to do that =.= Meh. Sorry for the ignorance
Mark Said,
January 29, 2008 @ 7:43 am
I am having trouble uploading my index.html file into my plugin folder using cPanel.
I am curious about something, Matt, why index.html? Why not index.php?
Peter Said,
January 31, 2008 @ 4:47 am
Wordpress Security Whitepaper ( downloadable .pdf )
http://blogsecurity.net/wordpress/wordpress-security-whitepaper/
David Dalka Said,
January 31, 2008 @ 9:42 am
Great stuff. Thanks.
Anuj Seth Said,
February 9, 2008 @ 9:18 pm
Why not just password protect the directory using .htaccess?
That’s what I’ve done. Wouldn’t that be an easier option to deal with?
Bala Krishna Said,
February 19, 2008 @ 1:26 am
IP method is good for static IP users.. but not useful with dynamic ip.. however it is great that everybody come up with new ideas to protect blog.. great thanks
Brian Said,
March 11, 2008 @ 3:20 pm
Thanks for the tip about putting an index.html file into the plugin directory.
Raul Said,
March 14, 2008 @ 12:28 am
I have included the .htaccess file and it works, it only permits my IP address to access the admin interface, however, my site gets hacked on a daily basis by some robot that I guess searchs for wordpress installations.
I’m using the latest version of wordpress (2.3.3)
Any suggestions?
Many thanks
greggles Said,
April 3, 2008 @ 6:12 am
What kind of protection does the IP address limitting fix provide? It won’t help CSRF nor XSS based attacks. So…I guess that leaves code execution? Privilege escalation? Can you describe more what you hope to prevent with that?
Paolo Said,
May 6, 2008 @ 12:39 pm
Thanks for these tips. they are useful!