Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
16 changes: 16 additions & 0 deletions inc/spbc-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -1731,6 +1731,22 @@ function spbc_field_scanner__prepare_data__files(&$table)
unset($row->actions['cure']);
}

// wp-config.php: detect only; content view for Super Admin only; never send to cloud
if ( Scanner\Helper::isWpConfigPath($row->path) ) {
unset($row->actions['cure']);
unset($row->actions['delete']);
unset($row->actions['quarantine']);
unset($row->actions['replace']);
unset($row->actions['send']);
if ( ! Scanner\Helper::canViewWpConfigContents() ) {
unset($row->actions['view']);
unset($row->actions['view_bad']);
}
if ( ! empty($row->weak_spots) || (isset($row->severity) && $row->severity === 'CRITICAL') ) {
$status = '<span class="spbcRed">' . esc_html(Scanner\Helper::getWpConfigManualCleanupMessage()) . '</span>';
}
}

$table->items[] = array(
'cb' => $row->fast_hash,
'uid' => $row->fast_hash,
Expand Down
57 changes: 57 additions & 0 deletions lib/CleantalkSP/SpbctWP/Scanner/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,63 @@ public static function getRowActionsNeedsNoConfirm()
return is_string($actions) ? $actions : '{[]}';
}

/**
* Whether the given path is WordPress wp-config.php (critical, no auto-cure).
*
* @param string $path Absolute or relative file path
* @return bool
*/
public static function isWpConfigPath($path)
{
return basename(str_replace('\\', '/', (string) $path)) === 'wp-config.php';
}
Comment thread
svfcode marked this conversation as resolved.

/**
* Message shown when wp-config.php infection is detected (manual cleanup only).
*
* @return string
*/
public static function getWpConfigManualCleanupMessage()
{
return __(
'Infection detected in wp-config.php. Automatic cure is disabled for this critical file — manual cleanup is required. Please contact support or order a malware removal.',
'security-malware-firewall'
);
}

/**
* Whether the current user may view wp-config.php contents in the scanner UI.
* Restricted to Super Admins to reduce credential exposure.
*
* @return bool
*/
public static function canViewWpConfigContents()
{
return function_exists('is_super_admin') && is_super_admin();
}
Comment thread
svfcode marked this conversation as resolved.

/**
* @return string
*/
public static function getWpConfigViewRestrictedMessage()
{
return __(
'Only a Super Admin can view wp-config.php contents (credentials protection).',
'security-malware-firewall'
);
}

/**
* @return string
*/
public static function getWpConfigSendRestrictedMessage()
{
return __(
'wp-config.php cannot be sent for analysis because it contains sensitive credentials.',
'security-malware-firewall'
);
}

/**
* query
* Get SQL *WHERE* suffix for SELECT query depends on files category.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ public static function deleteFile($file_id)
return array('error' => 'FILE_NOT_FOUND');
}

if (Helper::isWpConfigPath($file_info['path'])) {
return array('error' => Helper::getWpConfigManualCleanupMessage());
}

if ($file_info['status'] == 'QUARANTINED') {
return array('error' => 'USE_QUARANTINE_DELETE');
}
Expand Down Expand Up @@ -254,6 +258,10 @@ public static function replaceFileWithOriginal($file_id)
return array('error' => 'FILE_NOT_FOUND');
}

if (Helper::isWpConfigPath($file_info['path'])) {
return array('error' => Helper::getWpConfigManualCleanupMessage());
}

if (!file_exists($root_path . $file_info['path'])) {
return array('error' => 'FILE_NOT_EXISTS');
}
Expand Down Expand Up @@ -335,6 +343,10 @@ public static function viewFile($file_id)
return array('error' => 'FILE_NOT_FOUND');
}

if (Helper::isWpConfigPath($file_info['path']) && ! Helper::canViewWpConfigContents()) {
return array('error' => Helper::getWpConfigViewRestrictedMessage());
}

$file_path = $file_info['status'] == 'QUARANTINED' ? $file_info['q_path'] : $root_path . $file_info['path'];

if (!file_exists($file_path)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace CleantalkSP\SpbctWP\Scanner\ScannerActions;

use CleantalkSP\SpbctWP\Helpers\HTTP;
use CleantalkSP\SpbctWP\Scanner\Helper;

class QuarantineActions
{
Expand Down Expand Up @@ -184,6 +185,10 @@ public static function doQuarantineFile($file_id)
return array('error' => 'FILE_NOT_FOUND');
}

if (Helper::isWpConfigPath($file_info['path'])) {
return array('error' => Helper::getWpConfigManualCleanupMessage());
}

if (!file_exists($root_path . $file_info['path'])) {
return array('error' => 'FILE_NOT_EXISTS');
}
Expand Down
2 changes: 1 addition & 1 deletion lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ public function file_system_analysis($offset = null, $amount = null, $path_to_sc
'amount' => $amount,
'extensions' => 'php, html, htm, js, php2, php3, php4, php5, php6, php7, phtml, shtml, phar, odf, [ot.]',
'extensions_exceptions' => '', //array('jpg', 'jpeg', 'png', 'gif', 'css', 'txt', 'zip', 'xml', 'json')
'file_exceptions' => array('wp-config.php'),
'file_exceptions' => array(),
'files_mandatory' => array(),
'dir_exceptions' => array(SPBC_PLUGIN_DIR . 'quarantine'),
// important!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use CleantalkSP\SpbctWP\API as SpbcAPI;
use CleantalkSP\SpbctWP\DTO\MScanFilesDTO;
use CleantalkSP\SpbctWP\Scanner\Helper;
use CleantalkSP\SpbctWP\Scanner\ScannerActions\ScanActions;
use CleantalkSP\SpbctWP\Scanner\ScannerActions\ScanResultsTableActions;
use CleantalkSP\SpbctWP\Scanner\ScanRepository;
Expand Down Expand Up @@ -31,6 +32,11 @@ public static function sendFile($file_id, $do_rescan = true)
return array('error' => 'FILE_NOT_FOUND');
}

// Never send wp-config.php — contains DB credentials and salts
if (isset($file_info['path']) && Helper::isWpConfigPath($file_info['path'])) {
return array('error' => Helper::getWpConfigSendRestrictedMessage());
}

// Binary files cannot be sent for analysis
if (isset($file_info['source']) && $file_info['source'] === 'BINARY') {
return array('error' => __('Binary files cannot be sent for analysis.', 'security-malware-firewall'));
Expand Down
13 changes: 11 additions & 2 deletions lib/CleantalkSP/SpbctWP/Scanner/Stages/CureStage.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use CleantalkSP\SpbctWP\Scanner\CureLog\CureLog;
use CleantalkSP\SpbctWP\Scanner\CureLog\CureLogRecord;
use CleantalkSP\SpbctWP\Scanner\FileInfoExtended;
use CleantalkSP\SpbctWP\Scanner\Helper;
use CleantalkSP\SpbctWP\Scanner\ScannerActions\BackupsActions;
use CleantalkSP\SpbctWP\Scanner\ScanningLog\ScanningLogFacade;
use CleantalkSP\SpbctWP\Scanner\ScanningStagesModule\ScanningStagesStorage;
Expand Down Expand Up @@ -104,11 +105,13 @@ public function runStage($offset, $amount)
*/
public function getFilesToCure($limit = null)
{
// get files with signatures (excluding binary files)
// get files with signatures (excluding binary files and wp-config.php — critical, manual cleanup only)
$files_with_signatures = '
SELECT fast_hash, full_hash, mtime
FROM ' . SPBC_TBL_SCAN_FILES . '
WHERE weak_spots LIKE "%SIGNATURES%" AND (source IS NULL OR source != \'BINARY\')
WHERE weak_spots LIKE "%SIGNATURES%"
AND (source IS NULL OR source != \'BINARY\')
AND path NOT LIKE "%wp-config.php"
';
Comment thread
svfcode marked this conversation as resolved.
$files_with_signatures = $this->db->fetchAll($files_with_signatures, OBJECT_K);

Expand Down Expand Up @@ -232,6 +235,12 @@ public function processCure($file)
*/
private function preCheckFile($file, $cure_log_record)
{
if ( isset($file['path']) && Helper::isWpConfigPath($file['path']) ) {
$cure_log_record->cure_status = 0;
$cure_log_record->fail_reason = Helper::getWpConfigManualCleanupMessage();
return $cure_log_record;
}

BackupsActions::createBackupsForFilesWithSignatures();

//check if file has backup
Expand Down