cPanel. Raising the virus scanner AiBolit

cPanel. Raising the virus scanner AiBolit

The goal was to allow clients to scan their sites for malicious code. The scanner used was the Ai-Bolit fort scanner, which can be found at the link: https://github.com/rorry47/ai-bolit.git

First of all, let's create a folder on the server:

mkdir /usr/local/cpanel/base/frontend/jupiter/ai-bolit

Next, we will write the code that will download the scanner archive, unpack and display the client part of the functionality.

Let's create a file:

touch /usr/local/cpanel/base/frontend/jupiter/ai-bolit/index.live.php

And write the code in it:

<?php
require("/usr/local/cpanel/php/cpanel.php");
$name_a = 'ai-bolit-hosterv5.1.zip';
$url_name_a = 'https://example.com/';
$cpanel = new CPANEL();
$USER = $cpanel->cpanelprint("\$user");
$AI_BOLIT_DIR = "/home/" . $USER . "/.ai-bolit";
$action = isset($_GET["action"]) ? $_GET["action"] : "";
if ($action == "download" || $action == "view") {
        $time = isset($_GET["time"]) ? $_GET["time"] : "";

        if (preg_match("/^\d+$/", $time)) {
                $file = $AI_BOLIT_DIR . "/reports/report-" . $time . ".html";
                if (file_exists($file)) {
                        if ($action == "download") {
                                header("Content-Type: application/octet-stream");
                                header("Content-Disposition: attachment; filename=" . basename($file));
                        } else {
                                header("Content-Type: text/html");
                        }
                        readfile($file);
                }
        }
} else {
        if (!file_exists($AI_BOLIT_DIR)) {
                mkdir($AI_BOLIT_DIR);
                mkdir($AI_BOLIT_DIR . "/ai-bolit");
        }

        if (file_exists($AI_BOLIT_DIR . "/" . $name_a) && time() - filectime($AI_BOLIT_DIR . "/" . $name_a) > 604800) {
                exec("rm -rf " . $AI_BOLIT_DIR . "/{" . $name_a . ",ai-bolit}");
        }

        if (!file_exists($AI_BOLIT_DIR . "/" . $name_a)) {
                exec("wget -O " . $AI_BOLIT_DIR . "/" . $name_a . $url_name_a . $name_a);
        }

        if (!file_exists($AI_BOLIT_DIR . "/ai-bolit/ai-bolit-hoster.php")
                || !file_exists($AI_BOLIT_DIR . "/ai-bolit/AIBOLIT-WHITELIST.db")) {
                exec("unzip -o " . $AI_BOLIT_DIR . "/" . $name_a . " 'ai-bolit/*' -d " . $AI_BOLIT_DIR);
                //$content = file_get_contents($AI_BOLIT_DIR . "/ai-bolit/ai-bolit-hoster.php");
                //$content = preg_replace("/href=(\\\\)?\"https?:\/\/.+?(\\\\)?\"/",
                //        "href=$1\"https://revisium.com/ru/clean/?pro=800580$2\"", $content);
                //file_put_contents($AI_BOLIT_DIR . "/ai-bolit/ai-bolit-hoster.php", $content);
        }

        if (!file_exists($AI_BOLIT_DIR . "/reports")) {
                mkdir($AI_BOLIT_DIR . "/reports");
        }

        $proc_run = false;
        if (file_exists($AI_BOLIT_DIR . "/ai-bolit.pid")) {
                $pid = file_get_contents($AI_BOLIT_DIR . "/ai-bolit.pid");
                if (exec("ps --no-heading -P " . $pid . " | wc -l") > 0) {
                        $proc_run = true;
                } else {
                        $proc_run = false;
                }
        }

        if (!$proc_run && isset($_POST["scan"])) {
                $pid = exec("nohup /opt/cpanel/ea-php74/root/usr/bin/php " . $AI_BOLIT_DIR . "/ai-bolit/ai-bolit-hoster.php --path=/home/" . $USER
                        . " --report=" . $AI_BOLIT_DIR . "/reports/report-" . time() . ".html --progress=" . $AI_BOLIT_DIR
                        . "/progress.json --smart --skip=jpg,jpeg,png,gif,svg > /dev/null 2>&1 & echo $!");
                file_put_contents($AI_BOLIT_DIR . "/ai-bolit.pid", $pid);
        }

        echo $cpanel->header(iconv("Scanner AI-Bolit", "UTF-8", "CP1251"), "ai-bolit");

        if ($proc_run || isset($_POST["scan"])) {
                if (file_exists($AI_BOLIT_DIR . "/progress.json")) {
                        $progress_data = file_get_contents($AI_BOLIT_DIR . "/progress.json");
                        $progress = json_decode($progress_data, true);
                } else {
                        $progress = array("progress" => 0);
                }
                echo "<script>setTimeout(function() { location = \"index.live.php\"; }, 2000);</script>"
                        . "<div class=\"cjt-pagenotice-container cjt-notice-container\" style='border-radius:20px'><div class=\"yui-module cjt-notice cjt-pagenotice cjt-notice-info\" style='border-radius:20px'><div class=\"bd\" style='border-radius:20px'><div class=\"cjt-notice-content\"><span id=\"resellerSpinner\" class=\"fas fa-spinner fa-spin updating-elements\" title=\"Loading …\" ng-hide=\"updated\"></span> The folder is currently being scanned /home/" . $USER . ", scanned <b>" . $progress["progress"]
                        . "%</b> files.</div></div></div></div>";
        } else {
                echo "<form method=\"post\"><button type=\"submit\" name=\"scan\" class=\"btn btn-primary\" style='border-radius:20px'><span class=\"glyphicon glyphicon-eye-open\"></span> Scan folder <b>/home/" . $USER . "</b></button></form>";
        }

        exec("find " . $AI_BOLIT_DIR . "/reports -mindepth 1 -maxdepth 1 -type f -name 'report-*.html' | sort -r", $reports);
        echo "<hr>";

        if (empty($reports)) {
                echo "There are no reports because the scan has not yet been performed or the reports have been deleted.";
        } else {

        echo "<h2 id=\"hdrMainAcct\">Folder Scan Reports <b>/home/" . $USER . "</b></h2>";

        echo "<div class=\"table-responsive\">
        <table id='mainwebdavtbl' fixedtruncate='1' class='truncate-table sortable table table-striped'><thead><tr>
                <th class=' clickable'>Date</th>
                <th class=' clickable'>View</th>
                <th class='sorttable_nosort'>Download</th>
            </tr></thead>
            <tbody>";
        for ($i = 0; $i < count($reports); $i ++) {
                preg_match("/^\/home\/" . $USER . "\/\.ai-bolit\/reports\/report-(\d+)\.html$/", $reports[$i], $matches);
                echo "<tr><td><span class=\"glyphicon glyphicon-time\"></span> " . date("Y-m-d H:i:s", $matches[1]) . "</td><td> <a class=\"glyphicon glyphicon-search\" href=\"?action=view&time=" . $matches[1]
                        . "\" target=\"_blank\" title=\"View\"></a></td><td><a class=\"glyphicon glyphicon-download\" href=\"?action=download&time=" . $matches[1] . "\" title=\"Download\"></a></td>";
        }

        echo "</tbody><tfoot></tfoot></table></div>";

        }

        echo $cpanel->footer();
}

$cpanel->end();

Notice two variables:
$name_a - scanner archive file name.
$url_name_a - site\link from which you can always download this archive for the script.

🤔
In this case, I simply created a simple account on the cPanel server and uploaded the archive with the scanner to the root folder, thereby the script always downloads the archive from the link: https://example.com/ai-bolit-hosterv5.1.zip

Next, go to the WHM panel of our server: https://123.123.123.123:2087

Let's go along the way: Home -> Development -> cPanel Plugin File Generator Documentation:

Filling out the fields, example:

Name: Scanner AI-BOLIT
Group: security
URI: ai-bolit/index.live.php

On the server in the folder /var/cpanel/cpanel_plugin_generator/ the archive will appear. This is a generated application that needs to be installed. So we run the command:

cd /var/cpanel/cpanel_plugin_generator/
/usr/local/cpanel/scripts/install_plugin ai-bolit.tar.gz

Now we go to the cPanel account from the client and we will see that we have created an additional field:

If you go there, you can scan your entire account for malicious scripts and download or view the report:

🫢
Please note that this script only scans and collects information about the presence of malicious scripts or files, it does not remove the vulnerability.

Thanks to all. Good luck 😊