-->

Why PHP Is Best For Website Development

Securing OpenCart
Securing OpenCart

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

after hackers try a few times with a different ip they give up even when they have a whole block at there disposal

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

Categories: Web Development

Leave a Reply

Your email address will not be published.