Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File System Journal #272

Merged
merged 28 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
97604d5
Gathering to csv.
svfcode Nov 5, 2023
93e1a13
New. FSWatcher. Analyze WIP.
svfcode Nov 11, 2023
437d890
Fix. Codestyle.
alexandergull Nov 14, 2023
238cb0a
Fix. Logger.
alexandergull Nov 14, 2023
25c3d80
New. FSW table template.
alexandergull Nov 14, 2023
4130569
Fix. Compare. Delete unzipped files.
alexandergull Nov 15, 2023
7cae9d8
New. Settings. FS Watcher on/off. Enabled by defaults.
alexandergull Nov 16, 2023
c82fb7f
Ref. FWWatcher. Lot of improvements.
alexandergull Nov 16, 2023
6905f4c
JS docs and refactoring.
alexandergull Nov 16, 2023
f3dafde
PHPCS fixes.
alexandergull Nov 16, 2023
e4a871f
PSALM fixes.
alexandergull Nov 16, 2023
3049648
Merge branch 'dev' into fswatcher
alexandergull Nov 16, 2023
7452da2
PSALM Fixes after dev merge.
alexandergull Nov 16, 2023
f18a7af
Merge remote-tracking branch 'origin/dev' into fswatcher
Glomberg Dec 6, 2023
a31df7b
Fix. FS Watcher. Logs directory listing prevented.
Glomberg Dec 6, 2023
5a31b86
Fix. FS Watcher. Selectors rendering fixed.
Glomberg Dec 6, 2023
bc341e9
Upd. Code. Gitignore updated.
Glomberg Dec 6, 2023
d945685
Fix. Code. Code style fixed.
Glomberg Dec 6, 2023
801868f
Fix: Code. Doc-blocks added, psalm notices fixed.
Glomberg Dec 6, 2023
7afe77f
Upd. FS Watcher. Manual creating snapshot button and logic implemented.
Glomberg Dec 6, 2023
6acf3a9
Upd. FS Watcher. Phrases moved to the separated class.
Glomberg Dec 6, 2023
3757764
Upd. FS Watcher. Ajax url fixed.
Glomberg Dec 7, 2023
613d0c3
Upd. FS Watcher. Layout fixed.
Glomberg Dec 7, 2023
ae18595
Upd. FS Watcher. Ajax url fixed #2.
Glomberg Dec 8, 2023
23d5933
Merge branch 'dev' into fswatcher
alexandergull Dec 18, 2023
a6c2da3
Mod. FS Watcher updates.
alexandergull Dec 19, 2023
633808f
Merge branch 'dev' into fswatcher
alexandergull Jan 17, 2024
cbb7c63
Fix. FSWatcher. Logs path protected.
alexandergull Jan 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ psalm.xml
/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/tests/
/lib/CleantalkSP/Common/Scanner/SignaturesAnalyser/tests/
/lib/CleantalkSP/Common/Scanner/SignaturesAnalyser/.github/
/lib/CleantalkSP/Common/FSWatcher/Storage/data/
/lib/CleantalkSP/Common/FSWatcher/logs/
25 changes: 24 additions & 1 deletion inc/spbc-settings.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use CleantalkSP\Common\FSWatcher\View\View;
use CleantalkSP\SpbctWP\Scanner\ScanningLog\ScanningLogFacade;
use CleantalkSP\Variables\Post;
use CleantalkSP\Variables\Server;
Expand Down Expand Up @@ -674,6 +675,11 @@ function spbc_settings__register()
'title' => __('Important File Monitoring', 'security-malware-firewall'),
'description' => __('Monitoring of the individual most important files of the site.', 'security-malware-firewall'),
),
'scanner__fs_watcher' => array(
'type' => 'field',
'title' => __('File System Journal', 'security-malware-firewall'),
'description' => View::getFSWatcherDescription(new \CleantalkSP\SpbctWP\FSWatcher\View\Phrases()),
),
),
),

Expand Down Expand Up @@ -898,6 +904,16 @@ function spbc_settings__register()
'ajax' => false,
'callback' => 'spbc_tab__summary',
),
// FSWatcher
'fswatcher' => array(
'type' => 'tab',
'title' => __('FS journal', 'security-malware-firewall'),
'icon' => 'spbc-icon-info',
'class_prefix' => 'spbc',
'ajax' => true,
'callback' => 'spbc_tab__fswatcher',
'display' => $spbc->settings['scanner__fs_watcher']
),
// Debug
'debug' => array(
'type' => 'tab',
Expand Down Expand Up @@ -1586,6 +1602,13 @@ function spbc_tab__summary()
echo '<br>';
}

function spbc_tab__fswatcher()
{
echo "<div class='spbc_wrapper_field'>";
echo \CleantalkSP\Common\FSWatcher\View\View::renderSelectors(new \CleantalkSP\SpbctWP\FSWatcher\View\Phrases());
echo '</div>';
}

/**
* Admin callback function - Displays current statistics
*/
Expand Down Expand Up @@ -2460,7 +2483,7 @@ function spbc_field_scanner__prepare_data__files(&$table)
$ws_string .= '</p>';
}
}
if ( ! empty($weak_spots['DENIED_HASH'])) {
if ( !empty($weak_spots['DENIED_HASH']) ) {
// collecting all kinds of code
$all_unique_weak_spots = array();
foreach ($weak_spots['DENIED_HASH'] as $_string => $weak_spot_in_string) {
Expand Down
Empty file modified lib/CleantalkSP/Common/CleantalkTools.php
100644 → 100755
Empty file.
137 changes: 137 additions & 0 deletions lib/CleantalkSP/Common/FSWatcher/Analyzer/Analyzer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php

namespace CleantalkSP\Common\FSWatcher\Analyzer;

use CleantalkSP\Common\FSWatcher\Logger;
use CleantalkSP\Common\FSWatcher\Controller;

class Analyzer
{
/**
* @return array|false
*/
public static function getCompareResult()
{
$first = filter_var($_POST['fswatcher__first_date'], FILTER_VALIDATE_INT);
$second = filter_var($_POST['fswatcher__second_date'], FILTER_VALIDATE_INT);

if ($first > $second) {
$tmp = $first;
$first = $second;
$second = $tmp;
}

$first_journal = Controller::$storage::getJournal($first);
$second_journal = Controller::$storage::getJournal($second);

if (!$first_journal || !$second_journal) {
return false;
}

if (Controller::$debug) {
Logger::log('first journal ' . $first_journal);
Logger::log('second journal ' . $second_journal);
}

return self::compare($first_journal, $second_journal);
}

/**
* @param $first_journal
* @param $second_journal
* @return array|false
*/
private static function compare($first_journal, $second_journal)
{
$result = array(
'added' => array(),
'deleted' => array(),
'changed' => array(),
);

//return no diff if csv names is equal
if ( $first_journal === $second_journal) {
return $result;
}

//return no diff if md5 sums is equal
if (md5(@file_get_contents($first_journal)) === md5(@file_get_contents($second_journal))) {
return $result;
}

$first_journal = self::uncompress($first_journal);
$second_journal = self::uncompress($second_journal);

if ( !$first_journal || !$second_journal) {
return false;
}

$first_array = [];
$second_array = [];

try {
$fp_first = fopen($first_journal, 'r');
while ($first = fgetcsv($fp_first)) {
$first_array[$first[0]] = $first[1];
}
fclose($fp_first);
@unlink($first_journal);

$fp_second = fopen($second_journal, 'r');
while ($second = fgetcsv($fp_second)) {
$second_array[$second[0]] = $second[1];
}
fclose($fp_second);
@unlink($second_journal);

foreach ($first_array as $path => $time) {
if ((isset($second_array[$path]) && $time !== $second_array[$path])) {
$result['changed'][] = [$path, $second_array[$path]];
}
}

$keys_differ = array_merge(array_diff_key($first_array, $second_array), array_diff_key($second_array, $first_array));

foreach ($keys_differ as $path => $time) {
if ( in_array($path, array_keys($first_array)) && !in_array($path, array_keys($second_array))) {
$result['deleted'][] = [$path,$time];
}

if ( !in_array($path, array_keys($first_array)) && in_array($path, array_keys($second_array))) {
$result['added'][] = [$path,$time];
}
}

return $result;
} catch (\Exception $e) {
return false;
}
}

/**
* @param $file
* @return false|string
*/
private static function uncompress($file)
{
if ( substr($file, -3) === '.gz' ) {
$content = @gzopen($file, 'r');
if ( false === $content ) {
return false;
}
$gz_result = @gzread($content, 1024 * 1024 * 10);
if ( !is_string($gz_result) ) {
@gzclose($content);
return false;
}
$write_result = @file_put_contents(substr($file, 0, -3), $gz_result);
gzclose($content);
if ( false === $write_result ) {
return false;
}
$file = substr($file, 0, -3);
}

return $file;
}
}
136 changes: 136 additions & 0 deletions lib/CleantalkSP/Common/FSWatcher/Controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php

namespace CleantalkSP\Common\FSWatcher;

use CleantalkSP\Common\FSWatcher\Analyzer\Analyzer;
use CleantalkSP\Common\FSWatcher\Scan\Scan;

class Controller
{
/**
* @var bool
*/
public static $debug;

const STATUS_STOPPED = 'stopped';

const STATUS_RUNNING = 'running';

const EXECUTION_MIN_INTERVAL = 6000; // 1,66 hours

/**
* @var \CleantalkSP\Common\FSWatcher\Storage\Storage
*/
public static $storage;

/**
* @var \CleantalkSP\Common\FSWatcher\Repository\Repository
*/
public static $repository;

private static $status = self::STATUS_STOPPED;

/**
* Initialize the `$debug` property false|true
*
* @return void
*/
private static function getDebugState()
{
if ( defined('SPBC_FSWATCHER_DEBUG') ) {
self::$debug = (bool) SPBC_FSWATCHER_DEBUG;
}
}

/**
* This is the init method.
*
* Making initialize the `$debug` property
*
* Contains Ajax handler for requests:
* 1) Comparing logs
* 2) Scanning file system
* 3) Automatically making ajax requests for 2)
*
* @param $params
* @return void
*/
public static function work($params)
{
self::getDebugState();

if (self::$debug) {
Logger::log('check remote call = ' . (int)Service::isRC());
}

Service::setStorage(isset($params['storage']) ? $params['storage'] : 'file');

if (self::status() === self::STATUS_STOPPED && Service::isRC() && Service::isCompareRequest()) {
if (self::$debug) {
Logger::log('run compare file system');
}
$compare_result = Analyzer::getCompareResult();
if (false === $compare_result) {
Logger::log('Can not compare logs');
echo json_encode(array('error' => 'Can not compare logs'));
} else {
echo json_encode($compare_result);
}
die();
}

if (self::status() === self::STATUS_STOPPED && ( Service::isRC() || ( Service::isRC() && Service::isCreateSnapshotRequest() ))) {
if (self::$debug) {
Logger::log('run scan file system');
}
self::run($params);
die(json_encode('OK'));
}

if (self::status() === self::STATUS_STOPPED && Service::isMinIntervalPassed(self::EXECUTION_MIN_INTERVAL)) {
if (self::$debug) {
Logger::log('attach js to make remote request');
}
ob_start(['CleantalkSP\Common\FSWatcher\Service', 'attachJS']);
}
}

/**
* Scanning file system handler
*
* @param $params
* @return void
*/
private static function run($params)
{
self::$status = self::STATUS_RUNNING;
Scan::run($params);
self::stop();
}

/**
* Scanning file system stop trigger
*
* @return void
*/
private static function stop()
{
self::$status = self::STATUS_STOPPED;
Service::setAllJournalsAsCompleted();
}

/**
* Checking status of the scanning process
*
* @return string
*/
private static function status()
{
$is_exist = Service::getProcessingJournal();
if (!is_null($is_exist)) {
self::$status = self::STATUS_RUNNING;
}

return self::$status;
}
}
Loading