En terme de sécurité, il y a deux faces aux rapports d'erreur.
D'un coté, cela améliore la sécurité, mais d'un autre, cela
la réduit aussi.
Une tactique d'attaque standard consiste à faire faire des erreurs
au système, et lire les variables d'environnement et de contexte qui
sont retournées. Cela permet au pirate de lire de nombreuses
informations sur le serveur, et de détecter des faiblesses du serveur.
Par exemple, si un intrus a glané des informations sur votre page, avec
une première utilisation de votre site, il peut essayer de remplacer les
variables par ses propres valeurs :
Attacque de site avec une page HTML personnalisée
<form method="post" action="http://www.site.cible.com/?username=badfoo&password=badfoo">
<input type="hidden" name="username" value="badfoo">
<input type="hidden" name="password" value="badfoo">
</form>
Les erreurs PHP qui sont normalement retournées peuvent être
très pratiques pour un développeur qui essaie de débugger un
script, car elles donnent de précieux renseignements tels que
quelle fonction a échoué, quel fichier n'a pas été
trouvé, quel script PHP a buggé, et quelle ligne est en faute. Toutes
ces informations sont exploitables. Il est commun aux développeurs PHP
d'utiliser les fonctions show_source(),
highlight_string(), ou @xref{function.highlight-file,,highlight_file()}
comme outils de débuggage, mais sur un site en production, cela expose
des variables cachées, des syntaxes non vérifiées
ou d'autres informations critiques. Il est particulièrement dangeureux
d'exécuter du code de sources connues, avec les gestionnaires de
débuggage. Si l'intrus peut comprendre votre technique habituelle
d'utilisation, il peut tenter une attaque frontale sur une page, en
envoyant des chaînes de débuggage :
Exploiter des variables classiques de débuggage
<form method="post" action="http://www.site.cible.com/?errors=Y&showerrors=1"&debug=1">
<input type="hidden" name="errors" value="Y">
<input type="hidden" name="showerrors" value="1">
<input type="hidden" name="debug" value="1">
</form>
Indépendamment de la gestion des erreurs, la possibilité de tester
la gestion des erreurs d'un système conduit à un trou de sécurité,
et la diffusion de plus d'informations sur votre système.
Si un pirate affiche une page html, et essaye de la tester (pour
rechercher des faiblesses du système), il peut déterminer sur quel
système PHP a été compilé.
Une erreur de fonction indique si un système supporte une base de
données spécifique, ou bien indique comment la page a
été générée. Cela peut orienter l'intrus
vers les ports de cette base de données ou bien vers une attaque
liée à cette application. En envoyant des données
erronées, par exemple, un pirate peut déterminer l'ordre
d'authentification dans un script (à partir des lignes d'erreurs),
et d'essayer de les exploiter ailleurs, dans le script.
Une erreur de fichier, ou une erreur générale PHP peut indiquer
quelles sont les permissions du serveur web, ainsi que la structure
et l'organisation des fichiers. Les gestionnaires d'erreurs utilisateurs
peuvent aussi aggraver ce problème, en permettant l'exploitation facile
d'informations préalablement cachées.
Il y a trois solutions majeures à ces problèmes : la première
est de scruter toutes les fonctions, et d'essayer de traiter toutes les
erreurs. La deuxième est d'inactiver le rapport d'erreur, dès
que le script est en production. La troisième est d'utiliser les
fonctions de gestions des erreurs. Suivant votre politique de
sécurité, vous pouvez utiliser un panachage savant des
trois méthodes.
Une méthode pour gagner du temps est d'utiliser la fonction
error_reporting(), pour vous aider à
sécuriser le code, et détecter les utilisations dangeureuses de variables.
Vous testez votre code en béta-test avec la valeur E_ALL
,
et vous pouvez rapidement repérer les variables qui ne sont pas
protégées. Une fois que le code est prêt à être déployé,
utilisez la constante E_NONE
, pour isoler
votre code.
Détecter des variables non protégées avec E_ALL
<?php
if ($username) {
// Non initialisée, ou vérifée avant utilisation
$good_login = 1;
}
if ($good_login == 1) {
// Si le test ci-dessus échoue, les valeurs n'ont pas été testées
fpassthru ("/données/très/très/sensibles/index.html");
}
?>
Sommaire:
4.4 Rapport d'erreur