
Why PHP Is Best For Website Development
In this blog I will show you how to implement some great security using Apache, .htaccess ,Php , MYSQL, A reputation API , AND OPTIONALLY Firewalld to your site for protecting your site from hackers and networks with bad intentions
Before I continue Cyford Technologies LLC holds no responsibility for anything. Doing something wrong can further create risk or break something. We do have professionals that can do this for you as well.
If you’re using a shared hosting or do not have root access, then I am not sure u will be able to create firewall rules. later I will add a .htaccess for blocking IP’s in this case.
My security was mainly made for OpenCart shopping cart and is used on https://TiresDB.com | | https://onlinemerchantstore.com | https://onlinetirediscounts.com | https://victoriasworldofgifts.com
This can be easily implemented in other frameworks that only use index.php as the target file for all pages. Other frameworks that do not include from index will need more modifications in htaccess
- If your server is already compromised then I would suggest,
- Changing the root password,
- Delete all unknown system users.
- Setup firewall to only allow SSH from your network.
- Compare files from original framework.
- Backup all files.
- Delete files that look suspicions and is not included in the original framework.
- (use this tool to track all user activities with bad reputation to see what further to block)
- Remove MariaDB/mysql users that are not needed
- Make sure only db users can be used from localhost or 127.0.0.1
This Document and scripts is still in the process of being developed.
Some understanding of PHP , apache, and LINUX should be understood to make this work. I will be making it easier and stronger as I catch other hackers behaviors and test
To my knowledge no one else is using security like this, I post this article too the public not only help people needing security but to welcome all hackers and test vulnerabilities. Cyford Technologies LLC site does not implement these securities as of now because it is not a shopping cart and does not use OpenCart however it is behind a untangle firewall which checks every packet and URL and manages IP reputations as-well. I strongly stand by UNTANGLE if you run a complete network an not just a server. Most traffic can be blocked before reaching your server in which a lot of resources will be saved allowing more visitors.
I believe most of these rules if not all can also be created by fail2ban in which I also use but mainly for SSH MariaDB connections against authentication and pre-made apache rules but this is only for blocking IP without knowing the reputation and lacking tools like redirecting users based on conditions and many other helpful tools.
In web development I believe this to be the best strategy.
PART 1
First step is to have htaccess allow pages that are clearly normal browsing
This is done in the file /.htaccess (this is assumed Apache is configured to allow .htaccess)
I start it off by checking GET POST PUT DELETE from browser.
<Limit POST GET PUT PATCH DELETE>
</Limit>
If one of these is used, then I create a rewrite rule.
<Limit GET POST PUT DELETE>
<IfModule mod_rewrite.c>
</IfModule>
</Limit>
Now I believe this is practically every browser’s request, but if u don’t need to monitor GET request just simply remove it from the limit. I added it because I am using further filters to add more control.
I will start by adding exceptions so htaccess will not block good Uri’s (keep in mind this is for OpenCart) . I will be using TiresDB.com for my example.
A php file named /trap.php needs to be added to the root directory
/.htaccess
<Limit GET POST PUT DELETE>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/$
RewriteCond %{REQUEST_URI} !^/catalog/
RewriteCond %{REQUEST_URI} !^/image/
RewriteCond %{REQUEST_URI} !^/admin/
RewriteCond %{REQUEST_URI} !^/terms
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} !^route=product
RewriteCond %{REQUEST_URI} !^/trap.php
RewriteCond %{REQUEST_URI} !^/favicon.ico
RewriteCond %{REQUEST_URI} !^/robots.txt
RewriteCond %{HTTP_HOST} ^tiresdb.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.tiresdb.com$
RewriteRule (.*)$ https://%{HTTP_HOST}/trap.php?target=https://%{HTTP_HOST}%{REQUEST_URI}&reffer=%{HTTP_REFERER} [QSA,R=301,L]
</IfModule>
</Limit>
Now this block of code is telling Apache to handle all browser request but ignore anything that has nothing specified after root directory like https://tiresdb.com/
It also ignores catalog, image, which are includes from OpenCart framework
It ignores /admin/ in which I have a different .htaccess protecting that directory
It ignores /trap.php in which we need to send the bad people too
It ignores other things that we don’t mind showing /robots.txt , /favicon.ico , /terms
Of course, we need to ignore the main home page /index.php
route=product was used for testing when I thought index.php may have been compromised. I wanted to catch all index.php unless it was a user viewing the product pages, but it can be ignored
Now our htaccess is sending anyone scanning for vulnerabilities too our trap.php , right where we want them too to be, it passes the requested and refer website so we can document and add further conditions or redirects.
Part 2
Now that we have apache monitoring the traffic lets set our Database tables
CREATE TABLE `cy_trap` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`ip` varchar(45) DEFAULT NULL,
`browser` varchar(445) DEFAULT NULL,
`os` varchar(45) DEFAULT NULL,
`target_url` varchar(45) DEFAULT NULL,
`from_url` varchar(445) DEFAULT NULL,
`data` text DEFAULT NULL,
`message` varchar(45) DEFAULT NULL,
`fraud_score` int(11) DEFAULT NULL,
`country_code` varchar(45) DEFAULT NULL,
`region` varchar(45) DEFAULT NULL,
`city` varchar(45) DEFAULT NULL,
`ISP` varchar(45) DEFAULT NULL,
`ASN` varchar(45) DEFAULT NULL,
`operating_system` varchar(45) DEFAULT NULL,
`organization` varchar(45) DEFAULT NULL,
`is_crawler` varchar(45) DEFAULT NULL,
`timezone` varchar(45) DEFAULT NULL,
`mobile` varchar(45) DEFAULT NULL,
`host` varchar(45) DEFAULT NULL,
`proxy` varchar(45) DEFAULT NULL,
`vpn` varchar(45) DEFAULT NULL,
`active_vpn` varchar(45) DEFAULT NULL,
`active_tor` varchar(45) DEFAULT NULL,
`device_brand` varchar(45) DEFAULT NULL,
`device_model` varchar(45) DEFAULT NULL,
`bot_status` varchar(45) DEFAULT NULL,
`connection_type` varchar(45) DEFAULT NULL,
`zip_code` varchar(45) DEFAULT NULL,
`latitude` varchar(45) DEFAULT NULL,
`longitude` varchar(45) DEFAULT NULL,
`request_id` varchar(45) DEFAULT NULL,
`time` timestamp NULL DEFAULT current_timestamp(),
`blocked` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`ID`),
UNIQUE KEY `ip_UNIQUE` (`ip`)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=latin1 COMMENT='trAP BAD PEOPLE AND GET DATA';
CREATE TABLE `cy_trap_details` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ip_id` int(11) DEFAULT NULL,
`browser` varchar(45) DEFAULT NULL,
`os` varchar(45) DEFAULT NULL,
`target_url` varchar(45) DEFAULT NULL,
`from_url` varchar(445) DEFAULT NULL,
`data` text DEFAULT NULL,
`time` timestamp NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=964 DEFAULT CHARSET=latin1;
Now lets add our rules in trap.php
<?php
$debug = 0;
if ($debug >0){
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
}
$browser = $_SERVER['HTTP_USER_AGENT'];
$agent = $_SERVER['HTTP_USER_AGENT'];
$lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$target =$_GET['target'];
$from =$_GET['reffer'];
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
if ($debug >0){
echo " <br><br><br><br><br><br> ";
var_dump($ip);
echo " <br><br><br><br><br><br> ";
}
// replace 8.8.8.8 with your ip for testing
if ($ip=="8.8.8.8"){
$debug = 9;
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
}
// db connection
//
you will need a mysql user. I would only give select insert and update permissions to the specific trap table
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = mysqli_connect("127.0.0.1", "trap", "trap", "OTD");
// check if user exists in local db
$sql = "SELECT * FROM OTD3.cy_trap where ip ='$ip';";
if ($debug >0){
echo($sql);
}
$result = $conn->query($sql);
if ($debug >0){
echo " <br><br><br><br><br><br> ";
}
if ($result->num_rows >0){
$row = $result->fetch_assoc();
if ($debug >3){
var_dump($row);
}
$sql ="INSERT INTO `OTD3`.`cy_trap_details` (`ip_id`,`target_url`, `from_url`) VALUES ('$row[ID]', '$target', '$from');";
$exec= $conn->query($sql);
// end of getting api details and adding to db
if (mysqli_error($conn) > 0)
{
echo "<br><br>there has been a mysql error<br><br>";
}
// Condition if network is very bad . these guys need to be blocked
if ($row['fraud_score'] >= 80){
if ($debug >8){
// adding a fake ip to test firewalld blocking
$fakeip = "192.168.55.111";
$ip = $fakeip ;
}
echo "Your $ip is logged for Suspicious Activity !<br> ";
echo " <br><br><br><br><br><br> ";
$output=null;
$retval=null;
// these next commands are for firewalld rules. you will need root access to update visudo and give apache access to run firewalld-cmd rules (in the process of only allowing reject rules for added security)
$command = "sudo firewall-cmd --permanent --add-rich-rule='rule family='ipv4' source address='$ip' reject' ; sudo firewall-cmd --reload";
exec($command , $output, $retval);
echo "Returned with status $retval and output:\n";
if ($debug >7){
print_r($output);
}
$sql = "UPDATE `OTD3`.`cy_trap` SET `blocked` = '1' WHERE `ip` = '$ip'; ";
$exec= $conn->query($sql);
exit();
//print_r($command);
}
if ($row['fraud_score'] > 20){
echo "Your $ip is logged for Suspicious Activity !<br> ";
echo " <br><br><br><br><br><br> ";
header("Location: https://victoriasworldofgifts.com/index.php?route=common/home");
exit();
}
}else{
// get api data. an account needs to be created from https://ipqualityscore.com to get host details
$ch = curl_init();
$url ="https://ipqualityscore.com/api/json/ip/zlkijhiklhlkjhnkjhnklbhn/$ip?strictness=1&user_agent=$agent&user_language=$lang;";
curl_setopt($ch, CURLOPT_URL,"$url");
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$api_results = json_decode(curl_exec($ch),true);
curl_close ($ch);
echo " <br><br><br><br><br><br> ";
if ($debug >3){
var_dump($api_results);
}
// stop google from being blocked
if (strpos($api_results['ISP'], '.googlebot.com') !== false) {
$api_results['fraud_score'] =0;
}
$sql = "INSERT INTO `OTD3`.`cy_trap` (`ip`, `browser`, `target_url`, `from_url`, `data`, `message`, `fraud_score`, `country_code`, `region`, `city`, `ISP`, `ASN`, `operating_system`, `organization`, `is_crawler`, `timezone`, `mobile`, `host`, `proxy`, `vpn`, `active_vpn`, `active_tor`, `device_brand`, `device_model`, `bot_status`, `connection_type`, `zip_code`, `latitude`, `longitude`, `request_id`) VALUES ('$ip', '$browser', '$target', '$from', '$agent', '{$api_results['message']}' , '{$api_results['fraud_score']}', '{$api_results['country_code']}', '{$api_results['region']}', '{$api_results['city']}', '{$api_results['ISP']}', '{$api_results['ASN']}', '{$api_results['operating_system']}', '{$api_results['organization']}', '{$api_results['is_crawler']}', '{$api_results['timezone']}', '{$api_results['mobile']}', '{$api_results['host']}', '{$api_results['proxy']}', '{$api_results['vpn']}', '{$api_results['active_vpn']}', '{$api_results['active_tor']}', '{$api_results['device_brand']}', '{$api_results['device_model']}', '{$api_results['bot_status']}', '{$api_results['connection_type']}', '{$api_results['zip_code']}', '{$api_results['latitude']}', '{$api_results['longitude']}', '{$api_results['request_id']}');";
if ($debug >3){
var_dump($sql);
}
$exec= $conn->query($sql);
// end of getting api details and adding to db
if (mysqli_error($conn) > 0)
{
echo "<br><br>there has been a mysql error<br><br>";
}
if ($row['fraud_score'] >= 80){
if ($debug >8){
// adding a fake ip to test Firewalld blocking
$fakeip = "192.168.55.111";
$ip = $fakeip ;
}
echo "Your $ip is logged for Suspicious Activity !<br> ";
echo "<br><br><br><br><br><br> ";
$output=null;
$retval=null;
$command = "sudo firewall-cmd --permanent --add-rich-rule='rule family='ipv4' source address='$ip' reject' ; sudo firewall-cmd --reload";
exec($command , $output, $retval);
echo "Returned with status $retval and output:\n";
print_r($output);
$sql = "UPDATE `OTD3`.`cy_trap` SET `blocked` = '1' WHERE (`ip` = '$ip'); ";
$exec= $conn->query($sql);
exit();
//print_r($command);
}
}
$conn->close();
?>
Now what this script starts off doing is setting an debug session for testing.. probably not good to show your hackers what your doing, so all testing output is enabled when $debug > 0; (1-9).
Later I have also added condition based on your IP address. This is mainly so u can test conditions that only show when u hit the page.
$browser = $_SERVER['HTTP_USER_AGENT'];
$agent = $_SERVER['HTTP_USER_AGENT'];
$lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$target =$_GET['target'];
$from =$_GET['reffer'];
Now that we set variables and testing environment , why not get as much information about the user as possible. Keep in mind most of this information can be spoofed as-well. Now target and from URL’s we can not get from this php page because we have redirected the user already so that’s why we made htaccess send it as a $_GET variable in which we can retrieve using $target =$_GET[‘target’]; and $from =$_GET[‘reffer’];
Time to get the IP Address now. IP’s can be a bit more tricky when your webserver is behind a proxy or cache servers. so we can add a condition to check an use the appropriate IP.
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
now it is time to see if the user has been here before. lets connect to our DB and check if there IP is in a table
If their IP exists we have condition that inserts target page and from page too a child table.. this allows us to monitor a history for research.
Can also see how clever your hackers are

our parent table would look like this

As of now I only have conditions for IP with reputations >80 However my stores are us based only, I will probably make conditions if user is in any other country to not accept traffic if there score is above 29. the issue with this is most other countries only use DSL which IP changes frequently so good users can easily have a bad IP… but thanks to our htaccess we are only trapping users that are trying to go to pages they have no business going. as of the moment, the only flaw to this design is the possibility that bots and good automated traffic gets blocked as well trying to see if spam exists on your site.. but hey , they shouldn’t have a bad IP reputation anyway.
Now that we know if the IP has been logged here before we can set condition if (mysqli_error($conn) > 0){}
If IP is found, the next step is to see what we logged as the reputation fraud_score if > 80 we will activate our optional Firewalld rules
we can redirect them too the home page. get them back on track and hope they be good
ether way we log the user in the database.
Ok now lets assume the user has not visit us before. We know that they’re fishing for pages that do not exists or pages that are not allowed. we know the browser details that is being sent too us, we also know there ip or proxy , vpn , tor in which there using to connect to us. what we do not know is the reputation of the network there using. so lets get this
as of now we will be using ipqualityscore.com in our example. Soon Cyford Technologies LLC will offer these services specifically for this tool. we send a ip, user agent and Lang to them and they in return give us the quality of this ip,
We store all information in Database:
IP’s blocked so far

then we can run all conditions we want based on there reputation.
- Things I will be working on in the future:
- Adapting this security to other types of websites
- Allowing htaccess to block IP’s automatically without using Firewalld
- Option for email notifications to admins
- Landing page that allows visitors to contact you if blocked by mistake
- adding conditions based on country
- giving apache rights to create firewall rules would be a security risk in itself if there is already compromised files on the webserver
- I will be adding a function that white list all specified good ip’s
- I will be making a way for apache user to only run Firewalld in reject command – so other users can not grant access with it
- will be adding a feature to notify ISP of there hacked users
- will be adding function to notify the FBI
- whitelist ip address so that this rule is not effected for curtain networks in htaccess
My History:
I was brought to create this security because I was hacked by people from my password being exposed on the dark web. The users would add compromising files that my developers was missing, they would change permissions on the files as if apache had written them , having us believe it may of been a compromised /admin or another php page. They have changed .htaccess even when we restricted the user apache from writing too it. this let me to believe one of our pc was hacked and our pc was being used to change server files.. I immediately changed the password of root on my server and watched fail2ban ban ip’s still trying to use the old password. This is how I was aware they was connecting as root,. more then likely they was using SCP because I did not see any terminal or ssh logs from anywhere else other then my ip. After knowing this I only allowed ssh on my ip and blocked it from the rest of the world. Usually I always do this, however my server is in Australia and I moved around a lot before. Now all employees vpn .Vpn is required for ssh on all my networks
All security used in conjunction
- untangle
- cloudflare cloud DNS + filtering
- Firewalld server security
- fail2ban authentication blocking
- google ads security
- checkout security for shopping carts
Published on: May 03, 2021
5 website development tips comment I added