Résolu Scanner les fichiers uploadés sur mon serveur

jinpol

Habitué
Bonjour,

j'ai une application qui permet d'uploader des fichiers, et je voudrais savoir comment faire pour les scanner avant de les stocker dans ma base de données.

Je m'explique.
En fait, j'ai une application en ligne (PHP + PostgreSQL) qui tourne sur un serveur Apache Windows server 2003. Cette application permet aux utilisateurs d'uploader des fichiers.
Ces fichiers sont stockés dans une base de données PostgreSQL qui se trouve sur un serveur Ubuntu.

Or, j'aimerai qu'avant de stocker ces fichiers dans la BD, ceux-ci soient scannés par un antivirus que je pourrai lancé en ligne de commande via mon code PHP. Comme ça, si le fichier est vérolé, je le supprime et sinon je le stocke dans ma BD...

Y'a t'il un moyen de faire ça simplement svp ???

Merci de votre aide.

Tchuss, jinpol...
 

zeb

Modérateur
Salut Jinpol :hello:

Es-tu allé voir du côté de la fonction PHP system() ?
Quand à savoir quelle ligne de commande passer, elle doit dépendre de ton AV.
Lequel utilises-tu ?

Tu stockes vraiment des fichiers dans une base de données ? :heink:
En général, on les stocke dans un répertoire particulier et on gère une URI dans la base de données.
 

bebRito

Grand Maître
Salut !

Il faudrait d'abord avoir un antivirus sur la machine de réception. Ensuite, selon l'antivirus, il y a en général un mode invite de commande. Ce serait donc faisable en PHP, à condition de bien sécuriser évidemment.

Voilà une piste.

Le retour de la commande (vrai ou faux) pourrait être traiter pour renvoyer à l'utilisateur le succès/échec de son action et insérer ou non le fichier dans la base.


EDIT: trop rapide le zeb !! l'avantage du ressort :D
 

jinpol

Habitué
Salut et merci pour vos réponses.

> zeb : pour le moment, je n'utilise pas d'antivirus. Tu a des conseils à donner au sujet d'un bon antivirus qui s'utilise en ligne de commande ??? Sur les PC ici, on utilise en général Avast ou Trend Micro OfficeScan.

> bebRito : qu'est ce que tu veux dire par "à condition de bien sécuriser" ???

Encore merci pour votre aide.
Tchuss, @+, jinpol...
 

jinpol

Habitué
Bon, et bien apparemment, il n'est pas évident de trouver un antivirus gratos qui puisse s'utiliser en ligne de commande.

Avast par exemple n'est dispo en ligne de commande que dans sa version pro.
Je ne dis pas que j'y passerai jamais (même si c'est pas moi qui décide), mais j'aurai bien aimé pouvoir tester dans un premier temps sur une version gratos pour voir si la solution fonctionne correctement ou non...
 

bebRito

Grand Maître
Salut !

Il y a Avira qui est très bien en gratuit et qui possède un outil d'exécution en ligne de commande : (dernier fichier de la liste)

Ensuite pour ce que j'ai dit sur la sécurité, c'est surtout sur la façon de coder en PHP. Le PHP est exécuté côté serveur, si tu ne prends pas quelques précautions, tu peux vite te faire attaquer, surtout en exécutant une commande sur le serveur. Voici un guide sur la sécurité en français : http://phpsec.org/projects/guide/fr/

Après, tout dépend si le site est public ou en intranet ... ;)
 

jinpol

Habitué
Salut, et merci pour tes réponses.

Premièrement, pour la sécurité, ça m'a l'air bien intéressant tout ça, donc je vais me le mettre en favori, et dès que je peux, je vais me lire ce petit guide sur la sécurité :)

Ensuite, je viens de tester Avira qui à l'air très facile d'utilisation en effet.
J'ai téléchargé ce que tu m'as dit, et ensuite, il faut récupérer ce zip à l'adresse suivante et mettre les fichiers qu'il contient dans le répertoire d'antivir :



Il contient entre autre les définitions de virus.
Par contre je ne sais pas si il y a moyen de ne récupérer QUE le fichier des définitions de virus, car ce fichier fait quand même 30Mo, et je pense que pour mettre à jour les définitions, seuls les fichiers antivirX.vdf sont nécessaires (bon, on ne gagne que 5Mo au final, c'est vrai).

Autre remarque, cette version gratuite est quand même limitée par le fait que l'option -s n'est pas dispo, c'est à dire qu'on ne peut pas scanner dans les sous-répertoire. Par contre, on peut scanner dans les fichiers zip, et donc, pour mon utilisation, c'est suffisant.
Il faut maintenant que je vois si y'a moyen de récupérer facilement ce que renvoie le scan, afin d'insérer ou non le fichier uploader dans la base de données.

Pour le moment, j'ai juste essayé cet antivirus dans une commande Windows, je ne l'ai tjs pas intégré dans du code PHP.
 

bebRito

Grand Maître
Bon bah ca avance tout ça, c'est bien ! :D

Pour la mise à jour des définitions, je ne me suis pas penché sur le problème. Je vais y jeter un œil.
Si tu veux faire du récursif, tu devrais pouvoir le faire par PHP ou par un script (.bat ou autre) appelé par PHP.

Autre chose importante, à priori le Avira AntiVir Command Line Scanner (AVCLS) n'est pas nécessaire si tu as Avira Free Edition installé (source : et )
 

jinpol

Habitué
Bon, ça avance comme tu dis, et c'est bien grâce à toi, merci.
J'ai écris une fonction PHP à qui on donne en paramètre le nom du fichier à scanner :

[cpp]function ScanVirusFile($filename)
{
//Le nom du fichier a scanner dans le repertoire D:/tmp/
$filetoscan = basename($filename);
//Le nom du fichier de log du scan
//En fait on le cree pour ne pas que le texte s'affiche directement dans le navigateur
//Puis on le supprime une fois le scan termine
$filescanlog = "D:\antivir\scan".rand().".log";
//La commande a lancer pour scanner le fichier uploade
$scancommand = "D:\antivir\avcls -z -noboot D:/tmp/".$filetoscan." > ".$filescanlog;
//La commande a lancer pour supprimer le fichier de log
$rmcommand = "del ".$filescanlog;
system($scancommand,$return_scan);
system($rmcommand,$return_rm);

return $return_scan;
}[/cpp]

En fait, j'ai du rajouter une petite astuce car quand je lance l'antivirus et que je reviens sur ma page php, ça me met dans mon navigateur le resultat du scan (j'ai pas trouvé le moyen de le désactiver). Du coup ce que je fais, je crée un fichier log dans lequel je mets ce résultat, et une fois le scan terminé, je le supprime.
Ensuite, dans ma page qui appelle cette fonction, si le résultat est 0, le fichier est sain et je peux l'insérer dans ma BD, sinon j'envoie un message à l'utilisateur comme quoi le fichier est vérolé.
Le seul problème, c'est que je n'ai pas pu testé de fichier vérolé :)
J'ai pris un fichier dans la quarantaine de Avast sur mon PC, et j'ai testé l'upload...mais ça m'a renvoyé 0. Donc est-ce que Avast m'a mis en quarantaine un fichier sain, ou bien est-ce que avcls n'a pas détecté le virus ???
Il faudrait que je trouve un vrai fichier foireux pour tester :D

Sinon pour le problème des mises à jour, il faudrait que je fasse une tâche planifiée qui lance un programme qui récupère l'archive sur le net, puis qui la dézippe, et enfin qui la mette dans le répertoire d'avcls...
 

bebRito

Grand Maître
Meilleure réponse
Pour éviter d'afficher le résultat, tu peux essayer de passer par la fonction PHP "exec".

Pour le retour de la commande, pas facile en effet d'avoir un virus sous la main !
Il faut faire attention tout de même, Avast et Antivir sont réputés pour faire pas mal de faux positifs, donc détectent des virus alors qu'il n'y en a pas.

Sinon, l'algo est bon et dans le principe, tu y es ! ;)
 

jinpol

Habitué
Bon ben voilà, on y est arrivé...c'est plus facile à deux ;)
Donc en effet, avec la fonction exec, je n'ai plus le problème d'affichage dans ma page internet, et donc ma fonction se résume à ça :

[cpp]
/**
* Fonction qui scanne $filename pour verifier si le fichier est infecte ou non
* Return 0 si le fichier est sain
* @returns string
*/
function ScanVirusFile($filename)
{
//Le nom du fichier a scanner dans le repertoire D:/tmp/
$filetoscan = basename($filename);

//La commande a lancer pour scanner le fichier uploade
$scancommand = "D:\avcls\avcls -z -noboot D:/tmp/".$filetoscan;

exec($scancommand,$output,$return_scan);

return $return_scan;
}
[/cpp]

Voilà donc pour la fonction et pour le traitement du résultat, je fais comme indiqué dans mon post précédent, je mets dans ma BD si le résultat est 0 (fichier sain), sinon j'averti à l'utilisateur que son fichier ne sera pas uploader car il présente un risque.

Et donc pour automatiser la mise à jour de mes définitions de virus, je crée une tâche planifiée qui lance le progamme suivant :

[cpp]
@echo off
rem //script qui permet de recuperer sur le net les dernieres definitions de l'antivirus avcls via wget
rem //puis qui le dezippe dans le repertoire d:/avcls via 7Zip

rem ==init variables==
set binpath="C:\Program Files\7-Zip"

rem ==recuperation de l'archive==
wget

rem ==decompression de l'archive==
%binpath%\7z.exe e -y "ivdf_fusebundle_nt_en.zip"

goto end

:end
[/cpp]

où 7-Zip est un petit programme de compression, et wget est l'équivalent du wget de Linux, qui permet de récupérer des fichiers sur le net.
Je les ai trouvé ici :
7-Zip -> http://www.7-zip.org/
wget -> http://users.ugent.be/~bpuype/wget/

Voilà, je pense que c'est tout bon.
Y'a juste que je n'ai toujours pas pu tester avec un vrai fichier vérolé, et j'espère aussi que avcls ne va pas me bloquer trop souvent des fichiers sains, sinon, ce sera inutilisable.

En tous cas encore merci pour ton aide (et Zeb aussi), ça m'a fait gagner pas mal de temps.

Tchuss, @+, jinpol...
 

bebRito

Grand Maître
Cool !

Pour l'histoire des faux positifs, ca va, ce n'est pas non plus désastreux.

Cependant, si tu veux un antivirus payant très performant et disposant d'un invite de commande, je ne peux que te conseille Eset Nod32. Pour l'avoir depuis quelques temps, je peux te dire qu'il est très efficace et figure parmi les meilleurs du marché, que ce soit en terme de perf ou de détection.

Si je trouve un moyen pour te trouver un virus, je te fais signe ;)
 

jinpol

Habitué
Merci pour l'info :)

Sinon juste un petit truc en plus, dans mon programme pour récupérer les définitions de virus, j'ai rajouté la ligne suivante :

[cpp]
if exist "ivdf_fusebundle_nt_en.zip" del "ivdf_fusebundle_nt_en.zip"
[/cpp]

pour détruire les anciennes définitions de virus avant de récupérer les nouvelles, sinon il va sauver les nouvelles sous "ivdf_fusebundle_nt_en.zip.1" ou un truc comme ça et donc on va accumuler les archives et en plus, le programme dézippera toujours la première archive téléchargée.

Par contre, pour que ça marche dans le temps, j'espère qu'ils ne changeront ni l'url où récupérer les dernières définitions, ni le nom de l'archive.
Et il aurait été bien aussi de savoir quand est-ce qu'ils mettent à jour les définitions de virus, histoire de ne lancer la tâche planifiée que quand c'est nécessaire...

Tchuss, @+, jinpol...
 

bebRito

Grand Maître
Pour l'update, j'améliorerai un poil :

[cpp]SI la récupération se passe bien ALORS
backup de l'ancienne base de définition
écrasement de l'ancienne par la nouvelle
FINSI[/cpp]

Ca te permet de conserver au moins une base valide (même obsolète), tout le temps.
Tu peux encore améliorer en vérifier le retour de la commande copy de la nouvelle base sur l'ancienne pour être sûr d'avoir une base valide.

Tu peux logguer l'ensemble et les consulter de temps en temps pour voir si les mises à jour se passent bien.
 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 122
Messages
6 717 689
Membres
1 586 355
Dernier membre
Chris7miles77
Partager cette page
Haut