From 5480a216efce111c1afa6ec3508bda292732d09e Mon Sep 17 00:00:00 2001 From: x2003bruneau Date: Sat, 20 Jan 2007 19:22:45 +0000 Subject: [PATCH] New IP watcher : Each IP can have 5 states : -> not in our database -> safe and in our databe -> registration is forbidden -> all actions are logged -> authentification forbidden git-svn-id: svn+ssh://murphy/home/svn/platal/trunk@1369 839d8a87-29fc-0310-9880-83ba4fa771e5 --- ChangeLog | 1 + htdocs/images/icons/information.gif | Bin 0 -> 1314 bytes include/xorg.misc.inc.php | 28 ++++++++ include/xorg/session.inc.php | 63 +++++++++++------ modules/admin.php | 96 +++++++++++++++++++++++++ modules/axletter.php | 2 +- modules/register.php | 34 +++++---- modules/register/register.inc.php | 16 ----- templates/admin/index.tpl | 2 + templates/admin/ipwatcher.tpl | 136 ++++++++++++++++++++++++++++++++++++ upgrade/0.9.13/05_ip_watcher.sql | 15 ++++ 11 files changed, 344 insertions(+), 49 deletions(-) create mode 100644 htdocs/images/icons/information.gif create mode 100644 templates/admin/ipwatcher.tpl create mode 100644 upgrade/0.9.13/05_ip_watcher.sql diff --git a/ChangeLog b/ChangeLog index 9ff7535..c0e948b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,7 @@ New: * Admin: - Show last contact date on marketing validation -Fal/FRU - New page to add users in the database -FRU + - New IP based security tool -FRU * AXLetter: - New module AXLetter (legal mailer for AX) -FRU diff --git a/htdocs/images/icons/information.gif b/htdocs/images/icons/information.gif new file mode 100644 index 0000000000000000000000000000000000000000..9e9186c44132488267873c68bffb1ae6bc293624 GIT binary patch literal 1314 zcmdUvO-vI(6vtmnu`QylPyrFNfMS&v77%Uu3Z;oa@K6bn%BiJPmITUXyI{RFe8|Sr z8V@#x!-|R7gCTn`W{=Bl6CqhO!A6NG#u$!75>un3&U7^-M&iYbFPXQ$dGlued2eU8 zr|*i}6S9I8J^?m=Tp)TAabE6X6?Z~TO6fSSCIpqjUSS0#z)Hb{NF`-KPIF?46V)Iq z1rj0=mncpmNYRg&6o{ZeCY2y3kx4no$pKa*IhpV$DPATyiApMjp9^wIfRo}pVwUJ- z<4Gi!N{T8krFbdL%PCe+MJ3HiDFLyVl9Y5@P&r9eQ`;1;^m3}2-X?i%KWg~m-!e8YStM5W8># z&=VQc571c&khiuU8;$`yeF9KgyB~9u0URF!kec^nyVr6}(Uq*lZZ@MvBhwXj1LVKY zW_N1=jQ0WdxNP>@ayGm77-?(*$kFgLJ(J5t*?JGa-{x9z+UeR$z&bw%4*$lR(Od)Y z3J?H~dI5$C0QwgI9&Q1gTLCD3jy}~R0D~UTyFdOKTC;Nd%6*}U@ew-2L`LoS!uX~p zrsxz(!{f@sO9I+XEwV`C+5o=jpmxp z&YBueL*bm^kk#|d<*HaUHQ8tLS87(fx=ycGG@qHZSnumRows(); +} + +function send_warning_mail($title) +{ + $mailer = new PlMailer(); + $mailer->setFrom("webmaster@polytechnique.org"); + $mailer->addTo("florent.bruneau@polytechnique.org"); + $mailer->setSubject($title); + $mailer->setTxtBody("Identifiants de session :\n" . var_export($_SESSION, true) . "\n\n" + ."Identifiants de connexion :\n" . var_export($_SERVER, true)); + $mailer->send(); +} + ?> diff --git a/include/xorg/session.inc.php b/include/xorg/session.inc.php index 51ccfa4..71fe324 100644 --- a/include/xorg/session.inc.php +++ b/include/xorg/session.inc.php @@ -19,21 +19,28 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ***************************************************************************/ +require_once 'xorg.misc.inc.php'; + class XorgSession { // {{{ public static function init - public static function init() { + public static function init() + { S::init(); - if (!S::has('uid')) { - try_cookie(); + if (!S::has('uid')) { + try_cookie(); + } + if (check_ip('dangerous') && S::has('uid')) { + $_SESSION['log']->log("view_page", $_SERVER['REQUEST_URI']); } } // }}} // {{{ public static function destroy() - public static function destroy() { + public static function destroy() + { S::destroy(); XorgSession::init(); } @@ -116,7 +123,9 @@ class XorgSession if ($logger) { $logger->log('auth_ok'); } - start_connexion($uid, true); + if (!start_connexion($uid, true)) { + return false; + } if (Env::v('remember', 'false') == 'true') { $cookie = hash_encrypt(S::v('password')); setcookie('ORGaccess',$cookie,(time()+25920000),'/','',0); @@ -150,16 +159,16 @@ class XorgSession */ public static function doAuthCookie() { - if (S::logged()) { - return true; + if (S::logged()) { + return true; } - if (Env::has('username') and Env::has('response')) { - return XorgSession::doAuth(); + if (Env::has('username') and Env::has('response')) { + return XorgSession::doAuth(); } - if ($r = try_cookie()) { - return XorgSession::doAuth(($r > 0)); + if ($r = try_cookie()) { + return XorgSession::doAuth(($r > 0)); } return false; @@ -177,7 +186,7 @@ class XorgSession function try_cookie() { if (Cookie::v('ORGaccess') == '' or !Cookie::has('ORGuid')) { - return -1; + return -1; } $res = @XDB::query( @@ -186,13 +195,15 @@ function try_cookie() Cookie::i('ORGuid')); if ($res->numRows() != 0) { - list($uid, $password) = $res->fetchOneRow(); - require_once('secure_hash.inc.php'); - $expected_value = hash_encrypt($password); - if ($expected_value == Cookie::v('ORGaccess')) { - start_connexion($uid, false); - return 0; - } else { + list($uid, $password) = $res->fetchOneRow(); + require_once('secure_hash.inc.php'); + $expected_value = hash_encrypt($password); + if ($expected_value == Cookie::v('ORGaccess')) { + if (!start_connexion($uid, false)) { + return -3; + } + return 0; + } else { return 1; } } @@ -217,7 +228,7 @@ function start_connexion ($uid, $identified) FROM auth_user_md5 AS u INNER JOIN auth_user_quick AS q USING(user_id) INNER JOIN aliases AS a ON (u.user_id = a.id AND a.type='a_vie') - INNER JOIN aliases AS a2 ON (u.user_id = a2.id AND FIND_IN_SET('bestalias',a2.flags)) + INNER JOIN aliases AS a2 ON (u.user_id = a2.id AND FIND_IN_SET('bestalias',a2.flags)) LEFT JOIN logger.sessions AS s ON (s.uid=u.user_id AND s.suid=0) WHERE u.user_id = {?} AND u.perms IN('admin','user') ORDER BY s.start DESC @@ -239,7 +250,19 @@ function start_connexion ($uid, $identified) $_SESSION = array_merge($_SESSION, $sess); $_SESSION['log'] = $logger; $_SESSION['auth'] = ($identified ? AUTH_MDP : AUTH_COOKIE); + if (check_ip('unsafe')) { + send_warning_mail("Une IP surveillee a tente de se connecter"); + if (check_ip('ban')) { + $_SESSION = array(); + global $page; + $page->trig("Une erreur est survenue lors de la procédure d'authentification. " + ."Merci de contacter au plus vite " + ."support@polytechnique.org"); + return false; + } + } set_skin(); + return true; } // }}} diff --git a/modules/admin.php b/modules/admin.php index 0c5ff0c..54ef3b1 100644 --- a/modules/admin.php +++ b/modules/admin.php @@ -43,6 +43,7 @@ class AdminModule extends PLModule 'admin/validate' => $this->make_hook('validate', AUTH_MDP, 'admin'), 'admin/validate/answers' => $this->make_hook('validate_answers', AUTH_MDP, 'admin'), 'admin/wiki' => $this->make_hook('wiki', AUTH_MDP, 'admin'), + 'admin/ipwatch' => $this->make_hook('ipwatch', AUTH_MDP, 'admin'), ); } @@ -913,6 +914,101 @@ class AdminModule extends PLModule $page->assign('wiki_pages', $wiki_tree); $page->assign('perms_opts', $perms); } + + function handler_ipwatch(&$page, $action = 'list', $ip = null) + { + $page->changeTpl('admin/ipwatcher.tpl'); + + $states = array('safe' => 'Ne pas surveiller', + 'unsafe' => 'Surveiller les inscription', + 'dangerous' => 'Surveiller tous les accès', + 'ban' => 'Bannir cette adresse'); + $page->assign('states', $states); + + switch (Post::v('action')) { + case 'create': + if (trim(Post::v('ipN')) != '') { + Xdb::execute('INSERT IGNORE INTO ip_watch (ip, state, detection, last, uid, description) + VALUES ({?}, {?}, CURDATE(), NOW(), {?}, {?})', + trim(Post::v('ipN')), Post::v('stateN'), S::i('uid'), Post::v('descriptionN')); + }; + break; + + case 'edit': + Xdb::execute('UPDATE ip_watch + SET state = {?}, last = NOW(), uid = {?}, description = {?} + WHERE ip = {?}', Post::v('stateN'), S::i('uid'), Post::v('descriptionN'), Post::v('ipN')); + break; + + default: + if ($action == 'delete' && !is_null($ip)) { + Xdb::execute('DELETE FROM emails_watch WHERE ip = {?}', $ip); + } + } + if ($action != 'create' && $action != 'edit') { + $action = 'list'; + } + $page->assign('action', $action); + + if ($action == 'list') { + $sql = "SELECT w.ip, s.host, w.detection, w.state, a.alias AS forlife + FROM ip_watch AS w + LEFT JOIN logger.sessions AS s USING(ip) + LEFT JOIN aliases AS a ON (a.id = s.uid AND a.type = 'a_vie') + GROUP BY w.ip, a.alias + ORDER BY w.state, w.ip, a.alias"; + $it = Xdb::iterRow($sql); + + $table = array(); + $props = array(); + while (list($ip, $host, $date, $state, $forlife) = $it->next()) { + if (count($props) == 0 || $props['ip'] != $ip) { + if (count($props) > 0) { + $table[] = $props; + } + $props = array('ip' => $ip, + 'host' => $host, + 'detection' => $date, + 'state' => $state, + 'users' => array($forlife)); + } else { + $props['users'][] = $forlife; + } + } + if (count($props) > 0) { + $table[] = $props; + } + $page->assign('table', $table); + } elseif ($action == 'edit') { + $sql = "SELECT w.detection, w.state, w.last, w.description, + a1.alias AS edit, a2.alias AS forlife, s.host + FROM ip_watch AS w + LEFT JOIN aliases AS a1 ON (a1.id = w.uid AND a1.type = 'a_vie') + LEFT JOIN logger.sessions AS s ON (w.ip = s.ip) + LEFT JOIN aliases AS a2 ON (a2.id = s.uid AND a2.type = 'a_vie') + WHERE w.ip = {?} + GROUP BY a2.alias + ORDER BY a2.alias"; + $it = Xdb::iterRow($sql, $ip); + + $props = array(); + while (list($detection, $state, $last, $description, $edit, $forlife, $host) = $it->next()) { + if (count($props) == 0) { + $props = array('ip' => $ip, + 'host' => $host, + 'detection' => $detection, + 'state' => $state, + 'last' => $last, + 'description' => $description, + 'edit' => $edit, + 'users' => array($forlife)); + } else { + $props['users'][] = $forlife; + } + } + $page->assign('ip', $props); + } + } } ?> diff --git a/modules/axletter.php b/modules/axletter.php index 4ef05de..5a93897 100644 --- a/modules/axletter.php +++ b/modules/axletter.php @@ -362,7 +362,7 @@ class AXLetterModule extends PLModule function createHash($line, $key) { - $hash = implode(time(), $line); + $hash = implode(time(), $line) . rand(); $hash = md5($hash); return $hash; } diff --git a/modules/register.php b/modules/register.php index 4e57aff..a309bb7 100644 --- a/modules/register.php +++ b/modules/register.php @@ -33,6 +33,7 @@ class RegisterModule extends PLModule function handler_register(&$page, $hash = null) { + $alert = null; $sub_state = S::v('sub_state', Array()); if (!isset($sub_state['step'])) { $sub_state['step'] = 0; @@ -122,7 +123,6 @@ class RegisterModule extends PLModule break; case 3: - $alert = null; if (count($_POST)) { require_once(dirname(__FILE__) . '/register/register.inc.php'); if (!isvalid_email(Post::v('email'))) { @@ -139,7 +139,7 @@ class RegisterModule extends PLModule $promo = (int)$sub_state['promo']; if ($year > $promo - 15 || $year < $promo - 30) { $err[] = "La 'Date de naissance' n'est pas correcte."; - $alert = "Date de naissance proposée $birth\n\n"; + $alert = "Date de naissance incorrecte a l'inscription - "; } } @@ -157,10 +157,11 @@ class RegisterModule extends PLModule $aliases[] = $alias; } if (count($aliases) != 0) { - $alert .= "Email proposé : " . Post::v('email') . "\n" - . "Ce mails est connu avec l'état $state :\n" - . $description . "\n" - . "Pour les alias :\n* " . join("\n* ", $aliases) . "\n\n"; + $alert .= "Email surveille propose a l'inscription - "; + } + + if (check_ip('unsafe')) { + unset($err); } if (isset($err)) { @@ -171,17 +172,24 @@ class RegisterModule extends PLModule substr($birth,2,2), substr($birth,0,2)); $sub_state['email'] = Post::v('email'); - $sub_state['step'] = 4; - finish_ins($sub_state); - } - if (!is_null($alert)) { - send_alert_mail($sub_state, $alert); + if (check_ip('unsafe')) { + $err = "Une erreur s'est produite lors de l'inscription." + . " Merci de contacter register@polytechnique.org" + . " pour nous faire part de cette erreur"; + $alert .= "Tentative d'inscription depuis une IP surveillee"; + } else { + $sub_state['step'] = 4; + finish_ins($sub_state); + } } } break; } $_SESSION['sub_state'] = $sub_state; + if ($alert) { + send_warning_mail($alert); + } $page->changeTpl('register/step'.intval($sub_state['step']).'.tpl'); if (isset($err)) { $page->trig($err); @@ -269,7 +277,9 @@ class RegisterModule extends PLModule $mymail->assign('prenom', $prenom); $mymail->send(); - start_connexion($uid,false); + if (!start_connexion($uid,false)) { + return PL_FORBIDDEN; + } $_SESSION['auth'] = AUTH_MDP; /***********************************************************/ diff --git a/modules/register/register.inc.php b/modules/register/register.inc.php index 4189719..59235d2 100644 --- a/modules/register/register.inc.php +++ b/modules/register/register.inc.php @@ -217,22 +217,6 @@ function create_aliases (&$sub) } // }}} -// {{{ function send_alert_mail - -function send_alert_mail($state, $body) -{ - $mailer = new PlMailer(); - $mailer->setFrom("webmaster@polytechnique.org"); - $mailer->addTo("hotliners@staff.polytechnique.org"); - $mailer->setSubject("ALERTE LORS DE L'INSCRIPTION de " - . $state['prenom'] . ' ' . $state['nom'] . '(' . $promo . ')'); - $mailer->setTxtBody($body - . "\n\nIndentifiants :\n" . var_export($state, true) - . "\n\nInformations de connexion :\n" . var_export($_SERVER, true)); - $mailer->send(); -} - -// }}} // {{{ function finish_ins function finish_ins($sub_state) diff --git a/templates/admin/index.tpl b/templates/admin/index.tpl index 679e18a..95e26e2 100644 --- a/templates/admin/index.tpl +++ b/templates/admin/index.tpl @@ -44,6 +44,8 @@ Actions   |   Doublons +   |   + IPs diff --git a/templates/admin/ipwatcher.tpl b/templates/admin/ipwatcher.tpl new file mode 100644 index 0000000..73821b3 --- /dev/null +++ b/templates/admin/ipwatcher.tpl @@ -0,0 +1,136 @@ +{**************************************************************************} +{* *} +{* Copyright (C) 2003-2007 Polytechnique.org *} +{* http://opensource.polytechnique.org/ *} +{* *} +{* This program is free software; you can redistribute it and/or modify *} +{* it under the terms of the GNU General Public License as published by *} +{* the Free Software Foundation; either version 2 of the License, or *} +{* (at your option) any later version. *} +{* *} +{* This program is distributed in the hope that it will be useful, *} +{* but WITHOUT ANY WARRANTY; without even the implied warranty of *} +{* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *} +{* GNU General Public License for more details. *} +{* *} +{* You should have received a copy of the GNU General Public License *} +{* along with this program; if not, write to the Free Software *} +{* Foundation, Inc., *} +{* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *} +{* *} +{**************************************************************************} + +

Gestion des IPs surveillées

+ +{if $action eq "list"} + + + + + + + + + + + + {foreach from=$table item=ip} + + + + + + + {/foreach} +
AdresseEtatUtilisateurs
+ Ajouter une entrée + + créer{icon name=add} +
+ {$ip.ip}
+ {$ip.host}
+ Ajoutée le {$ip.detection|date_format} +
+ {$ip.state} + + {foreach from=$ip.users item=user name=all} + {if $user} + {$user} + {icon name=wrench title=Administrer} + {icon name=information title="Logs"}{if !$smarty.foreach.all.last}
{/if} + {/if} + {/foreach} +
+ {icon name=page_edit title="Editer"} + {icon name=delete title="Supprimer"} +
+{elseif $action eq "create" || $action eq "edit"} +[Retour à la liste des IPs surveillées]

+
+ + + + + + {if $action eq "create"} + + + {else} + + + {foreach from=$ip.users key=i name=all item=user} + {if $user} + {if $i is even}{/if} + + {if $i is even && $smarty.foreach.all.last}{/if} + {if $i is odd || $smarty.foreach.all.last}{/if} + {/if} + {/foreach} + + + + {/if} + + + + + + + + {if $ip.edit} + + + + {/if} + + + + + + + +
Commenter une adresse IP
Adresse IP + {$ip.ip} ({$ip.host}) + +
+ {$user} + {icon name=wrench title="Administrer} + {icon name=information title="Logs"}{if !$smarty.foreach.all.last}
{/if} +
Date de détection{$ip.detection|date_format}
Danger + +
Description
+ Dernière édition par {$ip.edit} le {$ip.last|date_format} +
+ +
+ + +
+
+{/if} + +{* vim:set et sw=2 sts=2 sws=2: *} diff --git a/upgrade/0.9.13/05_ip_watcher.sql b/upgrade/0.9.13/05_ip_watcher.sql new file mode 100644 index 0000000..d8ad573 --- /dev/null +++ b/upgrade/0.9.13/05_ip_watcher.sql @@ -0,0 +1,15 @@ +CREATE TABLE `ip_watch` ( + `ip` CHAR(16) NOT NULL, + `state` ENUM('safe', 'unsafe', 'dangerous', 'ban') NOT NULL DEFAULT 'unsafe', + `detection` DATE DEFAULT 0, + `last` TIMESTAMP DEFAULT 0, + `uid` SMALLINT(5) DEFAULT NULL, + `description` TEXT NOT NULL, + PRIMARY KEY(`ip`) +); +use logger; +alter table sessions add key(ip); +insert into actions (text, description) values ('view_page', 'Consultation d\'une page'); +use x4dat; + +# vim:set syntax=mysql: -- 2.1.4