Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plxUtils : refacto strCheck + nouvelle sanitizeHtml #739

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions core/lib/class.plx.admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,11 @@ public function editConfiguration($plxConfig, $content) {
# <!CDATA[..]]> est inutile : valeur numerique, champs uniquement avec caractères alphanumérique
$content = plxUtils::strCheck($v);
} elseif(in_array($k, array('description', 'feed_footer'))) {
# On tolère quelques balises par défaut : <i>, <em>, <a>, <sup>, <span>,
# <!CDATA[..]]> On tolère les balises HTML
$content = plxUtils::strCheck($v, true);
} else {
# Aucune balise HTML tolérée
$content = plxUtils::strCheck($v, true, null);
# <!CDATA[..]]> Aucune balise HTML tolérée
$content = plxUtils::strCheck($v, true, true);
}
?>
<parametre name="<?= $k ?>"><?= $content ?></parametre>
Expand Down Expand Up @@ -971,12 +971,12 @@ public function editCategories($content, $action=false) {
<categorie number="<?= $cat_id ?>" active="<?= $cat['active'] ?>" homepage="<?= $cat['homepage'] ?>" tri="<?= $cat['tri'] ?>" bypage="<?= $cat['bypage'] ?>" menu="<?= $cat['menu'] ?>" url="<?= $cat['url'] ?>" template="<?= basename($cat['template']) ?>">
<name><?= $cat['name'] ?></name>
<description><?= plxUtils::strCheck($cat['description'], true) ?></description>
<meta_description><?= plxUtils::strCheck($cat['meta_description'], true, null) ?></meta_description>
<meta_keywords><?= plxUtils::strCheck($cat['meta_keywords'], true, null) ?></meta_keywords>
<title_htmltag><?= plxUtils::strCheck($cat['title_htmltag'], true, null) ?></title_htmltag>
<thumbnail><?= plxUtils::strCheck($cat['thumbnail'], true, null) ?></thumbnail>
<thumbnail_alt><?= plxUtils::strCheck($cat['thumbnail_alt'], true) ?></thumbnail_alt>
<thumbnail_title><?= plxUtils::strCheck($cat['thumbnail_title'], true) ?></thumbnail_title>
<meta_description><?= plxUtils::strCheck($cat['meta_description']) ?></meta_description>
<meta_keywords><?= plxUtils::strCheck($cat['meta_keywords']) ?></meta_keywords>
<title_htmltag><?= plxUtils::strCheck($cat['title_htmltag']) ?></title_htmltag>
<thumbnail><?= plxUtils::strCheck($cat['thumbnail'], false, true) ?></thumbnail>
<thumbnail_alt><?= plxUtils::strCheck($cat['thumbnail_alt']) ?></thumbnail_alt>
<thumbnail_title><?= plxUtils::strCheck($cat['thumbnail_title']) ?></thumbnail_title>
<?php
# Hook plugins
eval($this->plxPlugins->callHook('plxAdminEditCategoriesXml'));
Expand Down Expand Up @@ -1112,7 +1112,7 @@ public function editStatiques($content, $action=false) {
<statique number="<?= $static_id ?>" active="<?= $static['active'] ?>" menu="<?= $static['menu'] ?>" url="<?= $static['url'] ?>" template="<?= basename($static['template']) ?>">
<group><?= plxUtils::strCheck($static['group']) ?></group>
<name><?= plxUtils::strCheck($static['name']) ?></name>
<meta_description><?= plxUtils::strCheck($static['meta_description'], true) ?></meta_description>
<meta_description><?= plxUtils::strCheck($static['meta_description']) ?></meta_description>
<meta_keywords><?= plxUtils::strCheck($static['meta_keywords']) ?></meta_keywords>
<title_htmltag><?= plxUtils::strCheck($static['title_htmltag']) ?></title_htmltag>
<date_creation><?= $static['date_creation'] ?></date_creation>
Expand Down Expand Up @@ -1291,15 +1291,15 @@ public function editArticle($content, &$id) {
<title><?= plxUtils::strCheck(trim($content['title']), true) ?></title>
<allow_com><?= intval($content['allow_com']) ?></allow_com>
<template><?= basename($content['template']) ?></template>
<chapo><![CDATA[<?= plxUtils::sanitizePhpTags(trim($content['chapo'])) ?>]]></chapo>
<content><![CDATA[<?= plxUtils::sanitizePhpTags(trim($content['content'])) ?>]]></content>
<tags><?= plxUtils::strCheck(trim($content['tags']), true) ?></tags>
<meta_description><?= plxUtils::strCheck(trim($meta_description)) ?></meta_description>
<meta_keywords><?= plxUtils::strCheck(trim($meta_keywords)) ?></meta_keywords>
<title_htmltag><?= plxUtils::strCheck(trim($title_htmltag)) ?></title_htmltag>
<thumbnail><?= plxUtils::strCheck(trim($thumbnail)) ?></thumbnail>
<thumbnail_alt><?= plxUtils::strCheck(trim($thumbnail_alt), true) ?></thumbnail_alt>
<thumbnail_title><?= plxUtils::strCheck(trim($thumbnail_title), true) ?></thumbnail_title>
<chapo><?= plxUtils::strCheck(trim($content['chapo']), true) ?></chapo>
<content><?= plxUtils::strCheck(trim($content['content']), true) ?></content>
<tags><?= plxUtils::strCheck(trim($content['tags']), false, true) ?></tags>
<meta_description><?= plxUtils::strCheck(trim($meta_description), false, true) ?></meta_description>
<meta_keywords><?= plxUtils::strCheck(trim($meta_keywords), false, true) ?></meta_keywords>
<title_htmltag><?= plxUtils::strCheck(trim($title_htmltag), false, true) ?></title_htmltag>
<thumbnail><?= plxUtils::strCheck(trim($thumbnail), false, true) ?></thumbnail>
<thumbnail_alt><?= plxUtils::strCheck(trim($thumbnail_alt)) ?></thumbnail_alt>
<thumbnail_title><?= plxUtils::strCheck(trim($thumbnail_title)) ?></thumbnail_title>
<date_creation><?= $dates['creation'] ?></date_creation>
<date_update><?= $dates['update'] ?></date_update>
<?php
Expand Down
4 changes: 2 additions & 2 deletions core/lib/class.plx.motor.php
Original file line number Diff line number Diff line change
Expand Up @@ -1122,12 +1122,12 @@ public function addCommentaire($content) {
ob_start();
?>
<comment>
<author><![CDATA[<?= plxUtils::cdataCheck($content['author']) ?>]]></author>
<author><?= plxUtils::strCheck($content['author']) ?></author>
<type><?= $content['type'] ?></type>
<ip><?= $content['ip'] ?></ip>
<mail><?= plxUtils::strCheck($content['mail']) ?></mail>
<site><?= plxUtils::strCheck($content['site']) ?></site>
<content><?= plxUtils::strCheck($content['content'], true) ?></content>
<content><?= plxUtils::strCheck($content['content'], true, '<a><b><i><p><q><u><em><sub><sup><del><pre><code><span><strong>', true) ?></content>
<parent><?= !empty($content['parent']) ? intval($content['parent']) : '' ?></parent>
<?php

Expand Down
108 changes: 93 additions & 15 deletions core/lib/class.plx.utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -892,36 +892,45 @@ public static function charAleatoire($taille=10) {
public static function strCut($str='', $length=25, $type='', $add_text='...') {
if($type == 'word') { # On coupe la chaine en comptant le nombre de mots
$content = explode(' ',$str);
$length = sizeof($content) < $length ? sizeof($content) : $length;
$length = count($content) < $length ? count($content) : $length;
return implode(' ',array_slice($content,0,$length)).$add_text;
} else { # On coupe la chaine en comptant le nombre de caractères
return strlen($str) > $length ? substr($str, 0, $length) . $add_text : $str;
}
}

/**
* Méthode qui retourne une chaine de caractères formatée en fonction du charset
* Méthode qui retourne une chaine de caractères formatée en fonction du charset ou encapsulé avec CDATA
* Possibilité de la nettoyer de toutes ou certaines balises HTML
*
* @param str chaine de caractères
* @param cdata encapsule str dans <![CDATA[ ]]> si true et str non nulle
* @param tags balises HTML autorisées dans <![CDATA[]]> ou null
* @return string chaine de caractères tenant compte du charset
* @param str string Chaine de caractères à formater OU à encapsulé
* @param cdata bool Encapsule str avec <![CDATA[ ]]> si true
* @param tags bool||string true : aucune Balises HTML || '', false : Toutes autorisées ou Liste* des autorisées '<a><br><em><i>...' *(array PHP>=7.4)
* @param clear bool true : scripts interdit et attributs nettoyés (nettoyage du html) + Effet de bords : valide et ferme les balises non fermées
* @return string Chaine vide ou chaine encapsulé par CDATA ou Chaine de caractères tenant compte du charset
**/
public static function strCheck($str, $cdata=false, $tags='<i><em><a><sup><span>') {
public static function strCheck($str, $cdata=false, $tags='', $clear=false) {

$str = trim($str);
if ($str === '') {
if(empty($str)) {
return '';
}

if ($cdata) {
# caractère " interdit. Remplacer par &quot; si besoin à la saisie
return '<![CDATA[' . strip_tags(str_replace('"', '', $str), $tags) . ']]>';
# Important : Appellé avant pour bien effacer toutes les balises <script>
# Évite que les balises <script> et </script> soient supprimées avec strip_tags
# et que leurs JS deviennent des noeuds textes impossible a nettoyés car non detectés.
# Elles sont supprimées avant et strip_tags n'aura point à les traiter car inexistantes.
# Si appellé après strip_tags : <script>JS</script> => JS => <p>JS</p>
if($clear) { # Scripts et autres attributs interdits : previent les attaques XSS
$str = plxUtils::sanitizeHtml($str);
}
if($tags) { # Balises HTML interdites (true) / Autorisées (liste)
$str = strip_tags($str, is_bool($tags)? '': $tags);
}
if($cdata) {
return '<![CDATA[' . plxUtils::cdataCheck($str) . ']]>';
}

# ENT_COMPAT : Convertit les guillemets doubles, et ignore les guillemets simples.
# les caractères suivants seont convertis en entités HTML : & > < "
return htmlspecialchars($str, ENT_COMPAT | ENT_HTML5, PLX_CHARSET);
return htmlspecialchars($str, ENT_QUOTES, PLX_CHARSET);
}

/**
Expand Down Expand Up @@ -1655,4 +1664,73 @@ public static function sanitizePhpTags(String $content) {
public static function sanitizePhp(String $content) {
return preg_replace('#\b(fsockopen|proc_open|system|exec|chroot|shell_exec|socket\w*)\b\([^)]*?\)\s*;#', '/* $1() not allowed here */;' . PHP_EOL, $content);
}


/**
* Nettoie du HTML ET Supprime les balises 'script' (par defaut) et ceux 'inline' pour prévenir des attaques XSS
* @param String|Array $content Texte ou tableau a nettoyer
* @param Array $noNodes Balises a supprimés :defaut: array('script'); :idée+: 'img',style','link','meta'
* @param Array $okAttrs Attributs a gardés :defaut: array('src','href','class'); :idée+: 'style'
* @return String|Array Variable nettoyée
* @author Thomas I. @sudwebdesign & info du web
* @note : Départ inspiré de https://mradeveloper.com/blog/remove-javascript-from-html-with-php (mais oublié '<a onclick=alert('wow')>')
* @todo : No goto? : traversé le DOM par la fin : boucle for inversée + recursive
* @voir : https://www.php.net/manual/fr/domdocument.loadhtml.php#125361
**/
public static function sanitizeHtml($content, $noNodes=array('script'), $okAttrs=array('src','href','class')) {
if(empty($content)) return $content;
elseif(is_bool($content)) return $content;
# Initialise les variables
if(is_array($content)) {
$inputArray = $content;
$returnType = 'array';
} else {
$inputArray = array(trim($content));
$returnType = 'string';
}
$sanitizedInput = array();
$flags = LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOERROR | LIBXML_NOBLANKS | LIBXML_NONET;
# Nettoyage
foreach($inputArray as $input) {
if(!empty($input) and is_string($input)){
# De https://www.php.net/manual/fr/function.strip-tags.php#119909
$xml = new DOMDocument('1.0', PLX_CHARSET);
# Suppression des avertissements
libxml_use_internal_errors(true);
# Petit hack pour un bon encodage : voir : https://www.php.net/manual/fr/domdocument.loadhtml.php#95251
if($xml->loadHTML('<?xml encoding="'.PLX_CHARSET.'"><html>' . $input . '</html>', $flags)){
$xml->encoding = PLX_CHARSET; # Insert propre du charset
RELOAD: # Fix récursif low cost : Voir : https://www.php.net/manual/fr/class.domnamednodemap.php#94078
foreach($xml->getElementsByTagName('*') as $tag){ # todo : pour faire bien, utiliser une boucle inversée
# Supprime un noeud interdit (script &+)
if(in_array($tag->nodeName, $noNodes)) {
$tag->parentNode->removeChild($tag);
goto RELOAD; # Nvl ordre du DOM, on recommence
}
elseif($tag->attributes->getNamedItem('href')
and stripos($tag->attributes->getNamedItem('href')->value, 'javascript') !== false) {
$tag->removeAttribute('href'); # Suppr inline js
}

RELOADATTR: # Suppr attributs interdits
foreach($tag->attributes as $attr){
if(!in_array(strtolower($attr->name), $okAttrs)){
$tag->removeAttribute($attr->name);
goto RELOADATTR;# Nvl ordre du DOM, on retraverse les attributs
}
}
}
}
# Sauve le HTML nettoyé et bien encodé :voir: https://www.php.net/manual/fr/domdocument.savexml.php#88525
$input = $xml->saveHTML($xml->documentElement); # sans l'entête xml et le html encapsulant
unset($xml);
}
$sanitizedInput[] = $input;
}

if($returnType == 'string') {
return $sanitizedInput[0];
}
return $sanitizedInput;
}
}
2 changes: 1 addition & 1 deletion themes/defaut/commentaires.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<?php $plxShow->lang('SAID'); ?> :
</small>
<blockquote>
<p class="content_com type-<?php $plxShow->comType(); ?>"><?php $plxShow->comContent(); ?></p>
<div class="content_com type-<?php $plxShow->comType(); ?>"><?php $plxShow->comContent(); ?></div>
</blockquote>
</div>
<?php
Expand Down