Example #1
0
 public function onAfterInitialise($args = array())
 {
     //Are we enabled?
     if (!$this->params->get('enabled', 1)) {
         return 0;
     }
     //DB item.
     $db = JFactory::getDbo();
     $this->add_log('JHackGuard initialised', 'debug');
     /* Maintenance steps start */
     $probability = rand(0, 100);
     //Clear the expired logs (probability of running 10%)
     if ($probability < 11) {
         $days = (int) $this->params->get('log_garbage_collection', 7);
         if (!$days) {
             $days = 7;
         }
         $query = $db->getQuery(true);
         $query->delete($db->quoteName('#__jhackguard_logs'));
         $query->where($db->quoteName('time') . ' < DATE_SUB(CURRENT_DATE, INTERVAL ' . $days . ' DAY)');
         $db->setQuery($query);
         $db->query();
         $this->add_log('Logs garbage collector ran.', 'debug');
     }
     //Clear the expired IP address filters (probability: 60%)
     if ($probability < 61) {
         $query = $db->getQuery(true);
         $query->delete($db->quoteName('#__jhackguard_ip_filters'));
         $query->where($db->quoteName('expires') . ' BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 36500 DAY) AND DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY)');
         $db->setQuery($query);
         $db->query();
         $this->add_log('IP filters garbage collector ran.', 'debug');
     }
     /* Maintenance steps end */
     /* Whitelisted Groups Check */
     $user = JFactory::getUser();
     $whg = $this->params->get('whitelisted_groups', array());
     foreach ($user->groups as $g) {
         if (in_array($g, $whg)) {
             $this->add_log('JHackGuard execution stopped because user group is whitelisted.', 'debug');
             return 0;
         }
     }
     /* IP black/white listing check */
     if ($this->ip_is('whitelisted')) {
         //Cease further processing
         $this->add_log('Encountered whitelisted IP', 'debug');
         return 0;
     }
     if ($this->ip_is('blacklisted')) {
         $this->add_log('Found blacklisted IP address. Script terminated.', 'standard');
         die(include_once JPATH_ADMINISTRATOR . '/components/com_jhackguard/blocked.html');
     }
     /* Administrator secret key addon */
     if ($this->params->get('admin_protection', 0)) {
         //Verify we have a secret word setup in the configuration.
         if (strlen($this->params->get('admin_keyword', '')) < 1) {
             $this->add_log('Administrator folder protection enabled but no keyword found.', 'debug');
         } else {
             //Check if the current page is in the administrator area.
             if (JFactory::getApplication()->isAdmin() and JFactory::getUser()->guest) {
                 if (is_array($_POST) and isset($_POST['option']) and $_POST['option'] == "com_login" and isset($_POST['task']) and $_POST['task'] == "login") {
                     //This is post login processing script and we do not want to filter it.
                     //TODO: check if we have actually came from a login page.
                     //Probably CSRF token would do the trick here.
                 } else {
                     if (!array_key_exists($this->params->get('admin_keyword', ''), $_GET)) {
                         //We have no secret word added to the URL. Redirecting to main page.
                         $this->add_log('No admin keyword found in request to administrator folder. Redirecting to main page. ', 'debug');
                         header("Location: " . JURI::base() . "..");
                         die;
                     }
                 }
             }
         }
     }
     /* Administrator secret word checks end */
     /* Filter Administrator panel, jHackGuard pages. We do not want to filter our own content, after all */
     if (JFactory::getApplication()->isAdmin() and !JFactory::getUser()->guest) {
         if (isset($_REQUEST['option']) and $_REQUEST['option'] == "com_jhackguard") {
             $this->add_log('Admin page com_jhackguard is whitelisted. Filters skipped.', 'debug');
             return 0;
         }
     }
     /* Input filters Start */
     if (file_exists(JPATH_ADMINISTRATOR . '/components/com_jhackguard/data/input_rules.php') and !file_exists(JPATH_ADMINISTRATOR . '/components/com_jhackguard/data/.disable_input_rules')) {
         require_once JPATH_ADMINISTRATOR . '/components/com_jhackguard/data/input_rules.php';
         if (class_exists('JHackGuard_Input_Filters')) {
             $rules = new JHackGuard_Input_Filters();
             $rules->run();
         } else {
             $this->add_log('Cannot locate JHackGuard_Input_Filters class in data/input_rules.php. Perhaps no rules have been defined yet.', 'debug');
         }
     } else {
         $this->add_log('No input filters found or .disable_input_rules was defined.', 'debug');
     }
     /* End of Input filters */
     /* Scan through or disable the upload files, if configured */
     if ($this->params->get('disable_uploads', 0)) {
         if (is_array($_FILES) and count($_FILES) > 0) {
             JFactory::getApplication()->enqueueMessage("File upload denied by JHackGuard.", "warning");
             $_FILES = array();
             //TADAAA. This is not OK. We should probably delete the tmp files.
         }
     }
     //Scan using or own rules.
     if ($this->params->get('scan_uploads', 1)) {
         if (is_array($_FILES) and count($_FILES) > 0 and is_readable(JPATH_ADMINISTRATOR . '/components/com_jhackguard/data/scans/rules.php')) {
             foreach ($_FILES as $key => $file) {
                 $hit = 0;
                 if (isset($file['tmp_name'])) {
                     if (is_array($file['tmp_name'])) {
                         foreach ($file['tmp_name'] as $tmp_file) {
                             include_once JPATH_ADMINISTRATOR . '/components/com_jhackguard/data/scans/rules.php';
                             $it = new SplFileInfo($tmp_file);
                             if ($it->isFile() and $it->isReadable()) {
                                 $s = new JHackGuard_OnDemand_Scan_Rules();
                                 $s->scan($it);
                                 if ($s->score > 99) {
                                     $hit = 1;
                                     JFactory::getApplication()->enqueueMessage("File upload denied by JHackGuard. Internal scan hit.", "warning");
                                     $this->add_log('Possible malicious file upload (score:' . $s->score . ').File deleted.', 'standard');
                                 } else {
                                     $this->add_log('Clean file upload (score:' . $s->score . ').', 'debug');
                                 }
                             }
                         }
                     }
                 }
                 //Do we have a hit?
                 if ($hit) {
                     unset($_FILES[$key]);
                 }
             }
             //End foreach in $_FILES
         }
     }
     //End if scan_uploads
     //Scan using CYMRU Malware Hash Registry.
     if ($this->params->get('use_cymru', 1)) {
         if (is_array($_FILES) and count($_FILES) > 0) {
             foreach ($_FILES as $key => $file) {
                 $hit = 0;
                 if (isset($file['tmp_name'])) {
                     if (is_array($file['tmp_name'])) {
                         foreach ($file['tmp_name'] as $tmp_file) {
                             if ($tmp_file != NULL) {
                                 $hash = md5_file($tmp_file);
                                 if (checkdnsrr($hash . ".malware.hash.cymru.com", "A")) {
                                     JFactory::getApplication()->enqueueMessage("File upload denied by JHackGuard. Cymru malware hash database hit.", "warning");
                                     $this->add_log('Possible malicious file upload (CYMRU Hash DB Hit).File deleted.', 'standard');
                                     $hit = 1;
                                 }
                             }
                         }
                     }
                 }
                 //Do we have a hit?
                 if ($hit) {
                     unset($_FILES[$key]);
                 }
             }
             //End foreach in $_FILES
         }
     }
     //End if use_cymru option.
     //END OF UPLOADED FILES CHECKS
 }
Example #2
0
 public function scan_files()
 {
     $dir = JPATH_ROOT;
     $id = 0;
     $maxFiles = 100;
     $start = 0;
     /* Files to be ignored by the scanner */
     $ignoreFiles = array(JPATH_ROOT . '/libraries/phpmailer/smtp.php', JPATH_ROOT . '/libraries/joomla/microdata/types.json', JPATH_ROOT . '/administrator/components/com_jhackguard/data/input_rules.php', JPATH_ROOT . '/administrator/components/com_jhackguard/data/backups/input_rules.backup.php', JPATH_ROOT . '/administrator/components/com_jhackguard/data/temp_rules.php', JPATH_ROOT . '/administrator/components/com_jhackguard/data/scans/rules.php', JPATH_ROOT . '/media/editors/codemirror/js/php.js', JPATH_ROOT . '/media/editors/tinymce/tinymce.min.js');
     if (isset($_POST['maxFiles'])) {
         $maxFiles = (int) $_POST['maxFiles'];
         if ($maxFiles == 0) {
             $maxFiles = 100;
         }
     }
     if (isset($_POST['startFrom'])) {
         $start = (int) $_POST['startFrom'];
     }
     if (isset($_POST['id']) and strlen($_POST['id']) > 0) {
         $id = (int) $_POST['id'];
     } else {
         echo json_encode(array("success" => false, "msg" => "Missing request id value."));
         return false;
     }
     chdir(JPATH_ROOT);
     //Rules file, verified by a previous AJAX call. TODO: verify it exists anyway...
     include_once JPATH_ADMINISTRATOR . '/components/com_jhackguard/data/scans/rules.php';
     //Hits, if any, will be written here
     $hits = array();
     //DB stuff..
     $db = JFactory::getDbo();
     // Create a new query object.
     $query = $db->getQuery(true);
     $query->select("DISTINCT (" . $db->quoteName('fname') . ")");
     $query->from($db->quoteName('#__jhackguard_scan_files'));
     $query->order('id ASC');
     $db->setQuery($query, $start, $maxFiles);
     $list = $db->loadObjectList();
     foreach ($list as $file) {
         //Check if file is to be ignored.
         if (in_array($file->fname, $ignoreFiles)) {
             continue;
         }
         //Not an ignored file.Continue checking...
         $it = new SplFileInfo($file->fname);
         if ($it->isFile() and $it->isReadable()) {
             $s = new JHackGuard_OnDemand_Scan_Rules();
             $s->scan($it);
             if ($s->score > 99) {
                 $hits[] = array('filename' => $file->fname, 'score' => $s->score, 'details' => $s->explain);
             }
         }
     }
     //We should insert the hits now, if any.
     if (count($hits) > 0) {
         $db = JFactory::getDbo();
         $query = $db->getQuery(true);
         $query->insert($db->quoteName('#__jhackguard_scan_hits'));
         $query->columns('fname, score, details, scan_id');
         foreach ($hits as $hit) {
             $ins = array($db->quote($hit['filename']), $db->quote($hit['score']), $db->quote(serialize($hit['details'])), $db->quote($id));
             $query->values(implode(',', $ins));
         }
         $db->setQuery($query);
         $db->query();
     }
     //Shall we continue?
     if (count($list) < $maxFiles) {
         $continue = false;
         //Seems like results from db were less than the max files.
     } else {
         $continue = true;
     }
     echo json_encode(array("success" => true, "continue" => $continue, "totalChecked" => count($list)));
 }