Exemple #1
0
def initialiserPG(dump_file,host,port,database,login,password):
    '''
    Cette fonction permet d'initialiser une base de donnée POstgreSQL
    à partir d'un fichier de dump
    '''

    conn = psycopg2.connect(host=host,port=port,database='postgres',user=login,password=password)
    conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
    cursor=conn.cursor()

    cursor.execute("SELECT datdba FROM pg_database WHERE datname=%s",[database])
    base=dictfetchall(cursor)

    cursor.execute("SELECT rolcreatedb,oid FROM pg_roles WHERE rolname=%s",[login])    
    user=dictfetchall(cursor)

    #si la base n'existe pas
    #et si l'utilisateur possede le droit de creation de base
    if ((len(base)==0) and (user[0]['rolcreatedb']==True)):
        error=re.search('[;|<>]&"\'',str(database))

        if error!=None:
            raise Exception("Erreur de paramètre")

        cursor.execute('CREATE DATABASE '+str(database))


    cursor.close()

    if len(base)==1:
        conn = psycopg2.connect(host=host,port=port,database=database,user=login,password=password)
        conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
        cursor=conn.cursor()
        cursor.execute("SELECT tablename FROM pg_tables WHERE tableowner=%s AND schemaname='public'",[login])
        liste=dictfetchall(cursor)

        for table in liste:
            cursor.execute("DROP TABLE IF EXISTS "+str(table['tablename'])+" CASCADE")

    
    os.putenv('PGPASSWORD',password)

    #On recupère l'adresse IP si l'utilisateur nous envoie le hostname
    try:
        host=valideIP(host)
    except:
        host=getIP(host)

    subprocess.check_output('psql -h '+desatanize(host)+' -p '+str(port)+' -d '+desatanize(database)+' -U '+desatanize(login)+' < '+dump_file, shell=True)
Exemple #2
0
def initialiserPG(dump_file, host, port, database, login, password):
    '''
    Cette fonction permet d'initialiser une base de donnée POstgreSQL
    à partir d'un fichier de dump
    '''

    conn = psycopg2.connect(host=host,
                            port=port,
                            database='postgres',
                            user=login,
                            password=password)
    conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
    cursor = conn.cursor()

    cursor.execute("SELECT datdba FROM pg_database WHERE datname=%s",
                   [database])
    base = dictfetchall(cursor)

    cursor.execute("SELECT rolcreatedb,oid FROM pg_roles WHERE rolname=%s",
                   [login])
    user = dictfetchall(cursor)

    #si la base n'existe pas
    #et si l'utilisateur possede le droit de creation de base
    if ((len(base) == 0) and (user[0]['rolcreatedb'] == True)):
        error = re.search('[;|<>]&"\'', str(database))

        if error != None:
            raise Exception("Erreur de paramètre")

        cursor.execute('CREATE DATABASE ' + str(database))

    cursor.close()

    if len(base) == 1:
        conn = psycopg2.connect(host=host,
                                port=port,
                                database=database,
                                user=login,
                                password=password)
        conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
        cursor = conn.cursor()
        cursor.execute(
            "SELECT tablename FROM pg_tables WHERE tableowner=%s AND schemaname='public'",
            [login])
        liste = dictfetchall(cursor)

        for table in liste:
            cursor.execute("DROP TABLE IF EXISTS " + str(table['tablename']) +
                           " CASCADE")

    os.putenv('PGPASSWORD', password)

    #On recupère l'adresse IP si l'utilisateur nous envoie le hostname
    try:
        host = valideIP(host)
    except:
        host = getIP(host)

    subprocess.check_output('psql -h ' + desatanize(host) + ' -p ' +
                            str(port) + ' -d ' + desatanize(database) +
                            ' -U ' + desatanize(login) + ' < ' + dump_file,
                            shell=True)
Exemple #3
0
def parserNessusCsv(fichierCSV,scans_status_id,modeStrict=False):
    '''
    Importe le rapport CSV d'un scan Nessus dans une base SQL
    
    Le mode restrictif permet de générer une erreur en cas de decouverte
    d'une vulnerabilite sur un service non présent en base
    '''

    csvfile=open(fichierCSV, 'r')
    spamreader = csv.reader(csvfile, delimiter=',')
    cursor=connection.cursor()

    cursor.execute('SELECT date_lancement FROM scans_status WHERE id=%s LIMIT 1',[scans_status_id])
    rep=dictfetchall(cursor)
    date_scan=rep[0]['date_lancement']

    #Gestion du mode restrict
    dict_raise={'ip':[],'ports_tcp':[],'ports_udp':[]}

    dict_vulns_hote={}
    entete=True

    #liste hotes existant
    cursor.execute('SELECT ip FROM hotes')
    dict_hotes_existant=dictfetchall(cursor)
    tableau_hotes_existant=[]
    dict_dns={}

    for elem in dict_hotes_existant:
        tableau_hotes_existant.append(elem['ip'])

    
    cve_a_interroger=[]
    
    for row in spamreader:
        #Pour ne pas recuperer la ligne dentete
        if entete==True:
            entete=False
            continue

        plugin_id=int(row[0])
        cve=str(row[1])
        cvss=str(row[2])
        criticite=str(row[3])
        protocole=str(row[5])
        port=str(row[6])
        nom=str(row[7])
        synopsis=str(row[8])
        description=str(row[9])
        solution=str(row[10])        
        a_lire=str(row[11])
        retour_plugin=str(row[12])

        if criticite =='None':
            criticite='Info'
        

        cursor.execute('SELECT id FROM vulnerabilitees WHERE plugin_id=%s AND criticite=%s AND nom=%s AND description=%s AND synopsis=%s LIMIT 1',[plugin_id,criticite,nom,description,synopsis])
        nb=dictfetchall(cursor)

        if len(nb)==0:
            #on ajoute la vulnerabilites a la base de donnee
            cursor.execute('INSERT INTO vulnerabilitees (plugin_id,nom,description,synopsis,solution,infos_complementaires,criticite) VALUES (%s,%s,%s,%s,%s,%s,%s)',[plugin_id,nom,description,synopsis,solution,a_lire,criticite])


        
        #On verifie s'il y a eu une MAJ au niveau de la solution ou des liens
        else:    

            cursor.execute('SELECT solution,infos_complementaires FROM vulnerabilitees WHERE id=%s LIMIT 1',[nb[0]['id']])
            info_scan=dictfetchall(cursor)

            if info_scan[0]['solution']!=solution:
                cursor.execute('UPDATE vulnerabilitees SET solution=%s WHERE id=%s',[solution,nb[0]['id']])

            if info_scan[0]['infos_complementaires']!=a_lire:
                cursor.execute('UPDATE vulnerabilitees SET infos_complementaires=%s WHERE id=%s',[a_lire,nb[0]['id']])



        #On recupere l'id de la vulnerabilite recemment ajoute ou correspondant
        cursor.execute('SELECT id FROM vulnerabilitees WHERE plugin_id=%s AND criticite=%s AND nom=%s AND description=%s AND synopsis=%s AND solution=%s AND infos_complementaires=%s',[plugin_id,criticite,nom,description,synopsis,solution,a_lire])
        temp=dictfetchall(cursor)
        id_vuln=temp[0]['id']


        #Gestion des références associées à la vulnérabilitée rencontrée (CVE)        
        for reference in cve.split(','):
            if reference !='':
                cursor.execute('SELECT id FROM refs WHERE nom=%s',[reference])
                temp=dictfetchall(cursor)

                #On ajoute la reference à un tableau si elle n'y est pas présente
                #A la fin de l'importation, chaque reference sera interrogé sur le site (cvedetails)
                # afin de récupérer diverse informations (facilité, impact sur la dispo,confidentialité,...)
                if reference not in cve_a_interroger:
                    cve_a_interroger.append(reference)

                #Si la reference n'existe pas on la cree
                if len(temp)==0:
                    cursor.execute('INSERT INTO refs (nom) VALUES(%s)',[reference])
                    cursor.execute('SELECT id FROM refs WHERE nom=%s',[reference])
                    temp=dictfetchall(cursor)
 
                id_ref=temp[0]['id']
    
                #On verifie si la vulnerabilite possede déjà une association avec la référence
                cursor.execute('SELECT vuln_id,ref_id FROM vulns_refs WHERE vuln_id=%s AND ref_id=%s',[str(id_vuln),str(id_ref)])
                nb=dictfetchall(cursor)
                
                if len(nb)==0:
                    cursor.execute('INSERT INTO vulns_refs (vuln_id,ref_id) VALUES (%s,%s)',[id_vuln,id_ref])
                
        
        #On parcourt l'ensemble des hotes affectes par la vulnerabilite
        #afin d'ajouter, si besoin, une correspondance dans la table vuln_hote_service
        
        for hote in str(row[4]).split(','):
            #Il arrive que Nessus mette le nom de la machine au lieu de son ip
            #Dans ce cas, on réalise une résolution DNS 
            #Le dictionnaire permet d'économiser le nombre de requêtes effectuées
            if re.search('([0-9]{1,3}\.){3}([0-9]{1,3})',str(hote))==None:
                if dict_dns.has_key(str(hote)):
                    hote=dict_dns[str(hote)]
                else:
                    try:
                        hostname=str(hote)
                        hote=getIP(hostname)
                        dict_dns[hostname]=hote
                    except:
                        continue
                             

            #On verifie que notre dictionnaire de travail contient une entree pour l'hote scanner
            #si ce n'est pas le cas on la cree avec comme valeur de cle la liste des vuln_id qu'il possede
            if dict_vulns_hote.has_key(hote)==False:
                cursor.execute('SELECT id_vuln,id_service FROM vuln_hote_service WHERE ip_hote=%s AND date_correction is NULL', [hote])
                rep=dictfetchall(cursor)
                tableau_vuln_service=[]

                for i in range(len(rep)):
                         tableau_vuln_service.append(rep[i])


                dict_vulns_hote[hote]=tableau_vuln_service


            #On selectionne l'id du service correpondant 
            cursor.execute('SELECT id FROM services WHERE ip_hote=%s AND protocole=%s AND port=%s AND date_retrait is NULL', [hote,protocole,port])
            rep=dictfetchall(cursor)


            #Dans le cas où le service n'est pas présent en base, on indique dans un dictionnaire le port correspondant
            #Une fois le CSV parcouru, on lévera une alerte indiquant les ports à scanner avec Nmap
            #Rappel: le modeStrict sur "OFF" permet de ne pas lever d'erreur en n'important pas la vulnérabilitée (mode dégradé)
            if len(rep)==0:
                #Cas d'une vulnerabilite systeme:
                if port=='0' and criticite!='Info':
                    cursor.execute("SELECT id  FROM services WHERE ip_hote=%s AND port=0 AND nom='OS' AND type='OS'",[hote])
                    rep=dictfetchall(cursor)

                    if len(rep)==0:
                        cursor.execute("INSERT INTO services (protocole,port,etat,nom,type,ip_hote,date_ajout) VALUES ('tcp',0,'open','OS','OS',%s,%s)",[hote,date_scan])

                        cursor.execute("SELECT id FROM services WHERE ip_hote=%s AND port=0 AND nom='OS' AND type='OS'", [hote])
                        rep=dictfetchall(cursor)


                elif modeStrict==True and str(port)!='0':
                    if (str(hote) not in dict_raise['ip']):
                        dict_raise['ip'].append(str(hote))

                    if (protocole=='udp' and (port not in dict_raise['ports_udp'])):
                        dict_raise['ports_udp'].append(str(port))

                    if (protocole=='tcp' and (port not in dict_raise['ports_tcp'])):
                        dict_raise['ports_tcp'].append(str(port))
                    continue
                else:
                    continue

            if port=="0":
                id_service=rep[0]['id']
                cursor.execute('SELECT id_vuln FROM vuln_hote_service WHERE ip_hote=%s AND id_service=%s AND id_vuln=%s AND date_correction is NULL',[hote,id_service,id_vuln])
                temp=dictfetchall(cursor)

            else:
                id_service=rep[0]['id']

                #On verifie si la table vuln_hote_service contient une entree pour le trio (service,ip,vuln)
                cursor.execute('SELECT id_vuln FROM vuln_hote_service WHERE ip_hote=%s AND id_service=%s AND id_vuln=%s AND date_correction is NULL',[hote,id_service,id_vuln])
                temp=dictfetchall(cursor)

            # 1)Il s'agit alors d'une nouvelle vulnérabilitée 
            if len(temp)==0:
                cursor.execute('INSERT INTO vuln_hote_service (ip_hote,id_service,id_vuln,date_detection,retour_vuln) VALUES (%s,%s,%s,%s,%s)',[hote,id_service,id_vuln,date_scan,retour_plugin])


            # 2) la vulnérabilitée était déjà présente en base (rien de nouveau donc)
            #on supprime donc l'entrée de notre dictionnaire de travail
            #Rappel dict_vulns_hote={'host1':[liste_vulnerabilitees]}
            else: 
                dict_a_supprimer={}
                dict_a_supprimer['id_vuln']=id_vuln
                dict_a_supprimer['id_service']=id_service
                try:
                    dict_vulns_hote[hote].remove(dict_a_supprimer)
                except ValueError:
                    #Il arrive que Nessus remonte la meme vulnerabilite pour un meme service mais avec 
                    #une syntaxe de sortie de plugin légérement différente (mais avec une information identique)
                    #dans ce cas note tableau_vuln initial ne contiendra qu'une iteration du couple service/vuln
                    #alors que le rapport en contient plusieurs, d'où l'erreur
                    pass


    for reference in cve_a_interroger:
        param=get_CVE_details(str(reference))
        cursor.execute("SELECT * FROM refs WHERE nom=%s",[str(reference)])
        temp=dictfetchall(cursor)

        if len(temp)==0:
            cursor.execute('''INSERT INTO refs (nom,cvss_score,confidentialite,integrite,disponibilite,complexite,authentification,type,acces_obtention) 
                            VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)''',
                            [reference,param['cvss_score'],param['confidentialite'],param['integrite'],param['disponibilite'],
                            param['complexite'],param['authentification'],param['type'],param['acces_obtention']])

        else:
            cursor.execute('''UPDATE refs
                            SET cvss_score=%s,
                            confidentialite=%s,
                            integrite=%s,
                            disponibilite=%s,
                            complexite=%s,
                            authentification=%s,
                            type=%s,
                            acces_obtention=%s WHERE nom=%s''',[param['cvss_score'],param['confidentialite'],param['integrite'],param['disponibilite'],
                                                      param['complexite'],param['authentification'],param['type'],param['acces_obtention'],reference])


    if modeStrict==True:
        if len(dict_raise['ip'])>0:
            raise ErreurScanNessus('Service(s) introuvable(s)',dict_raise)


    #Pour finir, on parcourt le dictionnaire de travail
    #Les vuln_id restantes correspondent à des vulnerabilitées qui ont été corrigées
    # On met donc a jour la table vuln_hote_service en fonction
    for hote in dict_vulns_hote.keys():
        for dic in dict_vulns_hote[hote]:
            cursor.execute('UPDATE vuln_hote_service SET date_correction=%s WHERE ip_hote=%s AND id_vuln=%s AND id_service=%s',[date_scan,hote,dic['id_vuln'],dic['id_service']])



        cursor.execute('SELECT count(id_vuln) FROM vuln_hote_service WHERE ip_hote=%s AND date_correction IS NULL',[hote])
        nb=dictfetchall(cursor)
        nb_vuln=nb[0]['count']

        cursor.execute('UPDATE hotes SET nb_vulnerabilites=%s WHERE ip=%s',[nb_vuln,hote])

    csvfile.close()