Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
67 changes: 67 additions & 0 deletions lib/CleantalkSP/SpbctWP/Scanner/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,73 @@ public static function getRowActionsNeedsNoConfirm()
return is_string($actions) ? $actions : '{[]}';
}

/**
* Whether the given path is the site-root WordPress wp-config.php (critical, no auto-cure).
* Does not match files named wp-config.php in subdirectories (e.g. uploads).
*
* @param string $path Absolute or relative file path (as stored in scan table or filesystem)
* @return bool
*/
public static function isWpConfigPath($path)
{
$normalized = str_replace('\\', '/', (string) $path);

if (defined('ABSPATH')) {
$abspath = rtrim(str_replace('\\', '/', ABSPATH), '/');
if ($abspath !== '' && stripos($normalized, $abspath . '/') === 0) {
$normalized = substr($normalized, strlen($abspath));
}
}

return ltrim($normalized, '/') === 'wp-config.php';
}

/**
* 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
16 changes: 14 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 @@ -106,9 +107,10 @@ public function getFilesToCure($limit = null)
{
// get files with signatures (excluding binary files)
$files_with_signatures = '
SELECT fast_hash, full_hash, mtime
SELECT fast_hash, full_hash, mtime, path
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\')
';
$files_with_signatures = $this->db->fetchAll($files_with_signatures, OBJECT_K);

Expand All @@ -118,6 +120,10 @@ public function getFilesToCure($limit = null)

$to_cure_fast_hashes = array();
foreach ($files_with_signatures as $key => $value) {
// Root wp-config.php: detect only, never auto-cure
if (isset($value->path) && Helper::isWpConfigPath($value->path)) {
continue;
}
if (isset($cure_log_data[$key])) { //fast hash found, do check for last cure date and hash
$found_by_fast_hash = $cure_log_data[$key];
// skip restored files
Expand Down Expand Up @@ -232,6 +238,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
Loading