After my own site was attacked this is great advice from 25yearsofprogramming.com (now offline). This article discusses how to prevent your site from getting hacked, how to repair a damaged site plus website security precautions.
The reason these procedures are described in so much detail is so that people who have never done them don't have to go hunting around the web for specifics. If you already know the specifics, you'll see that the steps are much less complicated than they look at first glance, and you can skip the long explanations.
If you just start at step 1, focus, and dive in, what you learn now will help you manage your site with a lot more confidence in the future. These are all useful things to know how to do. You might even wind up feeling like an expert.
I have had problems with Joomla and WordPress sites being hacked in the past. Rather than search for the corrupt code it's easier to redo the site with a fresh install. Read more…
Don't just repair the damaged files and hope this experience doesn't happen again. That is not enough.
Nobody is ever supposed to be able to add, delete, or change files in your website without your permission. It should never happen, and it usually doesn't. Most websites don't get hacked. If yours did, there is something wrong with it, or with the server, or with the webhost, or with the security on your PC. You have to figure out how this happened so you can prevent it from happening again.
Log into cPanel and check the line that says "Last login from:". This should always be your IP address from the last time you logged in.
If someone was able to log in to your control panel (like you do), they have your userID, password, and all the same access to your site that you have. They can probably also get FTP access, which is what they are more likely to use than cPanel. However, before you assume the worst, an unfamiliar IP could be legitimate if your site is at a web-hosting company and you recently submitted a support ticket. A technician might have logged into your account while investigating.
Leave cPanel open for the next two steps.
Your website access logs keep detailed records of who connects to your site by HTTP (normal visitors) and by FTP (file transfers such as when you publish pages). By default, those logs are deleted every day after the stats run (Webalizer, AWStats, ...). Log archiving forces the logs to be saved. If archiving was already on, the attack is most likely recorded, which will be useful. If it was off, the data is lost unless the daily stats run hasn't been done yet, but subsequent similar attacks, which are likely, will be logged.
If your pages have become infected with viruses that will attack your site visitors, which is usually the case, you should protect your visitors, and your reputation, by taking your site offline, which involves adding a few lines to your .htaccess and optionally uploading a file. If you do this right away, you might avoid getting the "This site may harm your computer" warning in Google search results and a similar warning at Yahoo.
Are you hesitant to take your site offline? Consider this: a visitor who finds your site down will hardly notice the incident and will (or at least might) come back later. A visitor who gets attacked by a virus from your site will develop a strong memory of the incident and probably not come back, ever.
In addition, it is possible that a script with a security hole was the reason the site got hacked. As long as that script is publicly accessible, the site remains vulnerable, which means it could get hacked again even while you're trying to repair it.
Lastly, it is possible the attacker installed a backdoor script to let themselves back into the site. Closing the site at least has a chance of locking them out and making it impossible for them to use the backdoor, giving you time to find and delete it.
File a support ticket.
It is a new development in 2009 that the #1 cause of website hacking is the webmaster's personal computer being infected by malware that steals FTP login information and sends it to remote computers which then inject the victim website's pages with JavaScript or hidden iframes pointing to malicious websites such as gumblar.cn, martuz.cn, and a growing list of others.
Make sure everyone who has password access to the website does at least one, and preferably two, antivirus and anti-spyware scans on their local computers, using two different scanners they don't normally use, to find threats that got past the AV scanner they were using. Some free scanners are at: Trend Micro Housecall, Panda Security, Malwarebytes, Symantec (Norton), BitDefender, McAfee, and F-Secure.
As long as the webmaster's PC is infected, changing the password is no use. The new one gets stolen, too.
After the administrator PCs are free of viruses and spyware, change all the website passwords that you use for control panel, FTP, database connections, email, everything. Use strong passwords. If you have been using a single password for more than one purpose, take this opportunity to make every password different. The linked article explains why this is important.
In cPanel, look for a "Change Password" icon or link. If you find none, your web-host might provide a separate login location for making password changes, so search their FAQ, forum, or ask customer support.
If you have scripts that use your cPanel userID/password to open database connections, the password change will cause those scripts to stop working, and you will get connection failure or "Could not connect" errors:
If your scripts connect to your databases as a user that is not your cPanel userID, the password change will not break your scripts. However, the hacker could have read the connection data for all your MySQL users from your files, so change all those passwords too.
Make a list of all the scripts you use. For each, if you are not using the latest version, upgrade now.
The "What is a website hack?" article (top of this page) has more information about the following three most common exploits of custom code, and some others:
The following PHP functions:
include($variable);
require($variable);
include_once($variable);
require_once($variable);
can be tricked into fetching a malicious script from a remote server and running it as part of the currently executing script if the value of $variable came from an HTTP query string or other user-supplied input and if the value supplied is a URL (web address) rather than the value that the programmer expected.
They can be tricked into divulging the contents of password or other sensitive files if the supplied value of $variable is a local file path on the server.
When an HTTP query string, or any other data from the outside such as input to a search box, is used in the building of an SQL database command string, maliciously crafted input can corrupt the SQL command, causing it to inject content into database tables or list the contents of the database (such as user names and passwords) on the output page. A widespread attack that used SQL injection was called ASPROX.
If you suspect that a script you wrote yourself might be the security weakness, it is safest to stop using that script until you can examine it carefully. After making a local copy for yourself, delete the script from the server. Removing the links to it isn't enough. As long as the script is on the server, anyone who already knows its name can still access and exploit it. If you leave it on the server, at least rename it.
Now that you have discovered where the security weakness was, and fixed it, it is now safe to repair your website's content, because the attackers won't be able to damage it again.
As described in the "What is a website hack?" article (top of this page), after someone has gained access to your site, they can change anything they want and can do an extraordinary amount of damage. In order of most to least common:
However, they rarely do all those things because a server so massively compromised would be quickly noticed, and they don't want that. Usually, they do the first or second item and possibly the third, meaning that you will probably have to clean up malicious changes in your website files or database tables, and look for new files that shouldn't be there.
Two "clean sweep" shortcuts: replace entire website from known-good backups
Steps 9a) to 9d) describe ways to locate and repair files that have been maliciously altered, which can be a time-consuming and painstaking chore, especially if you're not comfortable working with HTML code.
In some cases, it can save time to simply replace everything that might have been damaged with fresh copies that you know are clean. However, doing this destroys the evidence you might need for determining how the attack occurred and how to prevent it happening again. Therefore, before doing this, you should already have a clear idea why the attack succeeded, or should make a copy of the hacked site so you can study it later:
If you have published your site from known-good backups, you can skip a ton of trouble and go to Step 10)!
These sections (9abc) describe three ways to view a list of all the files in your website: shell command (cron), FTP, and cPanel File Manager.
Linux "cron" allows you to run a shell command that emails to you a complete listing of all the files in your site, showing for each the name, timestamp, size, owner, and all the permissions settings. This is by far the best method.
How to use the directory listing:
It is ideal if you have a similar list that you made previously when the site was clean. You can compare the two to find files that have changed size, files whose timestamps or permissions are not what they should be, and new files that shouldn't be there.
If you don't have a known-good list to compare against, you can still review the new list for files that seem out of place or have wrong ownership or permissions. This will be discussed below.
FileManager allows you to easily review filenames and permissions, but it doesn't show any other information about the files, and navigating up and down the directory tree is a tedious process. File and folder permissions are shown numerically. The article linked above at "Get a complete listing" describes how to translate between numeric "755" and "rwx" notation.
In an FTP view of your website, the folders and files look like what you are used to in Windows Explorer, with a navigational directory tree pane on the left and a folder contents pane on the right. FTP view is easy to navigate, and it allows sorting on the Date Modified column to easily spot recently changed files.
Using the complete file list you made, make sure file and folder permissions are what they should be. Although your complete file list is a text file, the search isn't too difficult. You can search for suspicious "world-writable" 777 folder permissions by searching for the equivalent "rwxrwxrwx" in the text. World-writable 666 file permissions appear in the text as "rw-rw-rw-".
Common correct permissions for world-readable (but not world-writable) folders are 755 (rwxr-xr-x), and common permissions for world-readable files are 644 (rw-r--r--). Those are what you should mostly expect to see.
There are only two situations where world needs write access (777 / 666), and both only apply if your server is configured with PHP as an Apache module:
If you find world-writable permissions on a file or folder, consider it potentially suspicious because those are areas the hacker could have accessed most easily:
In case someone was "watching" inside your site while you did it the first time, do it again now that you know the site is clean.
This is not to hunt down the attacker, which is usually pointless (most are robots, and there are millions of them). Rather, the IP address helps find other important information about the attack.
If you can identify their IP address, you will be able to search all your logs for all the places where that IP address appears. That will help identify what weak part of your site was attacked, how it was attacked, and what malicious actions were performed.
Stats programs like Analog, Webalizer, or AWStats won't be much help because they generate aggregated summary statistics. You need the details about individual page requests.
cPanel > Web/FTP Stats > Latest Visitors is useful and easy. It's a good place to go when you first discover the problem, but it's only a start. The raw log text files are a better source of information.
Your website's raw access logs are stored and sent to you as gzipped files. One program that will easily extract .gz files is 7-Zip. It is a command line utility that you run from a "Command Prompt" (aka "DOS box").
The log file location in Plesk has a similar name. If you don't have cPanel, Plesk, or a comparable control panel, you can usually get the logs by FTP, usually from a folder outside public_html, with "logs" or "access logs" in its name. Some shared webhosts don't provide access logs, or they charge an extra fee for them.
Go through the logs carefully, looking for suspicious activity in the days before the attack occurred, and keep monitoring your logs in case the hackers come back, which they often do.
Your HTTP log shows the visits to your site by HTTP, the request method normally used by ordinary visitors (using their browsers), robots, and hackers.
It's not always easy to determine which lines in an HTTP log are suspicious and which ones aren't. At my hack attempt identifier online calculator, you can paste lines from your HTTP log to find out which ones are hack attempts. It classifies the attempts by type so you can see what ways your site is being attacked, and it explains how the different types of attack work.
If you find suspicious changes made to your site (such as file timestamps that are not from when you changed the files yourself), you can try to correlate those changes with the suspicious entries in your log.
For example, a hacked file's timestamp will often show when the hack occurred (unless the hacker made a special effort not to change the timestamp). If your HTTP log shows a malicious request at the moment of the changed file's timestamp, that is very suspicious.
It could indicate that the file requested by the hack attempt had a security vulnerability that the hacker was able to exploit with their request. The exploitable file does not have to be the same file that was modified. The exploitable file is just the doorway to get at the other files. In this case, you would examine the requested file (not the modified file) for possible security vulnerabilities. This is how your logs can help identify how a hacker got in.
As another example, if you use a database, and if SQL injection attacks are the only type of hack attempt your site ever receives, SQL Injection becomes your primary suspect.
Your FTP log shows FTP accesses to your site. FTP stands for File Transfer Protocol. In contrast to HTTP, which is most often used to request files for viewing, FTP is a method of transferring files both to and from your server. It's normally used only by you, the site administrator, but if malicious people or robots manage to log into your FTP as you, they can download your pages, modify them, and upload them back to your website. The only IP addresses in the FTP log should be yours and other authorized FTP users. Make sure the timestamps match times you were logged in and doing transfers.
I've seen reports of numerous instances where a webhost spotted in an FTP log a transfer from an IP address other than that of the site owner and immediately informed the owner that their password had been stolen. In too many of these instances, the surrounding circumstances make the webhost's claim unbelievable. Here is an alternative explanation:
PHP scripts called by RFI attacks sometimes use PHP's FTP file transfer functions to download additional malicious scripts and related files from a remote server so it can run or install them. The initial RFI includes the remote script into a legitimate script on the victim server, at which point it becomes a part of that script. The script then initiates an FTP transfer, which is recorded in the FTP log. The server does not show its own IP address in the FTP log, but rather that of the second party to the transfer, the remote website. The log of the session makes it appear as though someone logged in (which would have required the password) and initiated an FTP transfer, but in fact there never was a login. There didn't have to be one, because the session was initiated on the server, from the inside.
Remember this as a possibility if you find IP addresses other than yours in your FTP log or if your webhost tries to convince you too quickly, without considering other evidence, that your password "must have been" cracked. The danger of believing this easy story line (if it is not true) is that it can lead you to believe that all you have to do is change your password. However, if the real initiator of the FTP transfer was an RFI attack, changing your password won't help at all.
If you identified the hacker's IP address, one site where you can look it up to get more information about it is http://whois.domaintools.com/.
You can ban the IP address from your site using your public_html/.htaccess file. Apache documentation for this is at: http://httpd.apache.org/docs/1.3/mod/mod_access.html.
Review the instructions in a prior article for how to open .htaccess for editing. As described there, insert the following line in a part of the file that is not enclosed in HTML-like tags.
deny from nnn.nnn.nnn.nnn
The nnn's are the IP address to block.
If the hacker returns with a different IP that is in the same IP range (i.e. using the same ISP), you can block the whole range for a while, although that carries the risk of banning legitimate visitors, too.
The Apache documentation has instructions for banning a range. Some IP ranges are easily specified using a simple wildcard notation. Others ranges can only be successfully defined using "CIDR/netmask" notation. Although it looks intimidating, it's easy after the first time you do it.
d) If the hacker has obtained access to your cPanel or FTP, banning their IP address in .htaccess will NOT keep them out of cPanel and FTP.
If they have scripts that they call by HTTP, it will prevent them from doing that, but only until they log into cPanel and un-ban themselves in .htaccess.
Hacking is a violation of the terms of service for any legitimate webhost or ISP. If you can prove conclusively that someone is using a particular IP address for hacking (or spamming, too), you could report the incident to the webhost or ISP in hopes that they might shut the perpetrator down. The contact email is often abuse@ the company.
However, your chances of getting anywhere with this aren't very great. Even if you succeed, it's a drop in the bucket. Although you might feel as though you are in a battle of wits with a wily adversary, it is thousands of times more likely that you were hit by an automated drive-by attack that is playing a percentage game, with malicious requests being launched against millions of websites, from hundreds of malicious servers. If one is shut down, it's just a cost of doing business for them.
It is a more worthwhile use of your time to do everything you can to protect your site from all hackers, regardless of who they are, and understand that there will be a constant flood of attacks against your site.
Sections 1-6 are absolutely necessary. They do not require a lot of technical knowledge.
Someone who successfully infects your PC can use it to get into your website. That is very common.
Don't load your website with every cool script, gadget, feature, function, and code snippet you can find on the web. Any one of them could let a hacker into your site. Before you use something new, read its vulnerability report, and do a web search on it to see if people talk about it as a security hazard. Some add-ons and templates are actually designed to be malicious. Ways to avoid those are described by the Google Blogger Team in Keeping Your Blog Secure.
Once you have installed a script such as WordPress, SMF, Coppermine, phpBB, or any others, find a way to make sure you are notified quickly when security updates are released. Get on a mailing list, subscribe to an RSS feed, subscribe to a forum board, create a Google Alert, whatever you need to do. When a security update is released, install it within 1 day, if possible.
SSH, Secure SHell, gives you command line access to your server, allowing you to execute operating system commands from a remote location. Most webhosts don't allow their shared hosting customers to use SSH at all, but a few do. Resellers and those who manage dedicated servers do have SSH.
Each file and folder on your server has permissions settings that determine who can read or write that file, execute that program, or enter that folder. Your webhost initially created your webspace with secure permission settings on all files and folders.
Do not modify the permissions until you know what you're doing. Don't guess. One mistake can allow any other account on your shared server to put files on your site, or allow anyone in the world to put files there by first getting into a weaker website on your shared server and running a malicious PHP script from there.
People having trouble installing web applications on their site are sometimes told to try setting the Linux permissions to 777 (for folders) or 666 (for files). Those permission levels are sometimes necessary, but they are a hazard and should only be used for folders and files for which it's absolutely necessary and only during times when it's absolutely necessary. For example, sometimes 777 only needs to be used during installation or during configuration changes or software upgrades. At other times, the application might function just fine even if you change the permissions back to more secure settings. In other words, if you need to use insecure permissions, try to minimize the amount of time they are in effect. There is no reason to leave permission levels low all the time if you only need them to be that way occasionally. Also, if software installation instructions tell you to delete the installation script itself after use, remember to do it. If it's left on the server, someone else who knows it's there (or knows it should be there) can run it, just like you can.
These precautions are also absolutely necessary, but only if you write your own program code.
These are extra precautions that provide an additional layer of security. If you understand what this section is talking about, the discussion and code examples should help you to put some good protections in place. If you don't understand this section, don't worry about it unless you are under constant attack and other remedies have failed.
Download and examine your raw access logs. You will most likely find attacks of the types described in my articles. Even if the attempts are unsuccessful, your logs give early warning about what methods are being used, which gives you time to figure out how to defend against them. Here are some examples of how to block suspicious activity:
SetEnvIfNoCase User-Agent libwww-perl block_bad_bots
# to deny more User-Agents, copy the line above and change
# only libwww-perl, to match the new name.
deny from env=block_bad_botsSetEnvIfNoCase does a case-insensitive test of the User-Agent against a regular expression, which in this case is "contains libwww-perl". If it matches, it sets the variable block_bad_bots. The final line says if block_bad_bots was set (i.e. if the requestor matched any of the bad robots), deny the request and send a 403 Forbidden error instead. Regardless of what the bad robot was trying to do, it won't succeed.
# If the next line is already in your .htaccess, you don't need to add a 2nd one.
RewriteEngine On
RewriteCond %{QUERY_STRING} =(ht|f)tp:// [NC]
# Allow yourself, for SMF Forum Package Manager upgrades.
# Set it to your own IP address so you are the only one who won't be blocked.
#RewriteCond %{REMOTE_ADDR} !^111.222.333.444$ [NC]
RewriteRule .* - [F]To test: you should get a 403 Forbidden error when you try to go to:
http://yoursite.com?test=http://yoursite.com/anypage.htm
http://yoursite.com?test=ftp://yoursite.com/anypage.htmIf you have coded your pages so they use remote file includes from your own site or from some external site (such that your site receives requests, constructed by you, that have URLs in the query strings), my first advice is that you should try to stop doing that:
- Instead of sending your own site a request that has a URL in the query string, you can put in the query string a text string that the receiving page translates into a URL after it receives it. That way, your script can't be tricked by someone who sends it a malicious URL instead of one of the legitimate ones it expects.
If you must send your own site requests that have URLs in the query strings, you can use a more complicated .htaccess to allow your own remote file inclusion requests but ban others:
# FIRST, DISALLOW QUERY STRINGS CONTAINING MORE INSTANCES OF http:// # THAN WE EVER USE OURSELVES, TO LIMIT THE NUMBER OF TESTS WE MUST DO LATER. # THIS EXAMPLE ALLOWS ONLY INSTANCE PER QUERY STRING. RewriteCond %{QUERY_STRING} (.*http(:|%3A)(/|%2F)(/|%2F).*){2,} [NC] RewriteRule .* - [F] # NOW WE CAN TEST EACH INSTANCE AGAINST THE LIST OF SITES WE WANT TO ALLOW. # SINCE THIS IS A NEW REWRITE RULE, WE MUST TEST AGAIN WHETHER IT CONTAINS http:// RewriteCond %{QUERY_STRING} http(:|%3A)(/|%2F)(/|%2F) [NC] # THEN FALL THROUGH TO THE BAN IF IT IS NOT ONE OF THE SITES IN OUR ALLOW LIST. RewriteCond %{QUERY_STRING} !(http(:|%3A)(/|%2F)(/|%2F)(www.)?site1.com) [NC] RewriteCond %{QUERY_STRING} !(http(:|%3A)(/|%2F)(/|%2F)(www.)?site2.com) [NC] #ADD A LINE FOR EACH EXTERNAL SITE YOU WANT TO ALLOW TO APPEAR IN QUERY STRINGS. RewriteRule .* - [F]Allowing for more than one instance of http:// in your query strings is possible. It requires complex code that I can custom design for you if needed.
Other query string bans:
1) Malicious RFI attempts almost always have a question mark at the end of the query string. Ban any query string that contains a question mark. The first question mark (which marks the beginning of the query string) is not part of the query string, so only question marks after the first one will trigger the ban:
RewriteCond %{QUERY_STRING} (?|%3F) [NC]
RewriteRule .* - [F]2) Be creative: find other characteristics that are common in the attacks on your site but that are never present in legitimate requests. Be thorough: use every good ban rule you can think of. It is very satisfying to see an attack on your site and know that even though it only needed to trigger one ban rule to fail, there were six others in reserve that it would have triggered.
You can use FTP and/or cPanel > Backups. Keep the backup somewhere not on your server, such as on your local PC or a DVD. Even if your webhost does backups, make a separate set for yourself. Do a new backup whenever there is enough new content that you don't want to have to redo the work. Keep more than one "generation" of backups. For example, if you backup monthly, keep separate versions from 1 month ago and from 2 months ago. This guards against backing up your site after it's been infected but before you discovered it. You'll still have (hopefully) a slightly older backup that isn't infected. For the same reason, don't backup too often.
Your raw HTTP and FTP logs are an important source of information after an attack, but the logs are normally deleted each day. Enable archiving to allow them to accumulate and preserve the evidence after an attack. Periodically download and review the logs to see what kinds of attacks are being launched against your site. As is so often the case, becoming familiar with what is normal will help you detect when something is not. Accumulated logs can take a lot of disk space, so you might want to delete old ones from the server periodically.
If you do it now, it will be a baseline list of the files you can assume are supposed to be there. If your site gets damaged, the list will help you decide whether a file you don't recognize is new or is just a system file that you never noticed before.
Not just your pages, but the whole site, using FTP or File Manager or the complete file list you made. If you get used to what is normal, things that aren't will catch your attention.
If you use your cPanel userID and password for database connections in your scripts, then changing your cPanel password will instantly break all your scripts until you re-code them to use the new password.
Instead, create one or more new users, completely unrelated to your cPanel login, that your scripts can use for their database connections:
Now update your scripts so they use the connection data for this new user instead of your old cPanel user. However, ...
If each of your scripts has its own code block for database connection, then if you are hacked and have to change your passwords, you'll have to hunt through all your files to find every code block that needs changing.
Instead, put all your database connection code in one central location such as an include file that is well-protected from web access, and make all your scripts read it from there. There are examples and some discussion about how to do this in the User Contributed Notes at http://us.php.net/mysql_connect. You can protect your include file by putting it in a folder above public_html, or in any folder that is closed to web access by an .htaccess file, or by the other methods mentioned in the php.net Notes.
Unfortunately, none of these protection methods will keep your data safe from someone who has actually gotten into your site, but the new database connection method you have just created will make it easy to change your password (in just one place) if that does happen.
Hardening WordPress | Many tips for how to improve WordPress security, with links to more. |
Security FAQ at Joomla.org Help Site | An excellent source of security information whether you use Joomla or not. |
(from http://25yearsofprogramming.com/blog/20070705.htm, now offline)
You must be logged in to post a comment.