source: spip-zone/_core_/securite/ecran_securite.php

Last change on this file was 112421, checked in by root, 2 months ago

ajout de robots qui font des hits sur des pages html + finalement ne pas lister les lecteurs RSS et podcast ici. Il ne sont pas comptés dans les stats de spip par défaut, et on ne souhaite pas les bloquer en cas de load.

File size: 14.3 KB
RevLine 
[1808]1<?php
2
3/*
4 * ecran_securite.php
5 * ------------------
[30260]6 */
7
[112247]8define('_ECRAN_SECURITE', '1.3.8'); // 2018-10-31
[30260]9
10/*
[30618]11 * Documentation : http://www.spip.net/fr_article4200.html
[1808]12 */
13
[30706]14/*
[63229]15 * Test utilisateur
[30706]16 */
17if (isset($_GET['test_ecran_securite']))
18        $ecran_securite_raison = 'test '._ECRAN_SECURITE;
[1808]19
[95895]20/*
21 * Monitoring
22 * var_isbot=0 peut etre utilise par un bot de monitoring pour surveiller la disponibilite d'un site vu par les users
23 * var_isbot=1 peut etre utilise pour monitorer la disponibilite pour les bots (sujets a 503 de delestage si
24 * le load depasse ECRAN_SECURITE_LOAD)
[95823]25 */
[104721]26if (!defined('_IS_BOT') and isset($_GET['var_isbot'])){
27        define('_IS_BOT', $_GET['var_isbot'] ? true : false);
28}
[95823]29
[33298]30/*
[95967]31 * Détecteur de robot d'indexation
[33298]32 */
[104721]33if (!defined('_IS_BOT')){
[33298]34        define('_IS_BOT',
35                isset($_SERVER['HTTP_USER_AGENT'])
[112247]36                and preg_match(','
37                . implode ('|', array(
38                        // mots generiques
39                        'bot',
40                        'slurp',
41                        'crawler',
[112421]42                        'crwlr',
43                        'java',
44                        'monitoring',
[112247]45                        'spider',
46                        'webvac',
47                        'yandex',
48                        'MSIE 6\.0', // botnet 99,9% du temps
49                        // UA plus cibles
50                        '200please',
51                        '80legs',
52                        'a6-indexer',
53                        'aboundex',
54                        'accoona',
[112421]55                        'acrylicapps',
[112247]56                        'addthis',
57                        'adressendeutschland',
58                        'alexa',
59                        'altavista',
60                        'analyticsseo',
[112406]61                        'antennapod',
[112421]62                        'arachnys',
[112247]63                        'archive',
[112421]64                        'argclrint',
[112247]65                        'aspseek',
66                        'baidu',
67                        'begunadvertising',
[112421]68                        'bing',
[112247]69                        'bloglines',
[112421]70                        'buck',
[112247]71                        'browsershots',
72                        'bubing',
73                        'butterfly',
74                        'changedetection',
75                        'charlotte',
76                        'chilkat',
77                        'china',
78                        'coccoc',
79                        'crowsnest',
80                        'dataminr',
81                        'daumoa',
[112421]82                        'dlvr\.it',
[112247]83                        'dlweb',
[112421]84                        'drupal',
[112247]85                        'ec2linkfinder',
[112421]86                        'eset\.com',
[112247]87                        'estyle',
[112421]88                        'exalead',
[112247]89                        'ezooms',
90                        'facebookexternalhit',
91                        'facebookplatform',
92                        'fairshare',
93                        'feedfetcher',
94                        'feedfetcher-google',
95                        'feedly',
96                        'fetch',
97                        'flipboardproxy',
98                        'genieo',
99                        'google',
[112421]100                        'go-http-client',
[112247]101                        'grapeshot',
102                        'hatena-useragent',
103                        'head',
104                        'hosttracker',
105                        'hubspot',
106                        'ia_archiver',
107                        'ichiro',
108                        'iltrovatore-setaccio',
109                        'immediatenet',
110                        'ina',
[112355]111                        'inoreader',
[112247]112                        'infegyatlas',
113                        'infohelfer',
114                        'instapaper',
115                        'jabse',
116                        'james',
[112421]117                        'jersey',
[112247]118                        'kumkie',
119                        'linkdex',
120                        'linkfluence',
121                        'linkwalker',
122                        'litefinder',
123                        'loadimpactpageanalyzer',
[112355]124                        'ltx71',
[112247]125                        'luminate',
126                        'lycos',
127                        'lycosa',
128                        'mediapartners-google',
129                        'msai',
[112421]130                        'myapp',
131                        'nativehost',
[112247]132                        'najdi',
133                        'netcraftsurveyagent',
134                        'netestate',
135                        'netseer',
[112421]136                        'netnewswire',
137                        'newspaper',
138                        'newsblur',
[112247]139                        'nuhk',
[112421]140                        'nuzzel',
141                        'okhttp',
142                        'otmedia',
[112248]143                        'owlin',
[112421]144                        'owncloud',
[112247]145                        'panscient',
[112421]146                        'paper\.li',
[112247]147                        'parsijoo',
[112421]148                        'protopage',
[112247]149                        'plukkie',
150                        'proximic',
[112421]151                        'pubsub',
152                        'python',
[112247]153                        'qirina',
[112421]154                        'qoshe',
[112247]155                        'qualidator',
[112356]156                        'qwantify',
[112247]157                        'rambler',
158                        'readability',
[112421]159                        'ruby',
[112247]160                        'sbsearch',
[112421]161                        'scoop\.it',
[112247]162                        'scooter',
[112421]163                        'scoutjet',
[112247]164                        'scrapy',
165                        'scrubby',
166                        'scrubbybloglines',
167                        'shareaholic',
168                        'shopwiki',
[112352]169                        'simplepie',
[112247]170                        'sistrix',
171                        'sitechecker',
172                        'siteexplorer',
[112421]173                        'snapshot',
[112247]174                        'sogou',
175                        'special_archiver',
176                        'speedy',
177                        'spinn3r',
178                        'spreadtrum',
179                        'steeler',
180                        'subscriber',
181                        'suma',
182                        'superdownloads',
183                        'svenska-webbsido',
184                        'teoma',
[112421]185                        'the knowledge AI',
[112247]186                        'thumbshots',
187                        'tineye',
[112355]188                        'traackr',
[112247]189                        'trendiction',
[112421]190                        'trendsmap',
[112247]191                        'tweetedtimes',
192                        'tweetmeme',
[112406]193                        'universalfeedparser',
[112247]194                        'uaslinkchecker',
195                        'undrip',
196                        'unwindfetchor',
[112421]197                        'upday',
[112247]198                        'vedma',
199                        'vkshare',
200                        'vm',
201                        'wch',
202                        'webalta',
203                        'webcookies',
[112421]204                        'webparser',
[112247]205                        'webthumbnail',
206                        'wesee',
207                        'wise-guys',
208                        'woko',
[112352]209                        'wordpress',
[112247]210                        'wotbox',
211                        'y!j-bri',
212                        'y!j-bro',
213                        'y!j-brw',
214                        'y!j-bsc',
215                        'yahoo',
216                        'yahoo!',
217                        'yahooysmcm',
[112421]218                        'ymobactus',
[112247]219                        'yats',
220                        'yeti',
221                        'zeerch'
222                )) . ',i',
223                (string)$_SERVER['HTTP_USER_AGENT'])
[33298]224        );
[104721]225}
226if (!defined('_IS_BOT_FRIEND')){
227        define('_IS_BOT_FRIEND',
228                isset($_SERVER['HTTP_USER_AGENT'])
[112247]229                and preg_match(',' . implode ('|', array(
230                        'facebookexternalhit',
[112352]231                        'flipboardproxy',
232                        'wordpress'
[112247]233                )) . ',i',
234                (string)$_SERVER['HTTP_USER_AGENT'])
[104721]235        );
236}
[30706]237
[63229]238/*
239 * Interdit de passer une variable id_article (ou id_xxx) qui ne
[95967]240 * soit pas numérique (ce qui bloque l'exploitation de divers trous
241 * de sécurité, dont celui de toutes les versions < 1.8.2f)
242 * (sauf pour id_table, qui n'est pas numérique jusqu'à [5743])
[85675]243 * (id_base est une variable de la config des widgets de WordPress)
[1808]244 */
245foreach ($_GET as $var => $val)
[95895]246        if ($_GET[$var] and strncmp($var, "id_", 3) == 0
247        and !in_array($var, array('id_table', 'id_base')))
248                $_GET[$var] = is_array($_GET[$var])?@array_map('intval', $_GET[$var]):intval($_GET[$var]);
[1808]249foreach ($_POST as $var => $val)
[95895]250        if ($_POST[$var] and strncmp($var, "id_", 3) == 0
251        and !in_array($var, array('id_table', 'id_base')))
252                $_POST[$var] = is_array($_POST[$var])?@array_map('intval', $_POST[$var]):intval($_POST[$var]);
[1808]253foreach ($GLOBALS as $var => $val)
[95895]254        if ($GLOBALS[$var] and strncmp($var, "id_", 3) == 0
255        and !in_array($var, array('id_table', 'id_base')))
256                $GLOBALS[$var] = is_array($GLOBALS[$var])?@array_map('intval', $GLOBALS[$var]):intval($GLOBALS[$var]);
[1808]257
[63229]258/*
[95967]259 * Interdit la variable $cjpeg_command, qui était utilisée sans
260 * précaution dans certaines versions de dev (1.8b2 -> 1.8b5)
[1808]261 */
[95895]262$cjpeg_command = '';
[1808]263
[63229]264/*
[95967]265 * Contrôle de quelques variables (XSS)
[1815]266 */
[103161]267foreach(array('lang', 'var_recherche', 'aide', 'var_lang_r', 'lang_r', 'var_ajax_ancre', 'nom_fichier') as $var) {
[44288]268        if (isset($_GET[$var]))
[95895]269                $_REQUEST[$var] = $GLOBALS[$var] = $_GET[$var] = preg_replace(',[^\w\,/#&;-]+,', ' ', (string)$_GET[$var]);
[44288]270        if (isset($_POST[$var]))
[95895]271                $_REQUEST[$var] = $GLOBALS[$var] = $_POST[$var] = preg_replace(',[^\w\,/#&;-]+,', ' ', (string)$_POST[$var]);
[43835]272}
[1808]273
[63229]274/*
[95967]275 * Filtre l'accès à spip_acces_doc (injection SQL en 1.8.2x)
[1909]276 */
[44288]277if (preg_match(',^(.*/)?spip_acces_doc\.,', (string)$_SERVER['REQUEST_URI'])) {
[43353]278        $file = addslashes((string)$_GET['file']);
[1909]279}
280
[25372]281/*
[72990]282 * Pas d'inscription abusive
283 */
[95895]284if (isset($_REQUEST['mode']) and isset($_REQUEST['page'])
285and !in_array($_REQUEST['mode'], array("6forum", "1comite"))
286and $_REQUEST['page'] == "identifiants")
[72990]287        $ecran_securite_raison = "identifiants";
288
289/*
[95967]290 * Agenda joue à l'injection php
[25372]291 */
292if (isset($_REQUEST['partie_cal'])
[95895]293and $_REQUEST['partie_cal'] !== htmlentities((string)$_REQUEST['partie_cal']))
[30706]294        $ecran_securite_raison = "partie_cal";
[25372]295if (isset($_REQUEST['echelle'])
[95895]296and $_REQUEST['echelle'] !== htmlentities((string)$_REQUEST['echelle']))
[30706]297        $ecran_securite_raison = "echelle";
[25372]298
[43300]299/*
[95967]300 * Espace privé
[43300]301 */
302if (isset($_REQUEST['exec'])
[95895]303and !preg_match(',^[\w-]+$,', (string)$_REQUEST['exec']))
[43300]304        $ecran_securite_raison = "exec";
305if (isset($_REQUEST['cherche_auteur'])
[95895]306and preg_match(',[<],', (string)$_REQUEST['cherche_auteur']))
[43300]307        $ecran_securite_raison = "cherche_auteur";
[60446]308if (isset($_REQUEST['exec'])
[95895]309and $_REQUEST['exec'] == 'auteurs'
310and preg_match(',[<],', (string)$_REQUEST['recherche']))
[60446]311        $ecran_securite_raison = "recherche";
[100783]312if (isset($_REQUEST['exec'])
313and $_REQUEST['exec'] == 'info_plugin'
314and preg_match(',[<],', (string)$_REQUEST['plugin']))
315        $ecran_securite_raison = "plugin";
316if (isset($_REQUEST['exec'])
317and $_REQUEST['exec'] == 'puce_statut'
[101069]318and isset($_REQUEST['id'])
[100783]319and !intval($_REQUEST['id']))
320        $ecran_securite_raison = "puce_statut";
[43300]321if (isset($_REQUEST['action'])
[95895]322and $_REQUEST['action'] == 'configurer') {
[43300]323        if (@file_exists('inc_version.php')
[95895]324        or @file_exists('ecrire/inc_version.php')) {
[43300]325                function action_configurer() {
326                        include_spip('inc/autoriser');
327                        if(!autoriser('configurer', _request('configuration'))) {
328                                include_spip('inc/minipres');
329                                echo minipres(_T('info_acces_interdit'));
330                                exit;
331                        }
332                        require _DIR_RESTREINT.'action/configurer.php';
333                        action_configurer_dist();
334                }
335        }
336}
337
[63229]338/*
[95967]339 * Bloque les requêtes contenant %00 (manipulation d'include)
[1909]340 */
[1910]341if (strpos(
[1984]342        @get_magic_quotes_gpc() ?
343                stripslashes(serialize($_REQUEST)) : serialize($_REQUEST),
344        chr(0)
[30706]345) !== false)
346        $ecran_securite_raison = "%00";
[1909]347
[63229]348/*
[95967]349 * Bloque les requêtes fond=formulaire_
[1984]350 */
351if (isset($_REQUEST['fond'])
[95895]352and preg_match(',^formulaire_,i', $_REQUEST['fond']))
[30706]353        $ecran_securite_raison = "fond=formulaire_";
[1984]354
[63229]355/*
[95967]356 * Bloque les requêtes du type ?GLOBALS[type_urls]=toto (bug vieux php)
[1909]357 */
[30706]358if (isset($_REQUEST['GLOBALS']))
359        $ecran_securite_raison = "GLOBALS[GLOBALS]";
[1909]360
[63229]361/*
[95967]362 * Bloque les requêtes des bots sur:
[63229]363 * les agenda
[95967]364 * les paginations entremélées
[27744]365 */
[95895]366if (_IS_BOT and (
367        (isset($_REQUEST['echelle']) and isset($_REQUEST['partie_cal']) and isset($_REQUEST['type']))
368        or (strpos((string)$_SERVER['REQUEST_URI'], 'debut_') and preg_match(',[?&]debut_.*&debut_,', (string)$_SERVER['REQUEST_URI']))
[27801]369)
[30706]370)
371        $ecran_securite_raison = "robot agenda/double pagination";
[27879]372
373/*
374 * Bloque une vieille page de tests de CFG (<1.11)
[43303]375 * Bloque un XSS sur une page inexistante
[27879]376 */
[43303]377if (isset($_REQUEST['page'])) {
[95895]378        if ($_REQUEST['page'] == 'test_cfg')
[43303]379                $ecran_securite_raison = "test_cfg";
[43353]380        if ($_REQUEST['page'] !== htmlspecialchars((string)$_REQUEST['page']))
[43303]381                $ecran_securite_raison = "xsspage";
[45847]382        if ($_REQUEST['page'] == '404'
[95895]383        and isset($_REQUEST['erreur']))
[45847]384                $ecran_securite_raison = "xss404";
[43303]385}
[27938]386
[39437]387/*
388 * XSS par array
389 */
[44288]390foreach (array('var_login') as $var)
[95895]391if (isset($_REQUEST[$var]) and is_array($_REQUEST[$var]))
[44288]392        $ecran_securite_raison = "xss ".$var;
[30706]393
[63229]394/*
395 * Parade antivirale contre un cheval de troie
396 */
397if (!function_exists('tmp_lkojfghx')) {
398        function tmp_lkojfghx() {}
[95895]399        function tmp_lkojfghx2($a = 0, $b = 0, $c = 0, $d = 0) {
[95967]400                // si jamais on est arrivé ici sur une erreur php
401                // et qu'un autre gestionnaire d'erreur est défini, l'appeller
[95895]402                if ($b && $GLOBALS['tmp_xhgfjokl'])
403                        call_user_func($GLOBALS['tmp_xhgfjokl'], $a, $b, $c, $d);
[63229]404        }
[27938]405}
[30706]406if (isset($_POST['tmp_lkojfghx3']))
407        $ecran_securite_raison = "gumblar";
[30260]408
[30587]409/*
[95967]410 * Outils XML mal sécurisés < 2.0.9
[30587]411 */
412if (isset($_REQUEST['transformer_xml']))
[30706]413        $ecran_securite_raison = "transformer_xml";
[30260]414
415/*
[99658]416 * Outils XML mal sécurisés again
417 */
418if (isset($_REQUEST['var_url']) and $_REQUEST['var_url'] and isset($_REQUEST['exec']) and $_REQUEST['exec']=='valider_xml'){
419        $url = trim($_REQUEST['var_url']);
420        if (strncmp($url,'/',1)==0
[99748]421          or (($p=strpos($url,'..'))!==false AND strpos($url,'..',$p+3)!==false)
[109554]422          or (($p=strpos($url,'..'))!==false AND strpos($url,'IMG',$p+3)!==false)
[99658]423                or (strpos($url,'://')!==false or strpos($url,':\\')!==false)) {
424                $ecran_securite_raison = 'URL interdite pour var_url';
425        }
426}
427
428/*
[95967]429 * Sauvegarde mal securisée < 2.0.9
[30587]430 */
431if (isset($_REQUEST['nom_sauvegarde'])
[95895]432and strstr((string)$_REQUEST['nom_sauvegarde'], '/'))
[30706]433        $ecran_securite_raison = 'nom_sauvegarde manipulee';
[30587]434if (isset($_REQUEST['znom_sauvegarde'])
[95895]435and strstr((string)$_REQUEST['znom_sauvegarde'], '/'))
[30706]436        $ecran_securite_raison = 'znom_sauvegarde manipulee';
[30587]437
[30706]438
[43532]439/*
[43829]440 * op permet des inclusions arbitraires ;
[95967]441 * on vérifie 'page' pour ne pas bloquer ... drupal
[43532]442 */
[95895]443if (isset($_REQUEST['op']) and isset($_REQUEST['page'])
444and $_REQUEST['op'] !== preg_replace('/[^\-\w]/', '', $_REQUEST['op']))
[43829]445        $ecran_securite_raison = 'op';
[30706]446
[63229]447/*
[95967]448 * Forms & Table ne se méfiait pas assez des uploads de fichiers
[63229]449 */
[46118]450if (count($_FILES)){
[95895]451        foreach($_FILES as $k => $v){
452                 if (preg_match(',^fichier_\d+$,', $k)
453                 and preg_match(',\.php,i', $v['name']))
[46118]454                        unset($_FILES[$k]);
455        }
456}
[86403]457/*
458 * et Contact trop laxiste avec une variable externe
459 * on bloque pas le post pour eviter de perdre des donnees mais on unset la variable et c'est tout
460 */
[95895]461if (isset($_REQUEST['pj_enregistrees_nom']) and $_REQUEST['pj_enregistrees_nom']){
[86403]462        unset($_REQUEST['pj_enregistrees_nom']);
463        unset($_GET['pj_enregistrees_nom']);
464        unset($_POST['pj_enregistrees_nom']);
465}
[46118]466
[63229]467/*
468 * reinstall=oui un peu trop permissif
469 */
[46421]470if (isset($_REQUEST['reinstall'])
[95895]471and $_REQUEST['reinstall'] == 'oui')
[46421]472        $ecran_securite_raison = 'reinstall=oui';
[46118]473
[63229]474/*
[95967]475 * Échappement xss referer
[63229]476 */
[60729]477if (isset($_SERVER['HTTP_REFERER']))
478        $_SERVER['HTTP_REFERER'] = strtr($_SERVER['HTTP_REFERER'], '<>"\'', '[]##');
[46421]479
[104833]480
[63229]481/*
[104833]482 * Echappement HTTP_X_FORWARDED_HOST
483 */
484if (isset($_SERVER['HTTP_X_FORWARDED_HOST']))
485        $_SERVER['HTTP_X_FORWARDED_HOST'] = strtr($_SERVER['HTTP_X_FORWARDED_HOST'], "<>?\"\{\}\$'` \r\n", '____________');
486
487
488/*
[95967]489 * Réinjection des clés en html dans l'admin r19561
[63229]490 */
[95895]491if (strpos($_SERVER['REQUEST_URI'], "ecrire/") !== false){
492        $zzzz = implode("", array_keys($_REQUEST));
493        if (strlen($zzzz) != strcspn($zzzz, '<>"\''))
[62430]494                $ecran_securite_raison = 'Cle incorrecte en $_REQUEST';
495}
496
[30587]497/*
[63229]498 * Injection par connect
499 */
500if (isset($_REQUEST['connect'])
[95895]501        and
[63229]502        // cas qui permettent de sortir d'un commentaire PHP
[95895]503        (strpos($_REQUEST['connect'], "?") !== false
504         or strpos($_REQUEST['connect'], "<") !== false
505         or strpos($_REQUEST['connect'], ">") !== false
506         or strpos($_REQUEST['connect'], "\n") !== false
507         or strpos($_REQUEST['connect'], "\r") !== false)
[63229]508        ) {
[81334]509        $ecran_securite_raison = "malformed connect argument";
[63229]510}
511
512/*
[30706]513 * S'il y a une raison de mourir, mourons
514 */
515if (isset($ecran_securite_raison)) {
516        header("HTTP/1.0 403 Forbidden");
[32166]517        header("Expires: Wed, 11 Jan 1984 05:00:00 GMT");
[30706]518        header("Cache-Control: no-cache, must-revalidate");
519        header("Pragma: no-cache");
520        header("Content-Type: text/html");
[31174]521        die("<html><title>Error 403: Forbidden</title><body><h1>Error 403</h1><p>You are not authorized to view this page ($ecran_securite_raison)</p></body></html>");
[30706]522}
[63229]523
[30706]524/*
[95895]525 * Un filtre filtrer_entites securise
[30706]526 */
[95895]527if (!function_exists('filtre_filtrer_entites_dist')) {
528        function filtre_filtrer_entites_dist($t) {
529                include_spip('inc/texte');
530                return interdire_scripts(filtrer_entites($t));
531        }
532}
[30706]533
534
[95895]535/*
[95967]536 * Fin sécurité
[95895]537 */
[30706]538
[95895]539
540
[30706]541/*
[95967]542 * Bloque les bots quand le load déborde
[30260]543 */
[30587]544if (!defined('_ECRAN_SECURITE_LOAD'))
545        define('_ECRAN_SECURITE_LOAD', 4);
546
[30260]547if (
[30706]548        defined('_ECRAN_SECURITE_LOAD')
[95895]549        and _ECRAN_SECURITE_LOAD > 0
550        and _IS_BOT
[104721]551        and !_IS_BOT_FRIEND
[95895]552        and $_SERVER['REQUEST_METHOD'] === 'GET'
553        and (
[66462]554                (function_exists('sys_getloadavg')
[95895]555                  and $load = sys_getloadavg()
556                  and is_array($load)
557                  and $load = array_shift($load)
[66462]558                )
[95895]559                or
[66462]560                (@is_readable('/proc/loadavg')
[95895]561                  and $load = file_get_contents('/proc/loadavg')
562                  and $load = floatval($load)
[66462]563                )
[30706]564        )
[95895]565        and $load > _ECRAN_SECURITE_LOAD // eviter l'evaluation suivante si de toute facon le load est inferieur a la limite
566        and rand(0, $load * $load) > _ECRAN_SECURITE_LOAD * _ECRAN_SECURITE_LOAD
[30706]567) {
[30260]568        header("HTTP/1.0 503 Service Unavailable");
569        header("Retry-After: 300");
[32166]570        header("Expires: Wed, 11 Jan 1984 05:00:00 GMT");
[30260]571        header("Cache-Control: no-cache, must-revalidate");
572        header("Pragma: no-cache");
573        header("Content-Type: text/html");
[31174]574        die("<html><title>Status 503: Site temporarily unavailable</title><body><h1>Status 503</h1><p>Site temporarily unavailable (load average $load)</p></body></html>");
[30260]575}
Note: See TracBrowser for help on using the repository browser.