Je me suis mis au Perl il y a pas trop longtemps pour un certain projet. En effet, j'ai souhaité installer le scanner de vulnérabilité OpenVAS sur un serveur, et automatiser le lancement des scan et le traitement des rapports. Tout ce passe bien grâce à un module Perl. Cependant, lorsque je souhaite traiter le rapport, j'ai l'impression que Perl me 'coupe' une partie du rapport.
Une petit explication s'impose :
Lorsque je lui demande un rapport, OpenVAS me renvoie un mélange de XML et HTML ( en base-64 sinon ce serait pas drole ! ). Je mets donc ce message dans une variable, j'extrais le rapport HTML du XML et je le décode grâce a la fonction decode_base64(). Et la c'est le drame, mon fichier HTML est incomplet : il est tout simplement coupé. Je me demandais si Perl tronque les variable lorsque celle-ci sont trop longue, et si oui, comment l'en empêcher ?
Si vous voulez je peux vous fournir la partie de code pour que ce soit plus clair.
Oui quand je parle de variable dans ce cas la c'est sensé être une chaîne de caractère ! Et non je ne pense pas qu'il y ai un problème de parsing car j'ai pu comparer le code que j'obtient avant et après le parsing et j'obtient bien le fichier html complet encodé en base 64. En revanche lorsque je le décode, celui-ci est tronqué...
Donc soit c'est un problème de taille, soit c'est carrément OpenVas qui me donne un rapport tronqué. Mais ça se serait un peu plus embêtant...
C'est ce que je pensais faire, cependant, lorsque je demande au serveur le rapport, lui il m'envoie tout d'un coup ! :/ Et puis si j'essaie de couper le rapport avant de l'avoir décodé ca risque de devenir délicat a décoder après non ?
Le retour du serveur, tu l'enregistres comme ça, non ?
my $content = `retour_du_serveur`;
Essaie de l'enregistrer directement dans une liste, t'as rien à perdre.
my @content = `retour_du_serveur`;
J'ai jamais testé decode_base64(), mais de la manière dont je le perçois, si tu découpes la variable et la réassembles dans le même ordre, t'obtiendras le même résultat. Après, je suis pas très formé au traitement binaire.
(Évidemment, il faudra décoder toute la variable à la fois, donc réassembler le contenu avant de le décoder, j'ai tourné ma phrase bizarrement.)
use strict;
use warnings;
use MIME::Base64;
use lib "d:/sophie/lib";
use OpenVAS::OMP;
use Std;
use Try::Tiny;
sub estFinis ( $ $ $ )
{
#Fonction qui regarde si les scans sont terminés.
my $compteur = 0;
my $finis = 1;
my $task_id = $_[0];
my $tableau_ip = $_[1];
my $omp = $_[2];
foreach my $task (@{$task_id})
{
my @donne = $omp->commandXML('<get_tasks id="'.$task.'"/>',1); #Envoie la question au serveur OpenVas
my @texte = split /status/, $donne[0];
if ( $texte[5] ne ">Done</") #Vérification de la terminaison du scanner
{
$finis = 0;
}
$compteur += 1;
}
return $finis;
}
sub editionRapport ( $ $ $ $ $ )
{
#Génère, décode et enregistre les rapports des scans lancé. Le fichier sort sous format HTML et daté.
my $i = 0;
my $tableau_report = $_[0];
my $tableau_task = $_[1];
my $tableau_target = $_[2];
my $tableau_ip = $_[3];
my $omp = $_[4];
my $time = localtime;
my $loop = 0;
my $filename = "C:\\Users\\ydeq\\rapport.html";
foreach my $report_id (@{$tableau_report})
{
my @report = $omp->commandXML('<get_reports report_id="'.$report_id.'" format_id="6c248850-1f62-11e1-b082-406186ea4fc5"/>'); #Demande le rapport au serveur OpenVas
print debug_value(@report);
my $test_fichier;
if ( $report[0] =~ m!</report_format>(.+)! )
{
print decode_base64($1);
if($loop == 0)
{
open(FICHIER, ">", $filename);
my @rapport = split /<body style="background-color: #FFFFFF; margin: 0px; font: small Verdana, sans-serif; font-size: 12px; color: #1A1A1A;">/, decode_base64($1); #Décode le rapport car OpenVas nous le fournit en base64.
my @rapport_bis = split m!</body>!, $rapport[1];
$rapport[1] = '<div id=accordeon><h3><a href="#">'.$tableau_ip->[$i].'</a></h3><div>'.$rapport_bis[0]."</div>";
print FICHIER join ('<body style="background-color: #FFFFFF; margin: 0px; font: small Verdana, sans-serif; font-size: 12px; color: #1A1A1A;">', @rapport);
$loop += 1;
}
else
{
open(FICHIER, ">>", $filename);
my @rapport = split /<body style="background-color: #FFFFFF; margin: 0px; font: small Verdana, sans-serif; font-size: 12px; color: #1A1A1A;">/, decode_base64($1); #Décode le rapport car OpenVas nous le fournit en base64.
my @rapport_bis = split m!</body>!, $rapport[1];
$rapport[1] = '<h3><a href="#">'.$tableau_ip->[$i].'</a></h3><div>'.$rapport_bis[0]."</div>";
print FICHIER $rapport[1];
}
}
$omp->commandXML('<delete_task task_id="'.$tableau_task->[$i].'"/>'); #On efface les targets et tasks du serveur pour éviter des conflits lors du prochain lancement
$omp->commandXML('<delete_target target_id="'.$tableau_target->[$i].'"/>');
$i++;
close FICHIER;
}
open (FICHIER, ">>", $filename);
print FICHIER "</div></body></html>";
print "L'analyse des différents IP est terminée.";
}
sub attenteScanner ( $ $ $ )
{
# Régule les demandes de rapports aux serveurs OpenVas afin de ne pas ralentir le scan.
my $tableau_task = $_[0];
my $tableau_ip = $_[1];
my $omp = $_[2];
print " Scans en cours \n";
while ( estFinis( $tableau_task , $tableau_ip, $omp) == 0 )
{
my $tempo;
for ( $tempo=0; $tempo<60; $tempo++) #On verifie la terminaison des scanner qu'une fois toutes les 600 secondes
{
sleep (10);
print "#"; #Permet de vérifié si le programme n'a pas planté...
}
print "\n";
print ( " Nouvelle vérification ! \n");
}
print " Scans terminés\n ";
}
my $omp = OpenVAS::OMP->new(
host => 'mettre l'ip de la machine faisant tourner openvas',
ssl_verify => 0,
username => 'mettre son identifiant',
password => 'mettre son mot de passe',
port => 9390,
); #Initialisation de notre objet OpenVas
$omp->commandXML('<sync_feed/>'); #Synchronisation des plugins OpenVas
sleep(30);
my $filename = "C:\\Users\\ydeq\\addresse_ip.txt"; #Document contenant la liste des ip à scanner
my @tableau_ip;
my @tableau_target;
my @tableau_task;
my @tableau_report;
my $i = 0;
my $test_ip;
my $continuer = 1;
my $compteur = 0;
open ( FICHIER, '<', $filename ) or die "Impossible d'ouvrir le fichier $filename en lecture";
#while ( $continuer == 1 )
#{
while ( my $ip = <FICHIER> )
{
chomp ( $ip );
$tableau_ip[$i] = $ip;
my @target = $omp->commandXML('<create_target><name>'.$ip.'</name><hosts>'.$ip.'</hosts><comment>__Automatic_Generated_Target_</comment></create_target>',1); #Demande à OpenVas de créer une cible
my $target_id = $target[0];
my $trouve_ip = 1; #Type : Booléen. Permet d'assurer d'effectuer des taches sur des targets bien définis dans openVas ie, qu'on arrive bien à récuperer leur ID unique.
if ( ( $target_id =~ /id="(.+)"/ ) && ( $ip ne "0.0.0.0" ) ) #On récupère l'identifiant unique de cette cible
{
print " On traite l'ip : $ip \n";
$target_id = $1;
$tableau_target[$i] = $target_id;
}
elsif ( $ip ne "0.0.0.0" ) #Si la cible a été ajouté avant, il faut chercher dans les fichiers de configurations d'OpenVas la clé primaire de la target associé à l'IP sélectionné.
{
print " On traite l'ip : $ip \n";
my $test = 0;
my @donne = $omp->commandXML('<get_targets/>',1);#On cherche l'identifiant de la cible dans le fichier de configuration XML d'OpenVas.
my @texte = split /hosts/, $donne[0];
my @texte2;
my $compteur = 0;
foreach my $elt ( @texte )
{
if ( $elt eq ">$ip</")
{
@texte2 = split /"/, $texte[$compteur + 5];
$target_id = $texte2[9];
$tableau_target[$i] = $target_id;
$test = 1;
}
$compteur += 1;
}
if ( $test == 0 )
{
print "L'IP $ip n'a pas pu être scanné.";
$trouve_ip = 0;
}
}
else
{
$trouve_ip = 0;
$continuer = 0;
}
if ( $trouve_ip == 1 ) #Si on a pu déterminer la clé primaire de notre target, alors on peut commencer à lancer les scans.
{
my @task = $omp->commandXML('<create_task><name>'.$ip.'</name><config id="daba56c8-73ec-11df-a475-002264764cea"/><target id="'.$target_id.'"/></create_task>', 1); #Création d'une nouvelle tache
my $task_id = $task[0];
if ( $task_id =~ /id="(.+)"/ ) #Récupération de son identifiant unique
{
$task_id = $1;
my @scan = $omp->commandXML('<start_task task_id="'.$task_id.'"/>',1);
my $report_id = $scan[0];
$tableau_task[$i] = $task_id;
if ( $report_id =~ m!<report_id>(.+)</report_id>!) #On détermine l'identifiant unique du rapport.
{
$tableau_report[$i] = $1;
}
}
$i ++;
}
$compteur += 1;
if ( $compteur == 5 )
{
attenteScanner ( \@tableau_task, \@tableau_ip, $omp );
$compteur = 0;
}
}
close FICHIER;
attenteScanner ( \@tableau_task, \@tableau_ip, $omp );
editionRapport ( \@tableau_report, \@tableau_task, \@tableau_target, \@tableau_ip, $omp );
Voila le code ! Il faut cependant installer openvas pour le faire tourner ! Et c'est la ligne 45 qui pose problemùe dans la fonction edition_rapports
Pas eu le temps de tester en bonnes conditions, vu que j'ai pas exactement le même système que toi (Je crois que tu travailles sous Windows, ça peut aussi fausser le test), donc mon seul conseil serait d'utiliser une librairie pour parser le xml obtenu ligne 45, au lieu de le faire toi-même, pour voir si ça change quelque chose.
Bon ! Finalement j'ai reussi à régler ce problème ! Ce n'ets pas Perl qui tronque la variable mais le module qui est buggé... Du coup, vu que je correspond avec une machine Linux par SSH depuis Windows, j'ai utilisé PLINK et la fonction `` de Perl qui permet de transmettre un message au PowerShell !
Variable tronqué en Perl
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Voila le code !