From 6c1650713fc948318852ace759aab8f1a84791cf Mon Sep 17 00:00:00 2001 From: Cerdic <cedric@yterium.com> Date: Tue, 19 May 2020 17:48:56 +0200 Subject: [PATCH] Divers petites sanitization et une balise manquante #4494 --- ecrire/inc/filtres.php | 11 +++++++++ ecrire/inc/precharger_objet.php | 8 +++---- ecrire/inc/utils.php | 37 +++++++++++++++++++++++++++++++ ecrire/public/aiguiller.php | 7 ++++++ ecrire/public/balises.php | 13 +++++++++++ ecrire/public/criteres.php | 4 ++-- prive/formulaires/editer_logo.php | 1 + prive/squelettes/structure.html | 1 + 8 files changed, 76 insertions(+), 6 deletions(-) diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php index 8a7b0de59e..4957ec7e40 100644 --- a/ecrire/inc/filtres.php +++ b/ecrire/inc/filtres.php @@ -403,6 +403,17 @@ function filtre_setenv(&$Pile, $val, $key, $continue = null) { return $continue ? $val : ''; } +/** + * @param array $Pile + * @param array|string $keys + * @return string + */ +function filtre_sanitize_env(&$Pile, $keys) { + $Pile[0] = spip_sanitize_from_request($Pile[0], $keys); + return ''; +} + + /** * Filtre `debug` qui affiche un debug de la valeur en entrée * diff --git a/ecrire/inc/precharger_objet.php b/ecrire/inc/precharger_objet.php index d11a381ebf..f607d38fd6 100644 --- a/ecrire/inc/precharger_objet.php +++ b/ecrire/inc/precharger_objet.php @@ -50,7 +50,7 @@ function precharger_objet($type, $id_objet, $id_rubrique = 0, $lier_trad = 0, $c // si l'objet existe deja, on retourne simplement ses valeurs if (is_numeric($id_objet)) { - return sql_fetsel("*", $table, "$_id_objet=$id_objet"); + return sql_fetsel("*", $table, "$_id_objet=".intval($id_objet)); } // ici, on demande une creation. @@ -133,7 +133,7 @@ function precharger_traduction_objet($type, $id_objet, $id_rubrique = 0, $lier_t $_id_objet = id_table_objet($table); // Recuperer les donnees de l'objet original - $row = sql_fetsel("*", $table, "$_id_objet=$lier_trad"); + $row = sql_fetsel("*", $table, "$_id_objet=".intval($lier_trad)); if ($row) { include_spip('inc/filtres'); $row[$champ_titre] = filtrer_entites(objet_T($type, 'info_nouvelle_traduction')) . ' ' . $row[$champ_titre]; @@ -172,12 +172,12 @@ function precharger_traduction_objet($type, $id_objet, $id_rubrique = 0, $lier_t $id_parent = 0; } else { // on cherche une rubrique soeur dans la bonne langue - $row_rub = sql_fetsel("id_parent", "spip_rubriques", "id_rubrique=$id_rubrique"); + $row_rub = sql_fetsel("id_parent", "spip_rubriques", "id_rubrique=".intval($id_rubrique)); $id_parent = $row_rub['id_parent']; } $row_rub = sql_fetsel("id_rubrique", "spip_rubriques", - "lang='" . $GLOBALS['spip_lang'] . "' AND id_parent=$id_parent"); + "lang='" . $GLOBALS['spip_lang'] . "' AND id_parent=".intval($id_parent)); if ($row_rub) { $row['id_rubrique'] = $row_rub['id_rubrique']; } diff --git a/ecrire/inc/utils.php b/ecrire/inc/utils.php index a61217fb4b..74e155d012 100644 --- a/ecrire/inc/utils.php +++ b/ecrire/inc/utils.php @@ -446,6 +446,43 @@ function set_request($var, $val = null, $c = false) { return false; # n'affecte pas $c } +/** + * Sanitizer une valeur *SI* elle provient du GET ou POST + * Utile dans les squelettes pour les valeurs qu'on attrape dans le env, + * dont on veut permettre à un squelette de confiance appelant de fournir une valeur complexe + * mais qui doit etre nettoyee si elle provient de l'URL + * + * On peut sanitizer + * - une valeur simple : `$where = spip_sanitize_from_request($value, 'where')` + * - un tableau en partie : `$env = spip_sanitize_from_request($env, ['key1','key2'])` + * - un tableau complet : `$env = spip_sanitize_from_request($env, '*')` + * + * @param string|array $value + * @param string|array $key + * @param string $sanitize_function + * @return array|mixed|string + */ +function spip_sanitize_from_request($value, $key, $sanitize_function='entites_html') { + if (is_array($value)) { + if ($key=='*') { + $key = array_keys($value); + } + if (!is_array($key)) { + $key = [$key]; + } + foreach ($key as $k) { + if (!empty($value[$k])) { + $value[$k] = spip_sanitize_from_request($value[$k], $k, $sanitize_function); + } + } + return $value; + } + // si la valeur vient des GET ou POST on la sanitize + if (!empty($value) and $value == _request($key)) { + $value = $sanitize_function($value); + } + return $value; +} /** * Tester si une URL est absolue diff --git a/ecrire/public/aiguiller.php b/ecrire/public/aiguiller.php index 0500e2d67d..44629a19ee 100644 --- a/ecrire/public/aiguiller.php +++ b/ecrire/public/aiguiller.php @@ -15,6 +15,13 @@ if (!defined('_ECRIRE_INC_VERSION')) { } function securiser_redirect_action($redirect) { + // cas d'un double urlencode : si un urldecode de l'url n'est pas secure, on retient ca comme redirect + if (strpos($redirect, '%') !== false) { + $r2 = urldecode($redirect); + if (($r3 = securiser_redirect_action($r2)) !== $r2) { + return $r3; + } + } if ((tester_url_absolue($redirect) or preg_match(',^\w+:,',trim($redirect))) and !defined('_AUTORISER_ACTION_ABS_REDIRECT')) { // si l'url est une url du site, on la laisse passer sans rien faire diff --git a/ecrire/public/balises.php b/ecrire/public/balises.php index 699bd50e11..08f18935b8 100644 --- a/ecrire/public/balises.php +++ b/ecrire/public/balises.php @@ -1691,6 +1691,19 @@ function balise_REM_dist($p) { return $p; } +/** + * Une balise #NULL quand on a besoin de passer un argument null sur l'appel d'un filtre ou formulaire + * (evite un #EVAL{null}) + * @param $p + * @return mixed + */ +function balise_NULL_dist($p) { + $p->code = "null"; + $p->interdire_scripts = false; + + return $p; +} + /** * Compile la balise `#HTTP_HEADER` envoyant des entêtes de retour HTTP diff --git a/ecrire/public/criteres.php b/ecrire/public/criteres.php index e948ab4efb..bed609c0dc 100644 --- a/ecrire/public/criteres.php +++ b/ecrire/public/criteres.php @@ -1557,11 +1557,11 @@ function critere_where_dist($idb, &$boucles, $crit) { if (isset($crit->param[0])) { $_where = calculer_liste($crit->param[0], $idb, $boucles, $boucle->id_parent); } else { - $_where = '@$Pile[0]["where"]'; + $_where = 'spip_sanitize_from_request(@$Pile[0]["where"],"where","vide")'; } if ($crit->cond) { - $_where = "(($_where) ? ($_where) : '')"; + $_where = "((\$zzw = $_where) ? \$zzw : '')"; } if ($crit->not) { diff --git a/prive/formulaires/editer_logo.php b/prive/formulaires/editer_logo.php index 21e8577f3a..5e5267cfe6 100644 --- a/prive/formulaires/editer_logo.php +++ b/prive/formulaires/editer_logo.php @@ -61,6 +61,7 @@ function formulaires_editer_logo_charger_dist($objet, $id_objet, $retour = '', $ if (!is_array($options)) { $options = unserialize($options); } + $options = spip_sanitize_from_request($options, '*'); if (!isset($options['titre'])) { $balise_img = chercher_filtre('balise_img'); diff --git a/prive/squelettes/structure.html b/prive/squelettes/structure.html index 5d721cac80..8fafccc0e9 100644 --- a/prive/squelettes/structure.html +++ b/prive/squelettes/structure.html @@ -5,5 +5,6 @@ <head> <INCLURE{fond=prive/squelettes/head/#ENV{type-page},env,espace_prive=1}> </head> +[(#LISTE{titre,sinon}|sanitize_env)] <INCLURE{fond=prive/squelettes/body,env,espace_prive=1}> </html> -- GitLab