Il s'agit d'un plugin de Phan pour essayer de détecter les problèmes de sécurité (tels que XSS). Il garde une trace de chaque fois qu'un utilisateur peut modifier une variable et vérifie que de telles variables sont échappées avant d'être sorties sous forme de HTML ou utilisées comme requête SQL, etc.
Il prend en charge les projets de PHP génériques, et il a également un mode dédié pour le code MediaWiki (analyse les crochets, les HTMLForms et les méthodes de base de données).
Une démonstration Web est disponible.
$ composer require --dev mediawiki/phan-taint-check-plugin
Le plugin peut être utilisé en mode "manuel" et "autonome". Le premier est le meilleur choix si votre projet exécute déjà Phan, et presque aucune configuration n'est nécessaire. Ce dernier ne doit être utilisé que si vous ne souhaitez pas ajouter Phan à votre projet et n'est pas pris en charge pour le code lié à Mediaki. Pour plus d'informations sur l'utilisation par Wikimedia de ce plugin, voir https://www.mediaki.org/wiki/Phan-Taint-check-plugin.
Vous devez simplement ajouter Taint-Check à la section plugins de votre configuration Phan. En supposant que Taint-Check se trouve dans l'emplacement standard du fournisseur, par exemple $seccheckPath = 'vendor/mediawiki/phan-taint-check-plugin/'; , le fichier à inclure est "$seccheckPath/GenericSecurityCheckPlugin.php" pour un projet générique, et "$seccheckPath/MediaWikiSecurityCheckPlugin.php" pour un projet MediaWiki.
Assurez-vous également que le mode rapide est désactivé ou que le plugin ne fonctionnera pas:
' quick_mode ' => false Vous devez également ajouter SecurityCheck-LikelyFalsePositive et SecurityCheck-PHPSerializeInjection pour suppress_issue_types (ce dernier a un taux élevé de faux positifs).
Ensuite, exécutez Phan comme vous le feriez normalement:
$ vendor/bin/phan -d . --long-progress-bar
L'exécution de Phan avec --analyze-twice pourra saisir des problèmes de sécurité supplémentaires qui pourraient passer inaperçus dans la phase d'analyse normale. Une limitation connue de cela est que le même problème pourrait être signalé plus d'une fois avec des lignes causées différentes.
Vous pouvez exécuter la carrefour via:
$ ./vendor/bin/seccheck
Vous voudrez peut-être ajouter un alias de script de compositeur pour cela:
"scripts" : {
"seccheck" : " seccheck "
}Notez que les faux positifs sont désactivés par défaut.
Le plugin sortira divers types de problèmes en fonction de ce qu'il détecte. Les types de problèmes qu'il publie sont:
SecurityCheck-XSSSecurityCheck-SQLInjectionSecurityCheck-ShellInjectionSecurityCheck-PHPSerializeInjection - pour quand quelqu'un fait unserialize( $_GET['d'] ); Ce type de problème semble avoir un taux de faux positif élevé actuellement.SecurityCheck-CUSTOM1 - pour permettre aux gens d'avoir des types de souche personnalisésSecurityCheck-CUSTOM2 - DittoSecurityCheck-DoubleEscaped - détectant que HTML est en double évasionSecurityCheck-RCE - Exécution du code distant, par exemple eval( $_GET['foo'] )SecurityCheck-PathTraversal - Path Traversal, par exemple require $_GET['foo']SecurityCheck-ReDoS - Denial de service d'expression régulière (redos), par exemple preg_match( $_GET['foo'], 'foo')SecurityCheck-LikelyFalsePositive - un problème potentiel, mais probablement pas. Se produit principalement lorsque le plugin est confus. Le champ de gravité est généralement marqué comme Issue::SEVERITY_NORMAL (5) . Les faux positifs obtiennent Issue::SEVERITY_LOW (0) . Les problèmes qui peuvent entraîner un compromis sur le serveur (par opposition au compromis de l'utilisateur final) tel que l'injection Shell ou SQL sont marqués comme Issue::SEVERITY_CRITICAL (10) . Sérialisation L'injection serait normalement "critique", mais elle est actuellement désignée comme une gravité de la normale, car le contrôle semble avoir un taux de faux positif élevé pour le moment.
Vous pouvez utiliser l'option de ligne de commande -y de Phan pour filtrer par gravité.
Si vous avez besoin de supprimer un faux positif, vous pouvez mettre @suppress NAME-OF-WARNING dans le DocBlock pour une fonction / méthode. Alternativement, vous pouvez utiliser d'autres types de suppression, comme @phan-suppress-next-line . Voir Phan's Readme pour une liste complète. Le @param-taint et @return-taint (voir la section "Personnalisation") sont également très utiles pour traiter les faux positifs.
Notez que le plugin rapportera les vulnérabilités XSS possibles dans le contexte de la CLI. Pour les éviter, vous pouvez supprimer à l'échelle du fichier SecurityCheck-XSS avec @phan-file-suppress dans les scripts CLI, ou pour l'ensemble de l'application (en utilisant l'option de configuration suppress_issue_types ) si l'application se compose uniquement de scripts CLI. Alternativement, si toute sortie se produit à partir d'une fonction interne, vous pouvez utiliser @param-taint comme suit:
/**
* @param-taint $stuffToPrint none
*/
public function printMyStuff ( string $ stuffToPrint ) {
echo $ stuffToPrint ;
}Lors de la débogage des problèmes de sécurité, vous pouvez utiliser:
'@phan-debug-var-taintedness $varname';
Cela émettra un problème de SecurityCheckDebugTaintedness contenant la taintentesse de $varname sur la ligne où l'annotation est trouvée. Notez que vous devez insérer l'annotation dans un littéral de chaîne; Les commentaires ne fonctionneront pas. Voir aussi l'annotation de Phan @phan-debug-var .
@return-taint html .$options ) et le sixième ( $join_cond ) d' IDatabase::select() de MediaWiki Si elle est directement fournie comme littéral de tableau, ou directement renvoyée sous forme de littéral à partir d'une méthode getQueryInfo() . Le plugin prend en charge la personnalisation, en sous-classant la classe SecurityCheckPlugin. Pour un exemple complexe de le faire, voir MediaWikiSecurityCheckPlugin.
Parfois, vous avez des méthodes dans votre base de code qui modifient la souillure d'une variable. Par exemple, une fonction d'échappement HTML personnalisée doit effacer le bit de souche HTML. De même, parfois le vérification de Phan-Taint peut être confus et vous souhaitez remplacer la souillure calculée pour une fonction spécifique.
Vous pouvez le faire en ajoutant une directive de souillure dans un commentaire DocBlock. Par exemple:
/**
* My function description
*
* @param string $html the text to be escaped
* @param-taint $html escapes_html
*/
function escapeHtml ( $ html ) {
}Les méthodes héritent également de ces directives à partir de définitions abstraites dans les interfaces ancêtres, mais pas des implémentations concrètes dans les classes d'ancêtre.
Les directives de souillure sont préfixées avec @param-taint $parametername ou @return-taint . S'il y a plusieurs directives, ils peuvent être séparés par une virgule. @param-taint est utilisé pour marquer comment la souillure est transmise du paramètre à la valeur de retour des méthodes, ou lorsqu'il est utilisé avec les directives exec_ , pour marquer les endroits où les paramètres sont sortis / exécutés. @return-taint est utilisé pour ajuster la souillure de la valeur de retour, quels que soient les paramètres d'entrée.
Le type de directives comprend:
exec_$TYPE - Si un paramètre est marqué en tant que exec_$TYPE l'alimentation de ce paramètre Une valeur avec $TYPE Taint entraînera un avertissement déclenché. En règle générale, vous l'utiliseriez lorsqu'une fonction qui publie ou exécute son paramètreescapes_$TYPE - Utilisé pour les paramètres où la fonction s'échappe puis renvoie le paramètre. Ainsi, escapes_sql effacerait le bit de souillure SQL, mais laisserait d'autres bits de souillure seuls.onlysafefor_$TYPE - pour une utilisation dans @return-taint , marque le type de retour comme sans danger pour un $TYPE spécifique mais dangereux pour les autres types.$TYPE - Si le type est spécifié dans un paramètre, il est bitwisé et avec la souillure de la variable d'entrée. Normalement, vous ne voudriez pas le faire, mais peut être utile lorsque $TYPE none pour spécifier que le paramètre n'est pas utilisé pour générer la valeur de retour. Dans un @return cela pourrait être utilisé pour énumérer les indicateurs de souillure la valeur de retour, ce qui n'est généralement utile que lorsqu'il est spécifié comme tainted de dire qu'il a tous les drapeaux.array_ok - Indicateur à usage spécial pour dire ignorer les arguments entachés s'ils sont dans un tableau.allow_override - Indicateur à usage spécial pour spécifier que cette annotation de souillure doit être remplacée par Phan-Taint-Check si elle peut détecter une souillure spécifique. La valeur pour $TYPE peut être l'une des htmlnoent , html , sql , shell , serialize , custom1 , custom2 , code , path , regex , sql_numkey , escaped , none , tainted . La plupart d'entre eux sont des catégories de souillure, sauf:
htmlnoent - Comme html mais désactivez la détection à double échappement qui est utilisée avec html . Lorsque escapes_html est spécifié, échappé est automatiquement ajouté à @return et exec_escaped est ajouté à @param . De même, onlysafefor_html équivaut à onlysafefor_htmlnoent,escaped .none - signifie pas de souilluretainted - signifie toutes les catégories de souillure sauf les catégories spéciales (équivalent à SecurityCheckPlugin::YES_TAINT )escaped - est utilisé pour signifier que la valeur est déjà échappée (pour suivre la double évasion)sql_numkey - est un objectif assez spécial pour MediaWiki. Il ignore la souillure dans les tableaux s'ils sont pour les clés associatives. La valeur par défaut pour @param-taint est tainted s'il s'agit d'une chaîne (ou d'un autre type dangereux), et none si c'est quelque chose comme un entier. La valeur par défaut pour @return-taint est allow_override (ce qui équivaut à none à moins que quelque chose de mieux ne puisse être automatique).
Au lieu d'annoter des méthodes dans votre base de code, vous pouvez également personnaliser Phan-Taint-Check pour avoir des connaissances intégrées de Tainnts de méthode. De plus, vous pouvez étendre le plugin pour avoir un comportement assez arbitraire.
Pour ce faire, vous remplacez la méthode getCustomFuncTaints() . Cette méthode renvoie un tableau associatif de noms de méthode pleinement qualifiés dans un tableau décrivant comment la souillure de la valeur de retour de la fonction en termes de ses arguments. Les clés numériques correspondent au nombre d'un argument, et une clé «globale» ajoute une souillure qui n'est présente dans aucun des arguments. Fondamentalement, pour chaque argument, le plugin prend la souillure de l'argument, le bit en bit et le fait à son entrée dans le tableau, puis est la clé globale. Si l'une des touches du tableau a des indicateurs d'exécution, alors un problème est immédiatement soulevé si la souillure correspondante est nourrie de la fonction (par exemple, une fonction de sortie). Les drapeaux Exec ne fonctionnent pas dans la clé «globale».
Par exemple, HTMLSpecialChars qui supprime la soute HTML, échappe à son argument et renvoie la valeur échappée que ressemblerait:
' htmlspecialchars ' => [
( self :: YES_TAINT & ~ self :: HTML_TAINT ) | self :: ESCAPED_EXEC_TAINT ,
' overall ' => self :: ESCAPED ,
];Les variables d'environnement suivantes affectent le plugin. Normalement, vous n'auriez pas à les ajuster.
SECURITY_CHECK_EXT_PATH - Chemin vers le répertoire contenant extension.json / skin.json en mode MediaWiki. Sinon, Set suppose le répertoire racine du projet.SECCHECK_DEBUG - Fichier pour produire des informations de débogage supplémentaires (si l'exécution de shell , /dev/stderr est pratique) Licence publique générale GNU, version 2 ou version ultérieure