Security – Tech Tips, Reviews, Tutorials, Occasional Rants Fri, 21 Mar 2014 05:03:09 +0000 en-US hourly 1 Help! My Site Was Hacked! Tue, 15 Jan 2013 03:50:17 +0000 This can happen to the best of us. Hacks suck. There is no formulaic response to them that is guaranteed to fix your site, but I’m going to outline a few steps that might get you back in the saddle and hopefully help you identify the extent of the damage. The most common type of hack I see is against sites running known systems (like WordPress) where the hacker modifies the index.php file and prints extra code into the pages. This causes visitors to inadvertently download malicious code and it causes Google to black-list your site. Did this happen to you? Keep reading…

1. Verify that no sensitive data was on the server. It’s a whole other ballgame if you were storing credit card or social security numbers. In a nutshell, never store sensitive data on your server! It’s too hot to handle! Let a professional store that stuff. If you did have sensitive data on your server, you can stop reading now, because you need to hire a professional security consultant (and possibly a lawyer) to help dig you out of this mess.

2. Take a snapshot of the crime-scene. Zip up a copy of all files on the site and copy of the database. You should also get copies of your system’s logs dating back to sometime before the hack occurred. You may not need to touch this stuff ever again, but there’s a possibility that later on, a security consultant may want to look at your “bag of evidence”.

3. Restore from backup. You did have backups right? Sometimes it is difficult to know which backup to use. Inspect the backups carefully: you want to find a clean copy. Your host should be able to help identify a time frame of when the site was compromised.

4. Determine your Exposure. If your site was running WordPress (or any CMS), then your database and your database login got exposed. This is simply because if the hacker was able to write to your index.php file, he was certainly able to read your CMS’s config file (e.g. wp-config.php), and thus able to read everything in the database. You have to assume that any passwords in that database are cracked. You can never use those passwords again.

Important question #1: did you use that same password on other sites (e.g. Gmail, Yahoo, Facebook, etc)? If the answer is yes, you need to change those passwords immediately. You’re in a race against time here: any hacker with an ounce of curiosity will try logging into other sites using the credentials he cracked from your database. This is why you should never reuse a password: if one site gets hacked, the dominos start falling. You can use 1password or a similar tool to help you manage your passwords.

Important question #2: does your database login have access to other databases? If the MySQL user you used had access to other databases, you have to assume that any data in those databases was also compromised (including passwords). So you may need to force a password update for those sites too. The lesson here: NEVER grant a MySQL user access to more databases than it absolutely needs.

Important question #3: did you use the same username/password for anything else on your server? Like your FTP login or your cPanel password. If you made that mistake, then you need to assume that the hacker compromised everything that he would have been able to see with that login. If this is your cPanel or WHM control panel, then it’s possible that ALL sites on that server or the server itself were compromised. At that point, you may need to restore your entire server or set up a new one entirely. Again, if you find yourself in this situation, consult with your hosting provider or find a qualified security professional.

5. Consult with your hosting provider or sysadmin. You need to figure out what files the hacker would have had access to. In a PHP site, that means that you would have to figure out what user and group PHP was running as. If you determine that the hacker was able to get root privileges, then you have to assume that any passwords on your server were harvested and cracked, and all sites and all data on the server were compromised. At that point, you need to restore your entire server. If you determine that only your home-directory was exposed, then you can continue patching things up. Make sure that no sensitive files were anywhere in that your user’s home dir. Some juicy targets for downloading might be any notes with logins or backup files that contained other configuration files.

It’s usually not 100% clear how exactly a hacker got in… an unpatched WordPress plugin might not be as bad as an unpatched version of OpenSSH. Your sysadmin might be able to help determine the attack vector. If you want to sniff around, google names and versions of WordPress and/or plugins on — it’s a one-stop shop for hackers, so if you see something on there that matches what you were running, it’s probably a good indicator that that’s how they got in. Hopefully your hosting provider will shoot you straight about what versions of software they were running — most hosts worth their salt will keep their servers patched, and most often, it’s the users who forgot to update something on their site. If you are reasonably certain that the hacker did not gain root privileges, then you can keep going…

6. Change ALL passwords on the server. The database login credentials were exposed via the config file, so you’ll have to change your database login at a minimum, but it’s a good idea to swap out other credentials at this time too — it’s possible that there were keyloggers or other payloads that harvested those other logins, so you’ll want to update them. REMEMBER: you need to do this even if you were able to restore from backup.

7. Update all your files. Update your server (if possible), your version of your CMS, any plugins, any themes, etc. Basically, if you can re-install something on your site, do it. You don’t know for sure if the backup had the same vulnerability, and it’s possible you may just be repeating this exercise in a few weeks if the same vulnerability is exploited again. Really the only stuff you want to keep is stuff that you (or other users) generated, i.e. content. Everything else should be re-installed from a trusted source. Inspect your content carefully for any strange code or payloads… it’s possible that the backup you restored from may not have been clean.

8. Notify Google. Presumably, this whole affair got your site black-listed from Google, so once you’ve cleaned up the damage, you need to fill out a form with Google and request that they re-scan your site. Often you have to specify what steps you took to clean things up. You should expect your site to black-listed for 48 hours. Sometimes you’ll be back online faster than that, but the time frame is not predictable.

Hope this helps those people who have found themselves in this unenviable situation. If you need more of a post-mortem than this, or if you need more protection moving forward, you can look into monitoring services or having a penetration test done. Security is one of those areas where it can be hard to know when to stop — it is a journey more than a destination, and at some point you have to strike a balance to get a setup that has acceptable risk.

Securing Your Email via 2-Step Verification Fri, 11 Jan 2013 20:53:14 +0000 It is vitally important to keep your email account as secure as possible. Google is one organization that emphasizes security, so take advantage of it! For Google Mail, it is easy to enable 2-step authentication. The idea is simple: in order to log in, you must provide something that you know (your password) and something that you have (your phone).

Think about this for a moment… normally if someone gets ahold of your email password, they could read your email (or impersonate you!). Think about it a bit more: once a hacker is in your email, they can visit other sites (like Facebook, PayPal, or ???) and they can easily click the “I Forgot my Password” link, and POOF: they’ll be able to log into any site that uses that email address.

The bottom line is that a hacked email account can start a chain reaction that can destroy your digital life. But with Google Mail, there are steps you can take to prevent this.

Here’s a brief video showing you how to set this up. If you’re not the domain administrator, then you can follow along with steps 4-7 below.

Enabling 2-Step Authentication in Google Mail

If you are not the domain administrator (e.g. if you are an employee) and you know that your domain administrator has already enabled this, then you can jump to step 4.

  1. Log into the Google Mail account that is the administrator for your domain.
  2. Click the Gear icon at top-right and click the “Manage” Link. That should bring up the administrator control panel.
  3. Click on the “Advanced Tools” tab, then check the box labeled “Allow Users to turn on 2-Step authentication”.
  4. Head back to the mail page by clicking the “Mail” link at the top of the screen. (If you’re not the domain administrator, this is where you would begin: inside your Google Mail home page).
  5. Click your email address at the top right: this should open a drop-down menu. Click the “Account” link next to your account avatar image.
  6. Click the “Security” link in the left-hand menu.
  7. In the “2-step Verification” section, click the “Settings” link and enter in a valid phone number.

See also Google’s official documentation.

Using Mail Applications

For our friends using iPads, smart phones, etc. and who are running a Mail application, you have to set up an “Application Password” for these applications. These single-use passwords are intended for use by a single application, and they bypass the 2-factor authentication. This is necessary because some applications don’t yet support 2-factor authentication, so the application-specific passwords offer a workaround that still takes advantage of the stronger security features.

Basic Web Security Mon, 10 May 2010 18:00:51 +0000 Continue reading Basic Web Security ]]> Web security is a huge topic, and this article only intends to cover some of the most basic issues and increase awareness of how carelessness or ignorance can lead to exploits. Ultimately, what you don’t know can hurt you, so it’s in your best interest to learn as much as you can about your site and the technologies it relies on. Here’s a brief run-down of some fairly common mistakes I’ve come across and what you can do to either avoid them or lessen your vulnerability.

Suspected Malware Site!
You've been F'd in the A!

Make Rolling Backups

If you do nothing else, make sure you are backing up your site and its databases. So long as you know if/when your site fails (or is hacked) and have the ability to roll back to a known good state, you have little to fear.

Make SURE you practice restoring a site from your backups! An untested backup is worthless. Nothing is worse that THINKING you have a viable backup only to discover that it is actually corrupted.

As your backup needs mature, consider storing them offsite, e.g. on Amazon’s S3 service.

I’m supplying two of my most-used backup scripts for those in need. These are fairly simple, but they will work on shared hosts. They will backup a web site’s files and its databases.

Be Diligent about Passwords

You’ve probably heard this a hundred times before, but it is really important:

  • NEVER use the same password twice! Ever!
  • Avoid short passwords! Length before strength. Try mixing up combinations of smaller units, e.g. “AlphaBetaCharlie” instead of “abc”. Be creative. You can have strong passwords that are easy to remember!
  • Store your passwords in a safe place, e.g. in a password manager like KeePass or in an encrypted disc image
  • Change your Passwords Frequently! Literally, put this in your calendar so you remember to do it on a periodic basis. This helps avoid brute-force attacks.
  • As a secondary line of defense, you can put an .htaccess password on your manager pages. All this does is slow down a brute-force attack by forcing the attacker to crack an additional password.

Password Protecting Directories using .htaccess

This adds an additional layer of authentication to a site or to a page; it’s not meant to substitute for more robust firewall rules or active filtering, but it is easy to set up.

First, create a username and password in a file that .htaccess can read. This can be done on the bash command line using the htpasswd command:

htpasswd -c /path/to/htpassword/file name_of_user

Next, add the following to your .htaccess file. Be sure you reference the file you just created above:

AuthName "Protected Area"
AuthGroupFile /dev/null
AuthType Basic
AuthUserFile /path/to/htpassword/file
Require valid-user

For some more detailed information on .htaccess passwords, see this page.

Stay Patched

Make sure you’ve got an updated version of your operating system, your scripting language (PHP), your database (MySQL), and your software (WordPress, MODx, etc.). Sometimes applying patches can be scary, but it’s a lot less so if you’ve got those rolling backups in place!

I want to make mention of a very useful tool: SimpleScripts. It’s available on Bluehost accounts; it provides one-click installs of many web software packages (like WordPress and MODx) and it will alert you to update them when you log into your cPanel. It’s a real time-saver!

Clean your Room!

  • Do not install superfluous/untrusted software on your site! Don’t go dumpster diving for code that’s going to end up on a public-facing web site!
  • Shut down services you’re not using (e.g. blog posts) because it takes more time to secure them.
  • Do not store backups or sensitive data inside your document root!
  • Encrypt sensitive data
  • Check permissions.
Proper web site folder structure
Don't put backups or database dumps in your document root!

Make sure you organize your site’s files in a way that ensures that only you have access to sensitive data like backups or database dumps. These should NEVER be stored in the publicly viewable document root!

Cross Site Scripting

Behold the terror that is:

<?php print $_GET['x']; ?>

That code should NEVER be used on a public site because it effectively gives free access to the public to put whatever they want on your site! This type of code often sneaks into pagination links or into code that re-populates forms, e.g.:

<input type="text" name="myfield" value="<?php print $_POST['myfield']; ?>" />

where the ‘myfield’ variable contains something like:
" /> <script src=""></script>

For a list of values you might want to try pasting into form fields to see if they are secure, check out this great cheat sheet at

In the end, be REALLY aware of any user-submitted data. Users can put their own data into ANY form field, and into any cookie, so anything in the $_GET, $_POST, or $_COOKIE arrays (and also the $_REQUEST array) is inherently insecure and should be carefully filtered. These are like the STDs of the web!!!

For articles about web hacks and some good real-world examples, check out other articles on

Don’t Take Cookies From Strangers!

If you thought cookies were somehow immune to the area of security threats, they are not! It’s easy to write your own! The Firefox Web Developer plugin lets you easily create your own cookies. This is great as a web developer, but it can also be a sneaky tool for a hacker to introduce unintended code to your application, so filter cookie contents as carefully as you would the user-submitted forms.

Cookies also store the PHP session id; all $_SESSION data is stored on the server, but the unique key that associates that data with the user is stored in the user’s cookie. If one user authenticates, it’s possible for another user to make requests using that $_SESSION id! Especially with applications that require a login, it’s good practice to get a new session id using session_regenerate_id().

Filtering data

Every time you submit form data, you should write your regular expressions very carefully so your application accepts ONLY clean, valid data. In general, if you can keep input as simplistic as possible, it tends to be easier to secure. Integer only inputs are “safer” than alphabetic inputs. Alphabetic input is safer than input that accepts HTML tags, and so on.

Consider the following filters:
Type-Casting to force integer only values:
$x = (int) $_GET['x'];

Alphabetical Characters Only:

// Accepts only letters a-z (case insensitive)
function alphabetical($str)
if ( preg_match('/^([a-z])+$/i', $str) )
return $str;
return FALSE;

For PHP coders, get familiar with the preg_replace() function: it offers a more standard regular expression syntax (the often emulated Perl syntax). Also have a look at the strip_tags() function.

Frame Buster

A common trick used in phishing scams or to perpetrate click fraud involves iframe-ing a site. Basically, the “trick” relies on the HTML iFrame tag to make one site display the contents of another without being obvious to the casual user.

One partial solution to this common attack vector is to use some simple javascript that checks to ensure that the page the parent page and not being iFramed:

if (top.frames.length!=0)
// -->

Do a Google search for “frame buster javascript” to find other examples.

SQL Injection

This is a very broad topic, and there are numerous ways that SQL-injection might be used to compromise a site, but they all rely on the same principle: you construct strings of SQL statements and issue them against your database. If a malicious user is able to put his own data into one of those strings, it’s possible that a user can execute queries on your database that you never expected. This often gets back to form-validation and the ever important task of filtering user-submitted data!

Here’s a not-so-hypothetical PHP example:

$username = $_POST['username'];
$sql = "SELECT * FROM `users` WHERE `username`='$username'";

where $username contains something like:
'; INSERT INTO users (username, password) VALUES ('hacker_dude', MD5('xxxxxx') )

When that executes, 2 different queries are sent to the database instead of one, and if your’e not careful, it can allow an attacker to gain access to parts of your site and delete or steal data.

One strong line of defense against this type of attack is using a robust database driver that allows for the use of prepared statements (available since MySQL 4.1): where you prepare a statement once, then execute it multiple times with only certain defined variables changing. What this does is it allows you to define your query and only let the user supply the variables to be used in that query. This is a much more sensible option than letting the user essentially construct the query from scratch.

More mature database driver libraries (such as phpmysli) will allow you to use prepared statements.

You should also get familiar with escaping quotes in your database queries; this isn’t anywhere as effective as using prepared statements, but sometimes you have to use statements that aren’t prepared, so get familiar with how to escape strings before sending them to the database. In PHP, use the mysql_real_escape() function.

Finally, consider setting up special database users and roles to handle different types of queries. If a query is hijacked, it can only execute with the same permissions as the database handle. In other words, you wouldn’t grant delete or insert permissions to a database handle that was used only for selecting data. It’s more work to set up your database handles this way, but it may help prevent an attack from succeeding.


Watch your cornhole. There’s a lot going on a web site, and there are a lot of ways to abuse the technologies that run them. If you understand how the exploits occur, you’ll be better prepared to prevent them.

]]> 2