3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2016 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2016
36 * Define the threshold for the ids reactions.
38 private $threshold = array(
52 * This function includes the IDS vendor parts and runs the
53 * detection routines on the request array.
55 * @param object $args cake controller object
59 public function check(&$args) {
60 // lets bypass a few civicrm urls from this check
61 $skip = array('civicrm/admin/setting/updateConfigBackend', 'civicrm/admin/messageTemplates');
62 CRM_Utils_Hook
::idsException($skip);
63 $path = implode('/', $args);
64 if (in_array($path, $skip)) {
68 // Add request url and user agent.
69 $_REQUEST['IDS_request_uri'] = $_SERVER['REQUEST_URI'];
70 if (isset($_SERVER['HTTP_USER_AGENT'])) {
71 $_REQUEST['IDS_user_agent'] = $_SERVER['HTTP_USER_AGENT'];
74 $configFile = self
::createConfigFile(FALSE);
76 // init the PHPIDS and pass the REQUEST array
77 require_once 'IDS/Init.php';
79 $init = IDS_Init
::init($configFile);
80 $ids = new IDS_Monitor($_REQUEST, $init);
82 catch (Exception
$e) {
83 // might be an old stale copy of Config.IDS.ini
84 // lets try to rebuild it again and see if it works
85 $configFile = self
::createConfigFile(TRUE);
86 $init = IDS_Init
::init($configFile);
87 $ids = new IDS_Monitor($_REQUEST, $init);
90 $result = $ids->run();
91 if (!$result->isEmpty()) {
92 $this->react($result);
99 * Create the default config file for the IDS system.
102 * Should we recreate it irrespective if it exists or not.
105 * the full path to the config file
107 public static function createConfigFile($force = FALSE) {
108 $config = CRM_Core_Config
::singleton();
109 $configFile = $config->configAndLogDir
. 'Config.IDS.ini';
110 if (!$force && file_exists($configFile)) {
114 $tmpDir = empty($config->uploadDir
) ? CIVICRM_TEMPLATE_COMPILEDIR
: $config->uploadDir
;
116 // also clear the stat cache in case we are upgrading
119 global $civicrm_root;
123 filter_path = {$civicrm_root}/packages/IDS/default_filter.xml
125 HTML_Purifier_Path = IDS/vendors/htmlpurifier/HTMLPurifier.auto.php
126 HTML_Purifier_Cache = $tmpDir
128 exceptions[] = __utmz
129 exceptions[] = __utmc
130 exceptions[] = widget_code
131 exceptions[] = html_message
132 exceptions[] = text_message
133 exceptions[] = body_html
134 exceptions[] = msg_html
135 exceptions[] = msg_text
136 exceptions[] = msg_subject
137 exceptions[] = description
139 exceptions[] = thankyou_text
140 exceptions[] = intro_text
141 exceptions[] = body_text
142 exceptions[] = footer_text
143 exceptions[] = thankyou_text
144 exceptions[] = tf_thankyou_text
145 exceptions[] = thankyou_footer
146 exceptions[] = thankyou_footer_text
147 exceptions[] = new_text
148 exceptions[] = renewal_text
149 exceptions[] = help_pre
150 exceptions[] = help_post
151 exceptions[] = confirm_title
152 exceptions[] = confirm_text
153 exceptions[] = confirm_footer_text
154 exceptions[] = confirm_email_text
155 exceptions[] = report_header
156 exceptions[] = report_footer
159 exceptions[] = instructions
160 exceptions[] = suggested_message
161 exceptions[] = page_text
163 if (file_put_contents($configFile, $contents) === FALSE) {
164 CRM_Core_Error
::movedSiteError($configFile);
167 // also create the .htaccess file so we prevent the reading of the log and ini files
168 // via a browser, CRM-3875
169 CRM_Utils_File
::restrictAccess($config->configAndLogDir
);
175 * This function reacts on the values in the incoming results array.
177 * Depending on the impact value certain actions are
180 * @param IDS_Report $result
184 private function react(IDS_Report
$result) {
186 $impact = $result->getImpact();
187 if ($impact >= $this->threshold
['kick']) {
188 $this->log($result, 3, $impact);
189 $this->kick($result);
192 elseif ($impact >= $this->threshold
['warn']) {
193 $this->log($result, 2, $impact);
194 $this->warn($result);
197 elseif ($impact >= $this->threshold
['log']) {
198 $this->log($result, 0, $impact);
207 * This function writes an entry about the intrusion to the database.
209 * @param array $result
210 * @param int $reaction
214 private function log($result, $reaction = 0) {
215 $ip = (isset($_SERVER['SERVER_ADDR']) &&
216 $_SERVER['SERVER_ADDR'] != '127.0.0.1') ?
$_SERVER['SERVER_ADDR'] : (
217 isset($_SERVER['HTTP_X_FORWARDED_FOR']) ?
$_SERVER['HTTP_X_FORWARDED_FOR'] : '127.0.0.1'
221 $session = CRM_Core_Session
::singleton();
222 foreach ($result as $event) {
224 'name' => $event->getName(),
225 'value' => stripslashes($event->getValue()),
226 'page' => $_SERVER['REQUEST_URI'],
227 'userid' => $session->get('userID'),
228 'session' => session_id() ?
session_id() : '0',
230 'reaction' => $reaction,
231 'impact' => $result->getImpact(),
235 CRM_Core_Error
::debug_var('IDS Detector Details', $data);
242 * @param array $result
246 private function warn($result) {
251 * Kick (whatever that means!).
253 * @param array $result
257 private function kick($result) {
258 $session = CRM_Core_Session
::singleton();
261 $msg = ts('There is a validation error with your HTML input. Your activity is a bit suspicious, hence aborting');
263 $path = implode('/', $args);
266 array("civicrm/ajax/rest", "civicrm/api/json")
268 require_once "api/v3/utils.php";
269 $error = civicrm_api3_create_error(
272 'IP' => $_SERVER['REMOTE_ADDR'],
273 'error_code' => 'IDS_KICK',
274 'level' => 'security',
275 'referer' => $_SERVER['HTTP_REFERER'],
276 'reason' => 'XSS suspected',
279 CRM_Utils_JSON
::output($error);
281 CRM_Core_Error
::fatal($msg);