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

Last change on this file was 113872, checked in by cedric@…, 6 weeks ago

Retour a une liste complete de bots telle qu'elle etait sur la version non incremente de la zone, et on incremente

File size: 14.7 KB
RevLine 
[1808]1<?php
2
3/*
4 * ecran_securite.php
5 * ------------------
[30260]6 */
7
[113872]8define('_ECRAN_SECURITE', '1.3.10'); // 2019-02-12
[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',
[113872]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',
[113872]55                        'acrylicapps',
[112247]56                        'addthis',
57                        'adressendeutschland',
58                        'alexa',
59                        'altavista',
60                        'analyticsseo',
[113872]61                        'antennapod',
62                        'arachnys',
[112247]63                        'archive',
[113872]64                        'argclrint',
[112247]65                        'aspseek',
66                        'baidu',
67                        'begunadvertising',
[113872]68                        'bing',
[112247]69                        'bloglines',
[113872]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',
[113872]82                        'dlvr\.it',
[112247]83                        'dlweb',
[113872]84                        'drupal',
[112247]85                        'ec2linkfinder',
[113872]86                        'eset\.com',
[112247]87                        'estyle',
[113872]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',
[113872]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',
[113872]111                        'inoreader',
[112247]112                        'infegyatlas',
113                        'infohelfer',
114                        'instapaper',
115                        'jabse',
116                        'james',
[113872]117                        'jersey',
[112247]118                        'kumkie',
119                        'linkdex',
120                        'linkfluence',
121                        'linkwalker',
122                        'litefinder',
123                        'loadimpactpageanalyzer',
[113872]124                        'ltx71',
[112247]125                        'luminate',
126                        'lycos',
127                        'lycosa',
128                        'mediapartners-google',
129                        'msai',
[113872]130                        'myapp',
131                        'nativehost',
[112247]132                        'najdi',
133                        'netcraftsurveyagent',
134                        'netestate',
135                        'netseer',
[113872]136                        'netnewswire',
137                        'newspaper',
138                        'newsblur',
[112247]139                        'nuhk',
[113872]140                        'nuzzel',
141                        'okhttp',
142                        'otmedia',
[112248]143                        'owlin',
[113872]144                        'owncloud',
[112247]145                        'panscient',
[113872]146                        'paper\.li',
[112247]147                        'parsijoo',
[113872]148                        'protopage',
[112247]149                        'plukkie',
150                        'proximic',
[113872]151                        'pubsub',
152                        'python',
[112247]153                        'qirina',
[113872]154                        'qoshe',
[112247]155                        'qualidator',
[113872]156                        'qwantify',
[112247]157                        'rambler',
158                        'readability',
[113872]159                        'ruby',
[112247]160                        'sbsearch',
[113872]161                        'scoop\.it',
[112247]162                        'scooter',
[113872]163                        'scoutjet',
[112247]164                        'scrapy',
165                        'scrubby',
166                        'scrubbybloglines',
167                        'shareaholic',
168                        'shopwiki',
[113872]169                        'simplepie',
[112247]170                        'sistrix',
171                        'sitechecker',
172                        'siteexplorer',
[113872]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',
[113872]185                        'the knowledge AI',
[112247]186                        'thumbshots',
187                        'tineye',
[113872]188                        'traackr',
[112247]189                        'trendiction',
[113872]190                        'trendsmap',
[112247]191                        'tweetedtimes',
192                        'tweetmeme',
[113872]193                        'universalfeedparser',
[112247]194                        'uaslinkchecker',
195                        'undrip',
196                        'unwindfetchor',
[113872]197                        'upday',
[112247]198                        'vedma',
199                        'vkshare',
200                        'vm',
201                        'wch',
202                        'webalta',
203                        'webcookies',
[113872]204                        'webparser',
[112247]205                        'webthumbnail',
206                        'wesee',
207                        'wise-guys',
208                        'woko',
[113872]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',
[113872]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',
[113872]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 */
[113867]245$_exceptions = array('id_table','id_base','id_parent','id_article_pdf');
[1808]246foreach ($_GET as $var => $val)
[95895]247        if ($_GET[$var] and strncmp($var, "id_", 3) == 0
[113867]248                and !in_array($var, $_exceptions))
[95895]249                $_GET[$var] = is_array($_GET[$var])?@array_map('intval', $_GET[$var]):intval($_GET[$var]);
[1808]250foreach ($_POST as $var => $val)
[95895]251        if ($_POST[$var] and strncmp($var, "id_", 3) == 0
[113867]252                and !in_array($var, $_exceptions))
[95895]253                $_POST[$var] = is_array($_POST[$var])?@array_map('intval', $_POST[$var]):intval($_POST[$var]);
[1808]254foreach ($GLOBALS as $var => $val)
[95895]255        if ($GLOBALS[$var] and strncmp($var, "id_", 3) == 0
[113867]256                and !in_array($var, $_exceptions))
[95895]257                $GLOBALS[$var] = is_array($GLOBALS[$var])?@array_map('intval', $GLOBALS[$var]):intval($GLOBALS[$var]);
[1808]258
[63229]259/*
[95967]260 * Interdit la variable $cjpeg_command, qui était utilisée sans
261 * précaution dans certaines versions de dev (1.8b2 -> 1.8b5)
[1808]262 */
[95895]263$cjpeg_command = '';
[1808]264
[63229]265/*
[95967]266 * Contrôle de quelques variables (XSS)
[1815]267 */
[103161]268foreach(array('lang', 'var_recherche', 'aide', 'var_lang_r', 'lang_r', 'var_ajax_ancre', 'nom_fichier') as $var) {
[44288]269        if (isset($_GET[$var]))
[95895]270                $_REQUEST[$var] = $GLOBALS[$var] = $_GET[$var] = preg_replace(',[^\w\,/#&;-]+,', ' ', (string)$_GET[$var]);
[44288]271        if (isset($_POST[$var]))
[95895]272                $_REQUEST[$var] = $GLOBALS[$var] = $_POST[$var] = preg_replace(',[^\w\,/#&;-]+,', ' ', (string)$_POST[$var]);
[43835]273}
[1808]274
[63229]275/*
[95967]276 * Filtre l'accès à spip_acces_doc (injection SQL en 1.8.2x)
[1909]277 */
[44288]278if (preg_match(',^(.*/)?spip_acces_doc\.,', (string)$_SERVER['REQUEST_URI'])) {
[43353]279        $file = addslashes((string)$_GET['file']);
[1909]280}
281
[25372]282/*
[72990]283 * Pas d'inscription abusive
284 */
[95895]285if (isset($_REQUEST['mode']) and isset($_REQUEST['page'])
286and !in_array($_REQUEST['mode'], array("6forum", "1comite"))
287and $_REQUEST['page'] == "identifiants")
[72990]288        $ecran_securite_raison = "identifiants";
289
290/*
[95967]291 * Agenda joue à l'injection php
[25372]292 */
293if (isset($_REQUEST['partie_cal'])
[95895]294and $_REQUEST['partie_cal'] !== htmlentities((string)$_REQUEST['partie_cal']))
[30706]295        $ecran_securite_raison = "partie_cal";
[25372]296if (isset($_REQUEST['echelle'])
[95895]297and $_REQUEST['echelle'] !== htmlentities((string)$_REQUEST['echelle']))
[30706]298        $ecran_securite_raison = "echelle";
[25372]299
[43300]300/*
[95967]301 * Espace privé
[43300]302 */
303if (isset($_REQUEST['exec'])
[95895]304and !preg_match(',^[\w-]+$,', (string)$_REQUEST['exec']))
[43300]305        $ecran_securite_raison = "exec";
306if (isset($_REQUEST['cherche_auteur'])
[95895]307and preg_match(',[<],', (string)$_REQUEST['cherche_auteur']))
[43300]308        $ecran_securite_raison = "cherche_auteur";
[60446]309if (isset($_REQUEST['exec'])
[95895]310and $_REQUEST['exec'] == 'auteurs'
311and preg_match(',[<],', (string)$_REQUEST['recherche']))
[60446]312        $ecran_securite_raison = "recherche";
[100783]313if (isset($_REQUEST['exec'])
314and $_REQUEST['exec'] == 'info_plugin'
315and preg_match(',[<],', (string)$_REQUEST['plugin']))
316        $ecran_securite_raison = "plugin";
317if (isset($_REQUEST['exec'])
318and $_REQUEST['exec'] == 'puce_statut'
[101069]319and isset($_REQUEST['id'])
[100783]320and !intval($_REQUEST['id']))
321        $ecran_securite_raison = "puce_statut";
[43300]322if (isset($_REQUEST['action'])
[95895]323and $_REQUEST['action'] == 'configurer') {
[43300]324        if (@file_exists('inc_version.php')
[95895]325        or @file_exists('ecrire/inc_version.php')) {
[43300]326                function action_configurer() {
327                        include_spip('inc/autoriser');
328                        if(!autoriser('configurer', _request('configuration'))) {
329                                include_spip('inc/minipres');
330                                echo minipres(_T('info_acces_interdit'));
331                                exit;
332                        }
333                        require _DIR_RESTREINT.'action/configurer.php';
334                        action_configurer_dist();
335                }
336        }
337}
338
[63229]339/*
[95967]340 * Bloque les requêtes contenant %00 (manipulation d'include)
[1909]341 */
[1910]342if (strpos(
[1984]343        @get_magic_quotes_gpc() ?
344                stripslashes(serialize($_REQUEST)) : serialize($_REQUEST),
345        chr(0)
[30706]346) !== false)
347        $ecran_securite_raison = "%00";
[1909]348
[63229]349/*
[95967]350 * Bloque les requêtes fond=formulaire_
[1984]351 */
352if (isset($_REQUEST['fond'])
[95895]353and preg_match(',^formulaire_,i', $_REQUEST['fond']))
[30706]354        $ecran_securite_raison = "fond=formulaire_";
[1984]355
[63229]356/*
[95967]357 * Bloque les requêtes du type ?GLOBALS[type_urls]=toto (bug vieux php)
[1909]358 */
[30706]359if (isset($_REQUEST['GLOBALS']))
360        $ecran_securite_raison = "GLOBALS[GLOBALS]";
[1909]361
[63229]362/*
[95967]363 * Bloque les requêtes des bots sur:
[63229]364 * les agenda
[95967]365 * les paginations entremélées
[27744]366 */
[95895]367if (_IS_BOT and (
368        (isset($_REQUEST['echelle']) and isset($_REQUEST['partie_cal']) and isset($_REQUEST['type']))
369        or (strpos((string)$_SERVER['REQUEST_URI'], 'debut_') and preg_match(',[?&]debut_.*&debut_,', (string)$_SERVER['REQUEST_URI']))
[113867]370                or (isset($_REQUEST['calendrier_annee']) and strpos((string)$_SERVER['REQUEST_URI'], 'debut_') )
371                or (isset($_REQUEST['calendrier_annee']) and preg_match(',[?&]calendrier_annee=.*&calendrier_annee=,', (string)$_SERVER['REQUEST_URI']))
[27801]372)
[30706]373)
374        $ecran_securite_raison = "robot agenda/double pagination";
[27879]375
376/*
377 * Bloque une vieille page de tests de CFG (<1.11)
[43303]378 * Bloque un XSS sur une page inexistante
[27879]379 */
[43303]380if (isset($_REQUEST['page'])) {
[95895]381        if ($_REQUEST['page'] == 'test_cfg')
[43303]382                $ecran_securite_raison = "test_cfg";
[43353]383        if ($_REQUEST['page'] !== htmlspecialchars((string)$_REQUEST['page']))
[43303]384                $ecran_securite_raison = "xsspage";
[45847]385        if ($_REQUEST['page'] == '404'
[95895]386        and isset($_REQUEST['erreur']))
[45847]387                $ecran_securite_raison = "xss404";
[43303]388}
[27938]389
[39437]390/*
391 * XSS par array
392 */
[44288]393foreach (array('var_login') as $var)
[95895]394if (isset($_REQUEST[$var]) and is_array($_REQUEST[$var]))
[44288]395        $ecran_securite_raison = "xss ".$var;
[30706]396
[63229]397/*
398 * Parade antivirale contre un cheval de troie
399 */
400if (!function_exists('tmp_lkojfghx')) {
401        function tmp_lkojfghx() {}
[95895]402        function tmp_lkojfghx2($a = 0, $b = 0, $c = 0, $d = 0) {
[95967]403                // si jamais on est arrivé ici sur une erreur php
404                // et qu'un autre gestionnaire d'erreur est défini, l'appeller
[95895]405                if ($b && $GLOBALS['tmp_xhgfjokl'])
406                        call_user_func($GLOBALS['tmp_xhgfjokl'], $a, $b, $c, $d);
[63229]407        }
[27938]408}
[30706]409if (isset($_POST['tmp_lkojfghx3']))
410        $ecran_securite_raison = "gumblar";
[30260]411
[30587]412/*
[95967]413 * Outils XML mal sécurisés < 2.0.9
[30587]414 */
415if (isset($_REQUEST['transformer_xml']))
[30706]416        $ecran_securite_raison = "transformer_xml";
[30260]417
418/*
[99658]419 * Outils XML mal sécurisés again
420 */
421if (isset($_REQUEST['var_url']) and $_REQUEST['var_url'] and isset($_REQUEST['exec']) and $_REQUEST['exec']=='valider_xml'){
422        $url = trim($_REQUEST['var_url']);
423        if (strncmp($url,'/',1)==0
[99748]424          or (($p=strpos($url,'..'))!==false AND strpos($url,'..',$p+3)!==false)
[109554]425          or (($p=strpos($url,'..'))!==false AND strpos($url,'IMG',$p+3)!==false)
[99658]426                or (strpos($url,'://')!==false or strpos($url,':\\')!==false)) {
427                $ecran_securite_raison = 'URL interdite pour var_url';
428        }
429}
430
431/*
[95967]432 * Sauvegarde mal securisée < 2.0.9
[30587]433 */
434if (isset($_REQUEST['nom_sauvegarde'])
[95895]435and strstr((string)$_REQUEST['nom_sauvegarde'], '/'))
[30706]436        $ecran_securite_raison = 'nom_sauvegarde manipulee';
[30587]437if (isset($_REQUEST['znom_sauvegarde'])
[95895]438and strstr((string)$_REQUEST['znom_sauvegarde'], '/'))
[30706]439        $ecran_securite_raison = 'znom_sauvegarde manipulee';
[30587]440
[30706]441
[43532]442/*
[43829]443 * op permet des inclusions arbitraires ;
[95967]444 * on vérifie 'page' pour ne pas bloquer ... drupal
[43532]445 */
[95895]446if (isset($_REQUEST['op']) and isset($_REQUEST['page'])
447and $_REQUEST['op'] !== preg_replace('/[^\-\w]/', '', $_REQUEST['op']))
[43829]448        $ecran_securite_raison = 'op';
[30706]449
[63229]450/*
[95967]451 * Forms & Table ne se méfiait pas assez des uploads de fichiers
[63229]452 */
[46118]453if (count($_FILES)){
[95895]454        foreach($_FILES as $k => $v){
455                 if (preg_match(',^fichier_\d+$,', $k)
456                 and preg_match(',\.php,i', $v['name']))
[46118]457                        unset($_FILES[$k]);
458        }
459}
[86403]460/*
461 * et Contact trop laxiste avec une variable externe
462 * on bloque pas le post pour eviter de perdre des donnees mais on unset la variable et c'est tout
463 */
[95895]464if (isset($_REQUEST['pj_enregistrees_nom']) and $_REQUEST['pj_enregistrees_nom']){
[86403]465        unset($_REQUEST['pj_enregistrees_nom']);
466        unset($_GET['pj_enregistrees_nom']);
467        unset($_POST['pj_enregistrees_nom']);
468}
[46118]469
[63229]470/*
471 * reinstall=oui un peu trop permissif
472 */
[46421]473if (isset($_REQUEST['reinstall'])
[95895]474and $_REQUEST['reinstall'] == 'oui')
[46421]475        $ecran_securite_raison = 'reinstall=oui';
[46118]476
[63229]477/*
[95967]478 * Échappement xss referer
[63229]479 */
[60729]480if (isset($_SERVER['HTTP_REFERER']))
481        $_SERVER['HTTP_REFERER'] = strtr($_SERVER['HTTP_REFERER'], '<>"\'', '[]##');
[46421]482
[104833]483
[63229]484/*
[104833]485 * Echappement HTTP_X_FORWARDED_HOST
486 */
487if (isset($_SERVER['HTTP_X_FORWARDED_HOST']))
488        $_SERVER['HTTP_X_FORWARDED_HOST'] = strtr($_SERVER['HTTP_X_FORWARDED_HOST'], "<>?\"\{\}\$'` \r\n", '____________');
489
490
491/*
[95967]492 * Réinjection des clés en html dans l'admin r19561
[63229]493 */
[95895]494if (strpos($_SERVER['REQUEST_URI'], "ecrire/") !== false){
495        $zzzz = implode("", array_keys($_REQUEST));
496        if (strlen($zzzz) != strcspn($zzzz, '<>"\''))
[62430]497                $ecran_securite_raison = 'Cle incorrecte en $_REQUEST';
498}
499
[30587]500/*
[63229]501 * Injection par connect
502 */
503if (isset($_REQUEST['connect'])
[95895]504        and
[63229]505        // cas qui permettent de sortir d'un commentaire PHP
[95895]506        (strpos($_REQUEST['connect'], "?") !== false
507         or strpos($_REQUEST['connect'], "<") !== false
508         or strpos($_REQUEST['connect'], ">") !== false
509         or strpos($_REQUEST['connect'], "\n") !== false
510         or strpos($_REQUEST['connect'], "\r") !== false)
[63229]511        ) {
[81334]512        $ecran_securite_raison = "malformed connect argument";
[63229]513}
514
515/*
[30706]516 * S'il y a une raison de mourir, mourons
517 */
518if (isset($ecran_securite_raison)) {
519        header("HTTP/1.0 403 Forbidden");
[32166]520        header("Expires: Wed, 11 Jan 1984 05:00:00 GMT");
[30706]521        header("Cache-Control: no-cache, must-revalidate");
522        header("Pragma: no-cache");
523        header("Content-Type: text/html");
[31174]524        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]525}
[63229]526
[30706]527/*
[95895]528 * Un filtre filtrer_entites securise
[30706]529 */
[95895]530if (!function_exists('filtre_filtrer_entites_dist')) {
531        function filtre_filtrer_entites_dist($t) {
532                include_spip('inc/texte');
533                return interdire_scripts(filtrer_entites($t));
534        }
535}
[30706]536
537
[95895]538/*
[95967]539 * Fin sécurité
[95895]540 */
[30706]541
[95895]542
543
[30706]544/*
[95967]545 * Bloque les bots quand le load déborde
[30260]546 */
[30587]547if (!defined('_ECRAN_SECURITE_LOAD'))
548        define('_ECRAN_SECURITE_LOAD', 4);
549
[30260]550if (
[30706]551        defined('_ECRAN_SECURITE_LOAD')
[95895]552        and _ECRAN_SECURITE_LOAD > 0
553        and _IS_BOT
[104721]554        and !_IS_BOT_FRIEND
[95895]555        and $_SERVER['REQUEST_METHOD'] === 'GET'
556        and (
[66462]557                (function_exists('sys_getloadavg')
[95895]558                  and $load = sys_getloadavg()
559                  and is_array($load)
560                  and $load = array_shift($load)
[66462]561                )
[95895]562                or
[66462]563                (@is_readable('/proc/loadavg')
[95895]564                  and $load = file_get_contents('/proc/loadavg')
565                  and $load = floatval($load)
[66462]566                )
[30706]567        )
[95895]568        and $load > _ECRAN_SECURITE_LOAD // eviter l'evaluation suivante si de toute facon le load est inferieur a la limite
569        and rand(0, $load * $load) > _ECRAN_SECURITE_LOAD * _ECRAN_SECURITE_LOAD
[30706]570) {
[113867]571        //https://webmasters.stackexchange.com/questions/65674/should-i-return-a-429-or-503-status-code-to-a-bot
572        header("HTTP/1.0 429 Too Many Requests");
[30260]573        header("Retry-After: 300");
[32166]574        header("Expires: Wed, 11 Jan 1984 05:00:00 GMT");
[30260]575        header("Cache-Control: no-cache, must-revalidate");
576        header("Pragma: no-cache");
577        header("Content-Type: text/html");
[113867]578        die("<html><title>Status 429: Too Many Requests</title><body><h1>Status 429</h1><p>Too Many Requests (try again soon)</p></body></html>");
[30260]579}
Note: See TracBrowser for help on using the repository browser.