CONNAITRE SI LE FICHIER UPLOADER N'EST PAS UN FICHIER PHP

LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009 - 26 déc. 2006 à 08:36
aze555666 Messages postés 208 Date d'inscription mardi 13 avril 2004 Statut Membre Dernière intervention 26 janvier 2009 - 3 janv. 2007 à 22:59
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/40856-connaitre-si-le-fichier-uploader-n-est-pas-un-fichier-php

aze555666 Messages postés 208 Date d'inscription mardi 13 avril 2004 Statut Membre Dernière intervention 26 janvier 2009
3 janv. 2007 à 22:59
Je sais. Je parlais du probleme de laisser ou non uploader des programmes sur le serveur.
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
3 janv. 2007 à 16:16
.... aze555666 ce code n'empèche pas d'uploader de fichiers asp...
aze555666 Messages postés 208 Date d'inscription mardi 13 avril 2004 Statut Membre Dernière intervention 26 janvier 2009
2 janv. 2007 à 19:02
@malamam en effet, je n'y avais pas pensé :-)
@coucou747 il me semble qu'il y a un site asp sur codes sources, le probleme est donc entier. Heuresement donc que ce sont en fait des zip.
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
2 janv. 2007 à 12:51
nix a un serveur ASP... impossible d'y exécuter du php (enfin, php tourne sous IIS, mais je serais étonné que nix ai installé le programme...)
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
2 janv. 2007 à 09:33
@AZE => Nix uploade des fichiers ZIP...c'est très différent ;-)
aze555666 Messages postés 208 Date d'inscription mardi 13 avril 2004 Statut Membre Dernière intervention 26 janvier 2009
2 janv. 2007 à 01:16
@malamam "perso, je ne laisserais pas un mec uploader ce genre de fichier sur mon serveur web...". Eh bien heuresement que Nix n'a pas les mêmes principes :-)
Pour reprendre le débat, on peut peut-ête éviter de se battre en utilisant la fonction de kankrelune lorsqu'un script php du site utilise un include non fixe (je veux dire qui d'inclue pas toujours le même fichier c'est à dire include('&fichier') plutot que include'machin.txt')), et se contenter de vérifier les extensions "à risque" (ce qui dépend du serveur, mais il suffit alors à chacun de lister dans le code php les extensions interdites une bonne fois pour toutes, plutot que de parser le php.ini à chaque exécution) lorsque ce n'est pas le cas.
amezghal Messages postés 385 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 21 août 2015 5
28 déc. 2006 à 16:12
suis avec preg_match,
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
28 déc. 2006 à 15:23
Suis de l'avis de Kankrelune, je pense que preg_match est la meilleure solution.
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
28 déc. 2006 à 15:19
Pareil pour strrpos()... mieux vaut un preg_match()... .. .

@ tchaOo°
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
28 déc. 2006 à 15:19
explode alors, mais ça aussi c'est gourmand...
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
28 déc. 2006 à 15:10
strpos s'arrête au premier motif trouvé. Donc là, hormis le fait que ton code est foireux -mais on a compris le principe-, si tu as d'abord <?xml suivi de <?php, t'es marron.
amezghal Messages postés 385 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 21 août 2015 5
28 déc. 2006 à 15:00
$file=file_get_contents($fichier);
$pos=strpos($file,"<?");
if($i===false){
return true;
}else{
if(substr($file,$pos,3)=="xml")
return false;
else
return true;
}
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
28 déc. 2006 à 14:23
Peut être... à tester... mais ça risque d'être plus facilement contournable...

<?xml ?>
<?php echo 'dans l\'os';
<?xml ?>

ça risque de passer... .. .

@ tchaOo°
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
28 déc. 2006 à 14:08
sur un gros fichiers, deux strpos, c'est mieux qu'un preg_match...
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
28 déc. 2006 à 14:04
@ amezghal... fais une recherche c'est mainte fois traité... sur ce site comme ailleurs... d'ailleurs tu devrais savoir de quoi il sagit car ton code est principalement (voir uniquement) destiné à empecher l'upload de fichier visant ce type de faille... .. .

@ coucou747... oui sauf que, comme dit plus haut, strpos ne fera pas la différence entre <?, <?php et <?xml... le preg_match est donc préférable... ou alors il faut faire des multiple strpos et je suis pas sûr du gain en perf... .. . ;o)

@ tchaOo°
amezghal Messages postés 385 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 21 août 2015 5
28 déc. 2006 à 13:40
une faille d'include ??
explique bien cette faille ça aide plus les autres(aussi moi ;p)
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
28 déc. 2006 à 11:35
si par hazard, t'as une faille de include sur ton site, et que n'importe qui peut inclure un fichier qui est présent sur ton site :
include('path/'.$_GET['file']);
si ton upload accèpte un .png qui contient :
<?php
echo '<hr />'.$password_mysql.'<hr/>';
?>
ça peut être une très mauvaise chose...

salon moi, strpos devrait remplacer ce code, mais la méthode est la bonne
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
28 déc. 2006 à 09:12
Hello,

j'arrive après la guerre on dirait...mais j'ai passé un très bon Noël ;-)
Bon, j'interviens juste pour dire que ce code va rester, déjà.
Et pour donner mon avis : tel que je le vois ici, même si sa place serait plutôt dans les snippets (www.codyx.org, je le rappelle), il me plait bien. Certes, ça peut être lourd, mais c'est efficace. Et dans le cadre d'un upload, il faut voir qu'il sera rare que l'on ait à utiliser cette fonction 20 fois d'affilée...ou sur un gros fichier.
Pour reprendre cet exemple :
"
Pour faire un hello world en php, il faut faire :

<?php echo 'Hello World'; ?>

Voilà ! A la prochaine !
"
perso, je ne laisserais pas un mec uploader ce genre de fichier sur mon serveur web...c'est la porte ouverte à toutes les fenêtres, comme dirait l'autre.
Quand bien même aurais-je la main sur mon serveur, d'ailleurs : question de principe ;-)
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
27 déc. 2006 à 16:11
Pour savoir si un fichier contient du php... si... le code si dessus... après concernant l'execution de fichier par le serveur effectivement c'est une autre histoire... .. .

@ tchaOo°
webdeb Messages postés 488 Date d'inscription samedi 5 avril 2003 Statut Membre Dernière intervention 31 mars 2009 4
26 déc. 2006 à 22:38
Il n'y a pas de solution fiable de toute façon !
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
26 déc. 2006 à 20:37
Ca change pas le problème puisque dans le cas d'un include toutes les extensions sont à risque... même les images... .. .

@ tchaOo°
Naixn Messages postés 455 Date d'inscription mardi 17 septembre 2002 Statut Membre Dernière intervention 22 juillet 2007
26 déc. 2006 à 17:20
Bah j'ai bien proposé de parser le php.ini ( ou php5.conf pour moi ) pour connaître les extensions à risque... :)
Mais sur Windows, ou sur tout autre configuration apache ou le php.ini ne fait qu'un seul et même fichier, ça risque d'être lourd...
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
26 déc. 2006 à 17:02
@ amezghal... si le fichier n'existe pas forcement il n'y a pas de code php dedans donc return false... quand à faire le test avant... non... d'une part la fonction doit être autonome donc si le fichier n'existe pas ça sert à rien qu'elle essaye de l'ouvrir (et ça évitera un warning)... d'autre part imaginons que tu utilise 20 fois cette fonction dans un script (peu de chance avec cette fonction mais imaginons) tu ne va pas faire 20 fois le test pour savoir si le fichier existe c'est à la fonction de le faire (en plus tu gagne de la place et c'est quand même un des but d'une fonction)... .. .

@ tchaOo°
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
26 déc. 2006 à 16:58
L'execution de code par php lors d'un include ne dépend pas du serveur donc ce n'est pas une question de configuration serveur... .. !

Par contre lorsque tu vas sur ce fichier en effet le serveur le traite en fonction de sa configuration... .. .

@ tchaOo°

ps : je ne dirais pas horrible... lourd sans ausun doute... mais si tu as une meilleur solution... .. ?
amezghal Messages postés 385 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 21 août 2015 5
26 déc. 2006 à 16:57
KANKRELUNE: pour ta version pourquoi tu met
if(!is_file($fichier))
return false;

a mon avis cette vérif ce fait avant l'utilisation de la fonction,
car
true:ya du code php
false: ya po
!!
Naixn Messages postés 455 Date d'inscription mardi 17 septembre 2002 Statut Membre Dernière intervention 22 juillet 2007
26 déc. 2006 à 16:38
Kankrelune : je crois que tu n'as pas lus les commentaires juste avant.
Les serveurs Apache, IIS, lighTTPD, etc. peuvent être configurés tels qu'ils fassent interpréter les fichiers HTML par PHP.

Cela dépend donc du serveur...

Sinon, si c'est pour tester la présence de code PHP, on est d'accord, ça teste bien, même si la façon de faire est vraiment horrible.
Après, si c'est pour vérifier la présence de code PHP QUI VA ÊTRE EXECUTÉ, alors là, non, je ne suis pas d'accord :)
amezghal Messages postés 385 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 21 août 2015 5
26 déc. 2006 à 16:17
merci KANKRELUNE pour la version améliorée

Naixn, no comment.

-mais en peut encore améliorer la fonction

amicalelment
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
26 déc. 2006 à 15:57
Alors là je crois qu'on ne se comprend pas... l'interet de ce genre de fonction est d'empecher l'upload de tous les fichiers contenant du php pour éviter l'exploitation d'une faille include par exemple... car si on reprend l'exemple que tu donne précédament si le pirate réussis à l'inclure le fichier sera éxécuté quel que soit son extension... l'extension conditionne la façon dont le serveur traite le fichier mais concernant php ce n'est pas la même musique...

include('monfichier.txt');

le fichier sera éxécuté...

echo file_get_contents('monfichier.php');

le fichier ne sera pas éxécuté... mais je pense que je ne t'apprend rien... .. .

Donc le but ici est juste de tester la présence de code php... point... et cette fonction (ou plutot la version que je donne) le fait très bien... .. . ;o)

@ tchaOo°
Naixn Messages postés 455 Date d'inscription mardi 17 septembre 2002 Statut Membre Dernière intervention 22 juillet 2007
26 déc. 2006 à 15:52
Eh bien, oui, ça sera reconnu en tant que fichier PHP, alors que ça n'en est pas un.

Certes tous les fichiers PHP seront reconnus, mais certains qui ne le sont pas le seront aussi.

Avoir un système qui fonctionne sur de faux-positifs ne peut pas, à mon goût, être qualifié de fiable...
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
26 déc. 2006 à 15:47
Et bien la fonction renverra true car <?php sera reconnu... moi je ne parse pas la première ligne mais tout le contenu... donc tu pourra mettre autant de text que tu veux ça reviendra au même... .. .

@ tchaOo°
Naixn Messages postés 455 Date d'inscription mardi 17 septembre 2002 Statut Membre Dernière intervention 22 juillet 2007
26 déc. 2006 à 15:45
Encore une fois, non !
Elle n'est pas fiable du tout !
Regarde bien mon exemple dans mon commentaire au dessus du tiens !
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
26 déc. 2006 à 15:40
La méthode de Amezghal bien que lourde est la seule vraiment fiable... en effet il est très simple de contourner le filtrage par extension via une fausse extension ou via une attaque null byte... il est également possible de simuler une image en ajoutant le bon header dans le contenu du fichier... bref le seul moyen fiable c'est de parser le contenu... par contre la fonction si dessus doit être améliorée... .. .

<?php

function is_php($fichier)
{
if(!is_file($fichier))
return false;

return (bool)preg_match('~<\?[^xml]~i',file_get_contents($fichier));
}

?>

@ tchaOo°
Naixn Messages postés 455 Date d'inscription mardi 17 septembre 2002 Statut Membre Dernière intervention 22 juillet 2007
26 déc. 2006 à 15:25
Non, elle n'est pas du tout efficace !
Exemple, je créé un fichier qui s'appelle "exemple de fichier PHP.txt"
Avec le contenu suivant :

"
Pour faire un hello world en php, il faut faire :

<?php echo 'Hello World'; ?>

Voilà ! A la prochaine !
"

Eh bien mon fichier contient les extensions PHP, pourtant ça n'en est pas un :-/

Le problème avec le type MIME, c'est que pour un fichier PHP, ça donnerait :
text/plain
Or, c'est aussi le cas des fichier TXT, HTML, etc.
Donc ça ne serait pas du tout efficace non plus.
younes371 Messages postés 502 Date d'inscription mercredi 29 décembre 2004 Statut Membre Dernière intervention 20 mars 2012
26 déc. 2006 à 14:45
la technique est tres lourde pour le serveur, mais elle est tres efficace,
mais reste à voir d'autres techniques plus simple,
par exemple la technique de verification d'extenstion :

<?php
//On fait un tableau contenant les extensions autorisées.
//Comme il s'agit d'un avatar pour l'exemple, on ne prend que
//des extensions d'images.
$extensions = array('.png', '.gif', '.jpg', '.jpeg');
// récupère la partie de la chaine à partir du dernier . pour
//connaître l'extension.
$extension = strrchr($_FILES['avatar']['name'], '.');
//Ensuite on teste
if(!in_array($extension, $extensions))
//Si l'extension n'est pas dans le tableau
{
$erreur = 'Vous devez uploader un fichier de type png, gif, jpg, jpeg, txt ou doc...';
}
?>
//Cette méthode est une première approche qui nous suffit pour
//le moment mais, en réalité, il faudrait vérifier le type MIME
//des fichiers uploadés.
Naixn Messages postés 455 Date d'inscription mardi 17 septembre 2002 Statut Membre Dernière intervention 22 juillet 2007
26 déc. 2006 à 14:41
Trouver une solution universelle, je ne suis pas bien sûr qu'il y en ai une efficace...
Je sais qu'avec ma configuration apache, il me suffirait de parser le fichier :
/etc/apache2/mods-available/php5.conf
Dans lequel j'ai (entre autre) :
AddType application/x-httpd-php .php .phtml .php3 .html .htm .inc .selected .txt .xml
Ce qui permet de connaître quels sont les fichiers qui peuvent être des fichiers PHP.
Après, ça dépend de la conf PHP de chacun... Et en plus ça marche pas sur Windows =D

P.S.: Oui ! Je sais c'est over dégueulasse les fichiers .txt/.xml parsés par PHP. Mais c'est pas moi qui choisi :(
TheSin Messages postés 331 Date d'inscription mardi 12 novembre 2002 Statut Membre Dernière intervention 10 février 2009
26 déc. 2006 à 13:52
Naixn, c'est sûr que c'est toujours plus pratique de simplement avoir l'extenstion html que php pour le référencement, mais il me semble que ça ne change rien, si ?
A la rigueur, vous avez toujours l'URL Rewriting, mais bon, vu que c'est pas toi qui décide .... ;-)

La solution par l'extension me parait être une bonne chose, si on a pas le serveur configuré comme à la boite de Naixn :-P
amezghal Messages postés 385 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 21 août 2015 5
26 déc. 2006 à 13:48
Naixn
a ton avis c quoi la solution,
je sais que ma méthode est tres lourde sur le serveur, mais ca, est valable pour les gros fichiers.
par contre ,et pour les fichiers dont la tailles est inferieur à 1Mega, yaura po des probs.
tu peut nous proposer une methode nickel?surtt que té d'accord que
" la reconnaissance par l'extension n'a jamais été une bonne chose !"
amicalement.
Naixn Messages postés 455 Date d'inscription mardi 17 septembre 2002 Statut Membre Dernière intervention 22 juillet 2007
26 déc. 2006 à 12:52
TheSin > Non, ça se devine bien qu'on utilise PHP, quand même.
Pendant un temps, c'était pour le référencement mais bon...
Mais en fait là, maintenant, les fichiers html, tu peux renommer en php c'est pareil, y'a des tags <?php ?> etc.

Enfin c'est pas moi qui ai choisi hein ! C'était déjà comme ça avant que j'arrive en fait =)
jdalton42 Messages postés 200 Date d'inscription samedi 25 décembre 2004 Statut Membre Dernière intervention 19 août 2009
26 déc. 2006 à 12:51
rien a voir
audayls Messages postés 373 Date d'inscription samedi 9 juillet 2005 Statut Membre Dernière intervention 11 août 2008
26 déc. 2006 à 12:35
Analyser les fichiers HTML par PHP, c'est en quelque sorte de l'URL Rewriting non ?
TheSin Messages postés 331 Date d'inscription mardi 12 novembre 2002 Statut Membre Dernière intervention 10 février 2009
26 déc. 2006 à 11:40
Naixn, pourquoi vous envoyez aussi les fichiers HTML à PHP ? pour faire du PHP sans que le client ne le sache ?
Naixn Messages postés 455 Date d'inscription mardi 17 septembre 2002 Statut Membre Dernière intervention 22 juillet 2007
26 déc. 2006 à 11:24
Ça dépend de la configuration Apache. C'est apache qui décide quel types de fichier sont à envoyer à PHP.
A mon boulot, par exemple, les fichiers HTML sont aussi envoyés à PHP.
De toute façon, la reconnaissance par l'extension n'a jamais été une bonne chose !
jdalton42 Messages postés 200 Date d'inscription samedi 25 décembre 2004 Statut Membre Dernière intervention 19 août 2009
26 déc. 2006 à 11:05
Plus facile, simplement récupèrer l'extention... php n'execute que les fichiers dont l'extention est .php
Naixn Messages postés 455 Date d'inscription mardi 17 septembre 2002 Statut Membre Dernière intervention 22 juillet 2007
26 déc. 2006 à 09:57
Bah en fait là, il ne fait que lire la première ligne.
Il suffirait que je fasse :

<html>
<head>
<title><?php echo $conf['title']; ?></title>
</head>

<?php

do_something();

?>

</html>

Et là, son truc ne marche pas...
Mais quoiqu'il en soit, ce serait vraiment porc de lire l'ensemble du fichier pour vérifier si c'est un fichier PHP.
Imaginez : si quelqu'un upload une vidéo de 500Mo, le script PHP va faire des fgets() en masse dessus ?

Bref, 1 pour la source.
Je doute même qu'elle ne reste très longtemps.
LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009
26 déc. 2006 à 08:36
Bon, ça reste à verifier ce que je vais dire, mais c'est tout pourri ton truc. Si c'est un fichier XML bien formé, bah il va croire que c'est un fichier PHP. Qui plus est, un fichier PHP n'est pas censé commencé par <?, mais par <?php, non ?
++ !
Rejoignez-nous