Jelajahi Sumber

Ticket #5529 - Protect confidential information.

AntonLV 2 bulan lalu
induk
melakukan
04064c6540

+ 34 - 32
inc/classes/BxDolDb.php

@@ -1332,29 +1332,29 @@ class BxDolDb extends BxDolFactory implements iBxDolSingleton
 
     protected function executeStatementSilent($oStatement, $aBindings = array(), $bVerbose = null)
     {
-    	$bResult = $oStatement->execute(!empty($aBindings) && is_array($aBindings) ? $aBindings : null);
-    	if($bResult)
-    		return true;
+        $bResult = $oStatement->execute(!empty($aBindings) && is_array($aBindings) ? $aBindings : null);
+        if($bResult)
+            return true;
 
-		$aError = $oStatement->errorInfo();
+        $aError = $oStatement->errorInfo();
 
         $aTrace = debug_backtrace();
         unset($aTrace[0]);
 
-		$this->_aError = array(
-			'code' => BX_DB_ERR_QUERY_ERROR,
-			'message' => !empty($aError[2]) ? $aError[2] : '',
-			'query' => $oStatement->queryString,
-			'trace' => $aTrace,
-			'verbose' => $bVerbose
-		);
+        $this->_aError = array(
+            'code' => BX_DB_ERR_QUERY_ERROR,
+            'message' => !empty($aError[2]) ? $aError[2] : '',
+            'query' => $oStatement->queryString,
+            'trace' => $aTrace,
+            'verbose' => $bVerbose
+        );
 
-		return false;
+        return false;
     }
 
-	protected function errorOutput($aError)
+    protected function errorOutput($aError)
     {
-		$aErrorLocation = array();
+        $aErrorLocation = [];
 
         if(!empty($aError['query']) && !empty($aError['trace']))
             foreach($aError['trace'] as $aCall )
@@ -1368,41 +1368,43 @@ class BxDolDb extends BxDolFactory implements iBxDolSingleton
                         }
 
         $sOutput = '';
-        
         if(!empty($aError['query']))
             $sOutput .= '<p><b>Query:</b><br />' . bx_process_output($aError['query']) . '</p>'."\n";
 
         if(!empty($aError['message']))
             $sOutput .= '<p><b>Mysql error:</b><br />' . $aError['message'] . '</p>'."\n";
 
-		if(!empty($aErrorLocation))
-			$sOutput .= '<p><b>Location:</b><br />The error was found in <b>' . $aErrorLocation['function'] . '</b> function in the file <b>' . $aErrorLocation['file'] . '</b> at line <b>' . $aErrorLocation['line'] . '</b>.</p>'."\n";
+        if(!empty($aErrorLocation))
+            $sOutput .= '<p><b>Location:</b><br />The error was found in <b>' . $aErrorLocation['function'] . '</b> function in the file <b>' . $aErrorLocation['file'] . '</b> at line <b>' . $aErrorLocation['line'] . '</b>.</p>'."\n";
 
         $sOutput .= '<p><b>collation_connection:</b><br />' . $this->getOne("SELECT @@collation_connection") . '</p>'."\n";
-        
-		if(!empty($aError['trace'])) {
+
+        if(!empty($aError['trace'])) {
             $sBackTrace = print_r($aError['trace'], true);
-            if (defined ('BX_DATABASE_USER') && !is_array(BX_DATABASE_USER))
+            if(defined ('BX_DATABASE_USER') && !is_array(BX_DATABASE_USER))
                 $sBackTrace = str_replace('[_sUser:protected] => ' . BX_DATABASE_USER, '[_sUser:protected] => *****', $sBackTrace);
-            if (defined ('BX_DATABASE_PASS') && !is_array(BX_DATABASE_PASS))
+            if(defined ('BX_DATABASE_PASS') && !is_array(BX_DATABASE_PASS))
                 $sBackTrace = str_replace('[_sPassword:protected] => ' . BX_DATABASE_PASS, '[_sPassword:protected] => *****', $sBackTrace);
 
-			$sOutput .= '<div><b>Debug backtrace:</b></div><div style="overflow:scroll;height:300px;border:1px solid gray;"><pre>' . htmlspecialchars_adv($sBackTrace) . '</pre></div>';
-		}
+            $sOutput .= '<div><b>Debug backtrace:</b></div><div style="overflow:scroll;height:300px;border:1px solid gray;"><pre>' . htmlspecialchars_adv($sBackTrace) . '</pre></div>';
+        }
 
-		if(!empty(self::$_aParams)) {
-			$sSettings = var_export(self::$_aParams, true);
+        if(!empty(self::$_aParams)) {
+            $aParams = self::$_aParams;
+            $aParamsSecret = $this->getColumn("SELECT `name` FROM `sys_options` WHERE `type`='secret'", "name");
+            if($aParamsSecret && is_array($aParamsSecret))
+                array_walk($aParams, function(&$sValue, $sKey) use ($aParamsSecret) {
+                    if(in_array($sKey, $aParamsSecret))
+                        $sValue = bx_gen_secret($sValue);
+                });
 
-			$sOutput .= '<div><b>Settings:</b></div><div style="overflow:scroll;height:300px;border:1px solid gray;"><pre>' . htmlspecialchars_adv($sSettings) . '</pre></div>';
-		}
+            $sOutput .= '<div><b>Settings:</b></div><div style="overflow:scroll;height:300px;border:1px solid gray;"><pre>' . htmlspecialchars_adv(var_export($aParams, true)) . '</pre></div>';
+        }
 
         $sOutput .= '<p><b>Called script:</b><br />' . htmlspecialchars_adv($_SERVER['PHP_SELF']) . '</p>';
 
-		if(!empty($_REQUEST)) {
-			$sRequest = var_export($_REQUEST, true);
-
-			$sOutput .= '<p><b>Request parameters:</b><br /><pre>' . htmlspecialchars_adv($sRequest) . '</pre></p>';
-		}
+        if(!empty($_REQUEST))
+            $sOutput .= '<p><b>Request parameters:</b><br /><pre>' . htmlspecialchars_adv(var_export($_REQUEST, true)) . '</pre></p>';
 
         return $sOutput;
     }

+ 7 - 0
inc/utils.inc.php

@@ -1330,6 +1330,13 @@ function genRndSalt()
     return genRndPwd(8, true);
 }
 
+function bx_gen_secret($sV)
+{
+    $iL = strlen($sV);
+    $iV = ceil(0.1 * $iL);
+    return substr($sV, 0, $iV) . str_repeat('*', floor(0.8 * $iL)) . substr($sV, -$iV);
+}
+
 /**
  * Encrypt user password.
  * When BX_PWD_ALGO is 'custom', then bx_custom_pwd_encrypt function with custom algorythm must be defined in inc/header.inc.php file.

+ 10 - 10
install/sql/system.sql

@@ -329,7 +329,7 @@ CREATE TABLE `sys_options` (
   `caption` varchar(255) NOT NULL default '',
   `info` varchar(255) NOT NULL default '',
   `value` mediumtext NOT NULL,
-  `type` enum('value','digit','text','code','checkbox','select','combobox','file','image','list','rlist','rgb','rgba','datetime') NOT NULL default 'digit',
+  `type` enum('value','digit','secret','text','code','checkbox','select','combobox','file','image','list','rlist','rgb','rgba','datetime') NOT NULL default 'digit',
   `extra` text NOT NULL default '',
   `check` varchar(32) NOT NULL,
   `check_params` text NOT NULL,
@@ -388,7 +388,7 @@ INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `ex
 (@iCategoryId, 'sys_push_queue_time', '_adm_stg_cpt_option_sys_push_queue_time', '0', 'digit', '', '', '', '', 7),
 
 (@iCategoryId, 'sys_ftp_login', '_adm_stg_cpt_option_sys_ftp_login', '', 'digit', '', '', '', '', 10),
-(@iCategoryId, 'sys_ftp_password', '_adm_stg_cpt_option_sys_ftp_password', '', 'digit', '', '', '', '', 11),
+(@iCategoryId, 'sys_ftp_password', '_adm_stg_cpt_option_sys_ftp_password', '', 'secret', '', '', '', '', 11),
 (@iCategoryId, 'sys_ftp_dir', '_adm_stg_cpt_option_sys_ftp_dir', '', 'digit', '', '', '', '', 12),
 
 (@iCategoryId, 'sys_template_cache_image_enable', '_adm_stg_cpt_option_sys_template_cache_image_enable', '', 'checkbox', '', '', '', '', 20),
@@ -588,7 +588,7 @@ SET @iCategoryId = LAST_INSERT_ID();
 
 INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `info`, `value`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
 (@iCategoryId, 'sys_oauth_key', '_adm_stg_cpt_option_sys_oauth_key', '', '', 'digit', '', '', '', 20),
-(@iCategoryId, 'sys_oauth_secret', '_adm_stg_cpt_option_sys_oauth_secret', '', '', 'digit', '', '', '', 21),
+(@iCategoryId, 'sys_oauth_secret', '_adm_stg_cpt_option_sys_oauth_secret', '', '', 'secret', '', '', '', 21),
 
 (@iCategoryId, 'currency_code', '_adm_stg_cpt_option_currency_code', '', 'USD', 'select', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:33:"get_options_currency_code_default";s:5:"class";s:21:"TemplPaymentsServices";}', 'Avail', '_adm_stg_err_option_currency_code', 30),
 (@iCategoryId, 'currency_sign', '_adm_stg_cpt_option_currency_sign', '', '&#36;', 'select', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:33:"get_options_currency_sign_default";s:5:"class";s:21:"TemplPaymentsServices";}', 'Avail', '_adm_stg_err_option_currency_sign', 31),
@@ -602,13 +602,13 @@ INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `info`, `value`, `ty
 (@iCategoryId, 'sys_embed_default', '_adm_stg_cpt_option_sys_embed_default', '', 'sys_system', 'select', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:25:"get_options_embed_default";s:5:"class";s:13:"TemplServices";}', '', '', 70),
 (@iCategoryId, 'sys_embed_lifetime', '_adm_stg_cpt_option_sys_embed_lifetime', '', '30', 'digit', '', '', '', 73),
 
-(@iCategoryId, 'sys_embedly_api_key', '_adm_stg_cpt_option_sys_embedly_api_key', '', '', 'digit', '', '', '', 80),
+(@iCategoryId, 'sys_embedly_api_key', '_adm_stg_cpt_option_sys_embedly_api_key', '', '', 'secret', '', '', '', 80),
 
-(@iCategoryId, 'sys_iframely_api_key', '_adm_stg_cpt_option_sys_iframely_api_key', '', '', 'digit', '', '', '', 90),
+(@iCategoryId, 'sys_iframely_api_key', '_adm_stg_cpt_option_sys_iframely_api_key', '', '', 'secret', '', '', '', 90),
 
-(@iCategoryId, 'sys_embed_microlink_key', '_adm_stg_cpt_option_sys_embed_microlink_key', '', '', 'digit', '', '', '', 100),
+(@iCategoryId, 'sys_embed_microlink_key', '_adm_stg_cpt_option_sys_embed_microlink_key', '', '', 'secret', '', '', '', 100),
 
-(@iCategoryId, 'sys_embed_peekalink_api_key', '_adm_stg_cpt_option_sys_embed_peekalink_api_key', '', '', 'digit', '', '', '', 110);
+(@iCategoryId, 'sys_embed_peekalink_api_key', '_adm_stg_cpt_option_sys_embed_peekalink_api_key', '', '', 'secret', '', '', '', 110);
 
 
 --
@@ -668,7 +668,7 @@ INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `ex
 (@iCategoryId, 'sys_security_form_token_lifetime', '_adm_stg_cpt_option_sys_security_form_token_lifetime', '86400', 'digit', '', '', '', 11),
 (@iCategoryId, 'sys_captcha_default', '_adm_stg_cpt_option_sys_captcha_default', 'sys_recaptcha_new', 'select', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:27:"get_options_captcha_default";s:5:"class";s:13:"TemplServices";}', '', '', 19),
 (@iCategoryId, 'sys_recaptcha_key_public', '_adm_stg_cpt_option_sys_recaptcha_key_public', '', 'digit', '', '', '', 20),
-(@iCategoryId, 'sys_recaptcha_key_private', '_adm_stg_cpt_option_sys_recaptcha_key_private', '', 'digit', '', '', '', 21),
+(@iCategoryId, 'sys_recaptcha_key_private', '_adm_stg_cpt_option_sys_recaptcha_key_private', '', 'secret', '', '', '', 21),
 (@iCategoryId, 'sys_add_nofollow', '_adm_stg_cpt_option_sys_add_nofollow', 'on', 'checkbox', '', '', '', 30),
 (@iCategoryId, 'sys_confirmation_before_redirect', '_adm_stg_cpt_option_sys_confirmation_before_redirect', 'on', 'checkbox', '', '', '', 31),
 (@iCategoryId, 'sys_security_block_content_after_n_reports', '_adm_stg_cpt_option_sys_security_block_content_after_n_reports', '0', 'digit', '', '', '', 35),
@@ -690,7 +690,7 @@ SET @iCategoryId = LAST_INSERT_ID();
 INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
 (@iCategoryId, 'sys_storage_default', '_adm_stg_cpt_option_sys_storage_default', 'Local', 'select', 'Local,S3,S3v4,S3v4alt', '', '', 1),
 (@iCategoryId, 'sys_storage_s3_access_key', '_adm_stg_cpt_option_sys_storage_s3_access_key', '', 'digit', '', '', '', 2),
-(@iCategoryId, 'sys_storage_s3_secret_key', '_adm_stg_cpt_option_sys_storage_s3_secret_key', '', 'digit', '', '', '', 3),
+(@iCategoryId, 'sys_storage_s3_secret_key', '_adm_stg_cpt_option_sys_storage_s3_secret_key', '', 'secret', '', '', '', 3),
 (@iCategoryId, 'sys_storage_s3_bucket', '_adm_stg_cpt_option_sys_storage_s3_bucket', '', 'digit', '', '', '', 4),
 (@iCategoryId, 'sys_storage_s3_domain', '_adm_stg_cpt_option_sys_storage_s3_domain', '', 'digit', '', '', '', 5),
 (@iCategoryId, 'sys_storage_s3_endpoint', '_adm_stg_cpt_option_sys_storage_s3_endpoint', '', 'digit', '', '', '', 6),
@@ -844,7 +844,7 @@ INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `ex
 (@iCategoryId, 'sys_sockets_url', '_adm_stg_cpt_option_sys_sockets_url', '', 'digit', '', '', '', 2),
 (@iCategoryId, 'sys_sockets_app_id', '_adm_stg_cpt_option_sys_sockets_app_id', '', 'digit', '', '', '', 3),
 (@iCategoryId, 'sys_sockets_key', '_adm_stg_cpt_option_sys_sockets_key', '', 'digit', '', '', '', 4),
-(@iCategoryId, 'sys_sockets_secret', '_adm_stg_cpt_option_sys_sockets_secret', '', 'digit', '', '', '', 5);
+(@iCategoryId, 'sys_sockets_secret', '_adm_stg_cpt_option_sys_sockets_secret', '', 'secret', '', '', '', 5);
 
 --
 -- CATEGORY (HIDDEN): Audit

+ 10 - 2
studio/classes/BxDolStudioOptions.php

@@ -478,8 +478,16 @@ class BxDolStudioOptions extends BxDol
     	if(method_exists($this, $sMethod))
     	    return $this->$sMethod($aOption, $mixedValue);
 
-        if(is_array($mixedValue))
-            $mixedValue = implode(',', $mixedValue);
+        switch($aOption['type']) {
+            case 'secret':
+                if(strcmp(bx_gen_secret($aOption['value']), $mixedValue) == 0)
+                    $mixedValue = $aOption['value'];
+                break;
+
+            default:
+                if(is_array($mixedValue))
+                    $mixedValue = implode(',', $mixedValue);
+        }
 
         return $mixedValue;
     }

+ 10 - 0
studio/template/scripts/BxBaseStudioFormView.php

@@ -184,6 +184,16 @@ class BxBaseStudioFormView extends BxDolStudioForm
 
         return parent::genInputCheckboxSet($aInput);
     }
+
+    protected function _genInputStandardAttrs(&$aInput)
+    {
+        $aAttrs = parent::_genInputStandardAttrs($aInput);
+
+        if($aInput['type'] == 'text' && ($aInput['secret'] ?? false) && ($sValue = $aAttrs['value'] ?? false))
+            $aAttrs['value'] = bx_gen_secret($sValue);
+
+        return $aAttrs;
+    }
 }
 
 /** @} */

+ 12 - 0
studio/template/scripts/BxBaseStudioOptions.php

@@ -640,6 +640,18 @@ class BxBaseStudioOptions extends BxDolStudioOptions
                     'db' => ['pass' => 'Xss'],
                 ];
                 break;
+            case 'secret':
+                $aField = [
+                    'type' => 'text',
+                    'name' => $aItem['name'],
+                    'caption' => _t($aItem['caption']),
+                    'info' => _t($aItem['info']),
+                    'value' => $mixedValue,
+                    'attrs' => $aAttributes,
+                    'secret' => 1,
+                    'db' => ['pass' => 'Xss'],
+                ];
+                break;
             case 'text':
                 $aField = [
                     'type' => 'textarea',