diff --git a/adm/tabs/AdminImport.php b/adm/tabs/AdminImport.php index ac81e603..5b4bdbef 100755 --- a/adm/tabs/AdminImport.php +++ b/adm/tabs/AdminImport.php @@ -898,6 +898,7 @@ class AdminImport extends AdminTab $image->id_product = (int)($product->id); $image->position = Image::getHighestPosition($product->id) + 1; $image->cover = (!$key AND !$productHasImages) ? true : false; + $image->legend = self::createMultiLangField($product->name); if (($fieldError = $image->validateFields(UNFRIENDLY_ERROR, true)) === true AND ($langFieldError = $image->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true AND $image->add()) { if (!self::copyImg($product->id, $image->id, $url)) diff --git a/modules/ant_alerthack/AdminAntAlertHack.php b/modules/ant_alerthack/AdminAntAlertHack.php new file mode 100644 index 00000000..cb96614a --- /dev/null +++ b/modules/ant_alerthack/AdminAntAlertHack.php @@ -0,0 +1,225 @@ +is_suspect = Tools::getValue('state'); + } + if($suspect->save()){ + echo HelperFormBootstrap::displaySuccess($this->l('Suspect has been updated')); + return; + } else { + echo HelperFormBootstrap::displayError($this->l('Error occured while updating Suspect')); + return; + } + } elseif (Tools::isSubmit('update_conf')) { + if(($limit = Tools::getValue('limit')) !== false) { + Configuration::updateValue('ANT_ALERTHACK_LIMIT', (int) $limit); + } + if($time = Tools::getValue('time')) { + Configuration::updateValue('ANT_ALERTHACK_TIME', (int) $time); + } + if($emails = Tools::getValue('emails')) { + Configuration::updateValue('ANT_ALERTHACK_EMAILS', $emails); + } + echo HelperFormBootstrap::displaySuccess($this->l('Configurations has been updated')); + return; + } + } + + public function display() { + global $cookie; + + $helper = new HelperFormBootstrap(); + $helper->_css.= $this->_addCss(); + $html = $helper->renderStyle(); + $html .= ' +
+
+
+
+

Alert Hack

+
+
+
+
+
+
'; + $input = array( + 'type' => 'text', + 'label' => $this->l('Emails :'), + 'name' => 'emails', + 'id' => 'emails', + 'required' => true, + 'help' => "Emails à alerter (séparés d'une virgule)", + 'default' => Configuration::get('ANT_ALERTHACK_EMAILS') + ); + $html.= $helper->generateInput($input); + $html.= '
'; + + $input = array( + 'type' => 'text', + 'label' => $this->l('Temps :'), + 'name' => 'time', + 'id' => 'time', + 'required' => true, + 'help' => "Temps en min ex: 5", + 'default' => Configuration::get('ANT_ALERTHACK_TIME') + ); + $html.= $helper->generateInput($input); + $html.= '
'; + + $input = array( + 'type' => 'text', + 'label' => $this->l('Limit :'), + 'name' => 'limit', + 'id' => 'limit', + 'required' => true, + 'help' => "Nombres de message envoyés dans le temps renseigné", + 'default' => Configuration::get('ANT_ALERTHACK_LIMIT') + ); + $html.= $helper->generateInput($input); + $html.= '
'; + + $html .=' +
+
+
+
+ +
+
+
+
+
+
+
'; + + $suspects = Suspect::getSuspects(); + $states = Suspect::$states; + $html .= ' +
+
+
+
+

Suspects

+
+
+
+
+
+ + + + + + + + + + + + + + '; + foreach ($suspects as $suspect) { + $html .= ' + + + + + + + + + + '; + } + $html .= ' + +
'.$this->l('ID').''.$this->l('email').''.$this->l('id_customer').''.$this->l('Remote IP').''.$this->l('Remote Host').''.$this->l('Condition').''.$this->l('State').''.$this->l('Action').'
'.$suspect['id_suspect'].''.$suspect['email'].''.$suspect['id_customer'].''.$suspect['remote_ip'].''.$suspect['remote_host'].''.$suspect['condition'].' '.$states[(int)$suspect['is_suspect']]['name'].' +
'; + if($suspect['is_suspect'] == 1){ + $html .= ' + + '; + }elseif($suspect['is_suspect'] == 2){ + $html .= ' + + '; + } + $html .=' + +
+
+
+
+
+
+
+
'; + + $html .= $helper->renderScript(); + + echo $html; + } + + protected function _addCss() + { + return ' + form sup { + color: #CC0000; + font-weight: bold; + vertical-align: sub; + } + #content .bootstrap-datetimepicker-widget tr th { + border-radius :0px !important; + } + .table tr th { + background: #565485; + background: rgba(86,84,133,0.9); + color: #fff; + font-size: 12px; + } + .table tr:nth-child(even) { + background: #F1F1F1; + } + .table>tbody>tr>td, + .table>tbody>tr>th, + .table>tfoot>tr>td, + .table>tfoot>tr>th, + .table>thead>tr>td, + .table>thead>tr>th { + vertical-align: middle; + } + .table .input-group-btn .btn { + padding: 4px 5px; + color: #504d8b; + + } + .table .input-group-btn .btn .anticon{ + font-size: 12px; + } + .bg-grey{ + background: #EFEFEF; + border-radius:4px; + } + .bg-grey .div-title { + border-bottom: 2px solid #504D8B; + } + .div-title i.anticon, + .div-title i.glyphicon, + ul li a{ + color:#504d8b; + } + '; + } +} \ No newline at end of file diff --git a/modules/ant_alerthack/ant_alerthack.php b/modules/ant_alerthack/ant_alerthack.php new file mode 100644 index 00000000..8800099d --- /dev/null +++ b/modules/ant_alerthack/ant_alerthack.php @@ -0,0 +1,179 @@ +name = 'ant_alerthack'; + $this->tab = 'administration'; + $this->author = 'Antadis'; + $this->version = '1.0'; + $this->need_instance = 0; + + parent::__construct(); + + $this->displayName = $this->l('Alert for hacking tentative'); + $this->description = $this->l('Alert when someone try to make SQL injection in contact form'); + } + + public function install() + { + // if (!$this->installDB()){ + // return false; + // } + + $hooks = array( + 'ant_alerthack' => array('Ant Alert Hack', 'Called when someone sends some messages in few minutes'), + 'ant_alerthackbefore' => array('Ant Alert Hack Before', 'Called before customer or visitor makes an action'), + ); + foreach($hooks as $k => $v) { + if(count(Db::getInstance()->ExecuteS(' + SELECT `id_hook` + FROM `'._DB_PREFIX_.'hook` + WHERE `name` = "'.$k.'" + LIMIT 1 + ')) == 0) { + Db::getInstance()->ExecuteS(' + INSERT INTO `'._DB_PREFIX_.'hook` + VALUES (DEFAULT, "'.$k.'", "'.$v[0].'", "'.$v[1].'", 0, 0) + '); + } + } + + if(!parent::install() + || !$this->registerHook('ant_alerthack') + || !$this->registerHook('ant_alerthackbefore')) { + return false; + } + + # Set default configuration values + Configuration::updateValue('ANT_ALERTHACK_LIMIT', 5); + Configuration::updateValue('ANT_ALERTHACK_TIME', 1); + Configuration::updateValue('ANT_ALERTHACK_EMAILS', 'marion@antadis.com'); + + return true; + } + + private function installDB() + { + $result = true; + # Add tables + $query = ' + CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'ant_alerthack_suspect` ( + `id_suspect` INTEGER NOT NULL AUTO_INCREMENT, + `id_customer` INTEGER DEFAULT 0, + `email` VARCHAR(128), + `page` VARCHAR(250), + `referrer` VARCHAR(250), + `user_agent` VARCHAR(128), + `remote_host` VARCHAR(255), + `remote_ip` VARCHAR(20), + `condition` VARCHAR(50), + `is_suspect` INTEGER DEFAULT 0, + `date_add` DATETIME NOT NULL, + `date_upd` DATETIME NOT NULL, + PRIMARY KEY(`id_suspect`) + ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8 + '; + + $result = Db::getInstance()->Execute($query); + + return $result; + } + + + public function uninstall() { + + if(parent::uninstall() == false) { + return false; + } + + Configuration::deleteByName('ANT_ALERTHACK_LIMIT'); + Configuration::deleteByName('ANT_ALERTHACK_TIME'); + Configuration::deleteByName('ANT_ALERTHACK_EMAILS'); + + return true; + } + + public function hookAnt_Alerthackbefore($params) { + global $cookie; + return true; + } + + public function hookAnt_Alerthack($params) { + global $cookie; + $min = (int)Configuration::get('ANT_ALERTHACK_TIME'); + $count_limit = (int)Configuration::get('ANT_ALERTHACK_LIMIT'); + $id_customer = ($params['id_customer']?$params['id_customer']:''); + + $count = Db::getInstance()->getValue(' + SELECT COUNT(m.`id_customer_message`) + FROM `'._DB_PREFIX_.'customer_message` m + LEFT JOIN `'._DB_PREFIX_.'customer_thread` t ON (t.`id_customer_thread` = m.`id_customer_thread`) + WHERE ( + t.`email` = "'.pSQL($params['email']).'" + '.(!empty($id_customer)?' OR t.`id_customer` = '.(int)$id_customer:'').' + ) + AND m.`date_add` < NOW() AND m.`date_add` > DATE_SUB(NOW(), INTERVAL '.$min.' MINUTE) + '); + + if($count >= $count_limit){ + $info = array( + 'count' => (int)$count, + 'time' => (int)$min + ); + $this->saveInfo($info, $params['email'], $id_customer); + + $emails = Configuration::get('ANT_ALERTHACK_EMAILS'); + $to = explode(',', $emails); + $data = array( + '{limit}' => (int)Configuration::get('ANT_ALERTHACK_LIMIT'), + '{time}' => (int)Configuration::get('ANT_ALERTHACK_TIME'), + '{suspect_email}' => $params['email'], + ); + foreach ($to as $email) { + Mail::Send((int)$cookie->id_lang, 'ant_alerthack', 'Alert Hack', $data, $to); + } + } + } + + public function saveInfo($info, $email, $id_customer = '') + { + + $remoteIP = $_SERVER['REMOTE_ADDR']; + if (strstr($remoteIP, ', ')) { + $ips = explode(', ', $remoteIP); + $remoteIP = $ips[0]; + } + $page = "https://{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"; + $page .= (!empty($_SERVER['QUERY_STRING'])? $_SERVER['QUERY_STRING']:''); + $referrer = $_SERVER['HTTP_REFERER']; + $useragent = $_SERVER['HTTP_USER_AGENT']; + $remotehost = gethostbyaddr($remoteIP); + $is_exist = Db::getInstance()->getRow(' + SELECT `id_suspect` + FROM `'._DB_PREFIX_.'ant_alerthack_suspect` + WHERE `email` = "'.pSQL($email).'" + '); + if($is_exist){ + $suspect = new Suspect((int)$is_exist['id_suspect']); + } else { + $suspect = new Suspect(); + } + $suspect->id_customer = (!empty($id_customer)?$id_customer:0); + $suspect->email = pSQL($email); + $suspect->page = pSQL($page); + $suspect->user_agent = pSQL($useragent); + $suspect->remote_host = pSQL($remotehost); + $suspect->remote_ip = pSQL($remoteIP); + $suspect->referrer = pSQL($referrer); + $suspect->is_suspect = 1; + $suspect->condition = pSQL($info['count'].' messages in '.$info['time'].' minutes'); + $suspect->save(); + } + +} diff --git a/modules/ant_alerthack/models/Suspect.php b/modules/ant_alerthack/models/Suspect.php new file mode 100644 index 00000000..77db2c7d --- /dev/null +++ b/modules/ant_alerthack/models/Suspect.php @@ -0,0 +1,125 @@ + array( + 'name' => "A vérifier", + 'icon' => 'anticon anticon-hour-glass text-orange', + ), + 1 => array( + 'name' => "Suspect", + 'icon' => 'anticon anticon-target text-rose', + ), + 2 => array( + 'name' => "Verifié", + 'icon' => 'anticon anticon-checkmark text-green-light', + ), + ); + + public $id_suspect; + public $id_customer; + public $email; + public $page; + public $referrer; + public $user_agent; + public $remote_host; + public $remote_ip; + public $condition; + public $is_suspect; + public $date_add; + public $date_upd; + + protected $fieldsRequired = array('email'); + protected $fieldsValidate = array( + 'id_suspect' => 'isUnsignedId', + 'id_customer' => 'isUnsignedId', + 'email' => 'isEmail', + 'page' => 'isString', + 'referrer' => 'isString', + 'user_agent' => 'isString', + 'remote_host' => 'isString', + 'remote_ip' => 'isString', + 'condition' => 'isString', + 'is_suspect' => 'isInt', + 'date_add' => 'isDate', + 'date_upd' => 'isDate', + ); + + protected $table = 'ant_alerthack_suspect'; + protected $identifier = 'id_suspect'; + + + public function getFields() + { + parent::validateFields(); + + $fields['id_suspect'] = (int)$this->id_suspect; + $fields['id_customer'] = (int)$this->id_customer; + $fields['email'] = pSQL($this->email); + $fields['page'] = pSQL($this->page); + $fields['referrer'] = pSQL($this->referrer); + $fields['user_agent'] = pSQL($this->user_agent); + $fields['remote_host'] = pSQL($this->remote_host); + $fields['remote_ip'] = pSQL($this->remote_ip); + $fields['condition'] = pSQL($this->condition); + $fields['is_suspect'] = (int)$this->is_suspect; + $fields['date_add'] = pSQL($this->date_add); + $fields['date_upd'] = pSQL($this->date_upd); + + return $fields; + } + + public function delete() + { + return true; + } + + /** + * Get suspects + * @param $states array get only suspects in specific states + * @return Array Groups + */ + public static function getSuspects($states = array(), $where = false) + { + if($where){ + return Db::getInstance()->executeS(' + SELECT * + FROM `'._DB_PREFIX_.'ant_alerthack_suspect` s + WHERE '.$where.' + '); + } else { + return Db::getInstance()->executeS(' + SELECT * + FROM `'._DB_PREFIX_.'ant_alerthack_suspect` s + WHERE 1 + '.(!empty($states) ? 'AND s.`is_suspect` IN ('.implode(',',$states).')' : '').' + ORDER BY s.date_add DESC + '); + } + } + + public function save() + { + if (parent::save()) { + return true; + } + } + + public static function isBannished($email){ + + $suspect = Db::getInstance()->getRow(' + SELECT `is_suspect` + FROM `'._DB_PREFIX_.'ant_alerthack_suspect` + WHERE `email` = "'.pSQL($email).'" + '); + if((int)$suspect['is_suspect'] == 1){ + return true; + } + return false; + } +} diff --git a/modules/ant_support_form/support.php b/modules/ant_support_form/support.php index e8b389ab..792c53b3 100644 --- a/modules/ant_support_form/support.php +++ b/modules/ant_support_form/support.php @@ -36,6 +36,12 @@ if ($cookie->isLogged()) { } if (Tools::isSubmit('submitMessage')) { + $alert_mode = false; + if(Module::isInstalled('ant_alerthack')) { + $alert_mode = true; + include_once dirname(__FILE__).'/../../modules/ant_alerthack/models/Suspect.php'; + } + $fileAttachment = NULL; if (isset($_FILES['fileUpload']['name']) AND !empty($_FILES['fileUpload']['name']) AND !empty($_FILES['fileUpload']['tmp_name'])) { @@ -46,24 +52,40 @@ if (Tools::isSubmit('submitMessage')) { $fileAttachment['mime'] = $_FILES['fileUpload']['type']; } $message = Tools::htmlentitiesUTF8(Tools::getValue('message')); - if (!($from = trim(Tools::getValue('from'))) OR !Validate::isEmail($from)) + if (!($from = trim(Tools::getValue('from'))) OR !Validate::isEmail($from)){ $errors[] = Tools::displayError('Invalid e-mail address'); - elseif (!($message = nl2br2($message))) + } + elseif ($alert_mode && Suspect::isBannished($from)){ + $errors[] = Tools::displayError('Message cannot be sent.'); + } + elseif (!($message = nl2br2($message))){ $errors[] = Tools::displayError('Message cannot be blank'); - elseif (!Validate::isCleanHtml($message)) + } + elseif (!Validate::isCleanHtml($message)){ $errors[] = Tools::displayError('Invalid message'); - elseif (!($id_contact = (int)(Tools::getValue('id_contact'))) OR !(Validate::isLoadedObject($contact = new Contact((int)($id_contact), (int)($cookie->id_lang))))) + } + elseif (!($id_contact = (int)(Tools::getValue('id_contact'))) OR !(Validate::isLoadedObject($contact = new Contact((int)($id_contact), (int)($cookie->id_lang))))){ $errors[] = Tools::displayError('Please select a subject on the list.'); - elseif (($id_contact = (int)(Tools::getValue('id_contact'))) && $id_contact == 9 && !Tools::getValue('id_reason')) + } + elseif (($id_contact = (int)(Tools::getValue('id_contact'))) && $id_contact == 9 && !Tools::getValue('id_reason')){ $errors[] = Tools::displayError('Please select a reason on the list.'); - elseif (($id_contact = (int)(Tools::getValue('id_contact'))) && ($id_contact == 9 || $id_contact == 1 || $id_contact == 2) && !Tools::getValue('id_order')) + } + elseif (($id_contact = (int)(Tools::getValue('id_contact'))) && ($id_contact == 9 || $id_contact == 1 || $id_contact == 2) && !Tools::getValue('id_order')){ $errors[] = Tools::displayError('Please enter/choose an order ID'); - elseif (($id_contact = (int)(Tools::getValue('id_contact'))) && $id_contact == 1 && !Tools::getValue('id_products')) - $errors[] = Tools::displayError('Please choose a product'); - elseif (!empty($_FILES['fileUpload']['name']) AND $_FILES['fileUpload']['error'] != 0) + } + elseif (($id_contact = (int)(Tools::getValue('id_contact'))) && $id_contact == 1 && !Tools::getValue('id_products')){ + if((int)($cookie->id_customer)){ + $errors[] = Tools::displayError('Please choose a product'); + } else { + $errors[] = Tools::displayError('You have to be logged'); + } + } + elseif (!empty($_FILES['fileUpload']['name']) AND $_FILES['fileUpload']['error'] != 0){ $errors[] = Tools::displayError('An error occurred during the file upload'); - elseif (!empty($_FILES['fileUpload']['name']) AND !in_array(substr($_FILES['fileUpload']['name'], -4), $extension) AND !in_array(substr($_FILES['fileUpload']['name'], -5), $extension)) + } + elseif (!empty($_FILES['fileUpload']['name']) AND !in_array(substr($_FILES['fileUpload']['name'], -4), $extension) AND !in_array(substr($_FILES['fileUpload']['name'], -5), $extension)){ $errors[] = Tools::displayError('Bad file extension'); + } else { if ((int)($cookie->id_customer)) @@ -218,7 +240,11 @@ if (Tools::isSubmit('submitMessage')) { $errors[] = Tools::displayError('An error occurred while sending message.'); } - // Module::hookExec('ant_alert', array()); // @ToDo - uncomment it + Module::hookExec('ant_alerthack', array( + 'email' => $from, + 'id_customer' => (isset($customer->id)?$customer->id:false), + 'message' => $message + )); if (count($errors) > 1) array_unique($errors); diff --git a/override/controllers/ContactController.php b/override/controllers/ContactController.php index fa7bdaf6..2a6d26db 100755 --- a/override/controllers/ContactController.php +++ b/override/controllers/ContactController.php @@ -3,7 +3,7 @@ class ContactController extends ContactControllerCore { public function preProcess() { - parent::preProcess(); + FrontController::preProcess(); if (self::$cookie->isLogged()) { @@ -40,6 +40,12 @@ class ContactController extends ContactControllerCore { if (Tools::isSubmit('submitMessage')) { + $alert_mode = false; + if(Module::isInstalled('ant_alerthack')) { + $alert_mode = true; + include_once dirname(__FILE__).'/../../modules/ant_alerthack/models/Suspect.php'; + } + $fileAttachment = NULL; if (isset($_FILES['fileUpload']['name']) AND !empty($_FILES['fileUpload']['name']) AND !empty($_FILES['fileUpload']['tmp_name'])) { @@ -50,18 +56,27 @@ class ContactController extends ContactControllerCore { $fileAttachment['mime'] = $_FILES['fileUpload']['type']; } $message = Tools::htmlentitiesUTF8(Tools::getValue('message')); - if (!($from = trim(Tools::getValue('from'))) OR !Validate::isEmail($from)) + if (!($from = trim(Tools::getValue('from'))) OR !Validate::isEmail($from)){ $this->errors[] = Tools::displayError('Invalid e-mail address'); - elseif (!($message = nl2br2($message))) + } + elseif ($alert_mode AND Suspect::isBannished($from)){ + $this->errors[] = Tools::displayError('Message cannot be sent.'); + } + elseif (!($message = nl2br2($message))){ $this->errors[] = Tools::displayError('Message cannot be blank'); - elseif (!Validate::isCleanHtml($message)) + } + elseif (!Validate::isCleanHtml($message)){ $this->errors[] = Tools::displayError('Invalid message'); - elseif (!($id_contact = (int)(Tools::getValue('id_contact'))) OR !(Validate::isLoadedObject($contact = new Contact((int)($id_contact), (int)(self::$cookie->id_lang))))) + } + elseif (!($id_contact = (int)(Tools::getValue('id_contact'))) OR !(Validate::isLoadedObject($contact = new Contact((int)($id_contact), (int)(self::$cookie->id_lang))))){ $this->errors[] = Tools::displayError('Please select a subject on the list.'); - elseif (!empty($_FILES['fileUpload']['name']) AND $_FILES['fileUpload']['error'] != 0) + } + elseif (!empty($_FILES['fileUpload']['name']) AND $_FILES['fileUpload']['error'] != 0){ $this->errors[] = Tools::displayError('An error occurred during the file upload'); - elseif (!empty($_FILES['fileUpload']['name']) AND !in_array(substr($_FILES['fileUpload']['name'], -4), $extension) AND !in_array(substr($_FILES['fileUpload']['name'], -5), $extension)) + } + elseif (!empty($_FILES['fileUpload']['name']) AND !in_array(substr($_FILES['fileUpload']['name'], -4), $extension) AND !in_array(substr($_FILES['fileUpload']['name'], -5), $extension)){ $this->errors[] = Tools::displayError('Bad file extension'); + } else { if ((int)(self::$cookie->id_customer)) @@ -188,6 +203,11 @@ class ContactController extends ContactControllerCore { } Module::hookExec('ant_alert', array()); + Module::hookExec('ant_alerthack', array( + 'email' => $from, + 'id_customer' => (isset($customer->id)?$customer->id:false), + 'message' => $message + )); if (count($this->errors) > 1) array_unique($this->errors);