File size: 9,792 Bytes
89c8ad5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import requests
import re

class SecurityAuditAnalyzer:
    def __init__(self, api_key, model="deepseek/deepseek-chat:free", api_url="https://openrouter.ai/api/v1/chat/completions"):
        self.api_url = api_url
        self.api_key = api_key
        self.model = model
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}",
            "HTTP-Referer": "https://security-audit-api.com",
            "X-Title": "Security Audit API"
        }

    def analyze_responses(self, responses):
        """Analyse les réponses d'un audit et retourne une évaluation structurée."""
        prompt = self._build_prompt(responses)
        payload = {
            "model": self.model,
            "messages": [
                {"role": "system", "content": self._get_system_prompt()},
                {"role": "user", "content": prompt}
            ],
            "temperature": 0.5
        }
        try:
            response = requests.post(self.api_url, headers=self.headers, json=payload)
            response.raise_for_status()
            result = response.json()
            analysis = result['choices'][0]['message']['content']
            return self._parse_analysis(analysis)
        except requests.RequestException as e:
            return {
                "error": str(e),
                "status": "error",
                "evaluation": {"score": 0, "level": "Inconnu"},
                "strengths": [], "weaknesses": [], "recommendations": [],
                "summary": "Une erreur s'est produite lors de l'analyse."
            }

    def _get_system_prompt(self):
        return """Vous êtes un expert en cybersécurité spécialisé dans l'analyse des audits de sécurité.
Votre tâche est d'analyser les réponses fournies à un audit de sécurité et de produire une évaluation détaillée.

Adaptez votre analyse au type d'audit fourni (audit complet ou audit spécifique à un domaine).
Identifiez automatiquement le domaine spécifique de l'audit si les questions sont concentrées sur un sujet particulier 
(ex: sécurité des réseaux, politique de mots de passe, gestion des données, etc.).

Structurez toujours votre réponse avec les balises suivantes:
<AUDIT_TYPE>Type de l'audit identifié</AUDIT_TYPE>
<EVALUATION>Score sur 10 et niveau (Critique, Faible, Moyen, Bon, Excellent)</EVALUATION>
<POINTS_FORTS>Liste des points forts avec leur niveau d'importance (Fort, Moyen, Faible)</POINTS_FORTS>
<FAILLES>Liste des vulnérabilités identifiées avec leur niveau de risque (Critique, Élevé, Moyen, Faible)</FAILLES>
<RECOMMANDATIONS>Liste des recommandations détaillées pour chaque faille identifiée</RECOMMANDATIONS>
<RESUME>Résumé concis de la situation générale de sécurité et prochaines étapes prioritaires</RESUME>
"""

    def _build_prompt(self, responses):
        audit_type = self._detect_audit_type(responses)
        prompt = f"Type d'audit détecté: {audit_type}\n\n"
        prompt += "Voici les réponses à un audit de sécurité numérique:\n\n"
        for question, answer in responses.items():
            prompt += f"Question: {question}\nRéponse: {answer}\n\n"
        prompt += """
Analysez ces réponses et fournissez:
1. Le type d'audit que vous avez identifié
2. Une évaluation globale du niveau de sécurité (score sur 10 et niveau: Critique, Faible, Moyen, Bon, Excellent)
3. Les points forts de la sécurité actuelle (listez-les avec leur importance: Fort, Moyen, Faible)
4. Les vulnérabilités identifiées (listez-les avec leur niveau de risque: Critique, Élevé, Moyen, Faible)
5. Des recommandations détaillées pour résoudre chaque vulnérabilité
6. Un résumé général de la situation actuelle et prochaines étapes prioritaires

Formatez votre réponse avec les sections clairement délimitées par les balises spécifiées.
"""
        return prompt

    def _detect_audit_type(self, responses):
        domains = {
            "Politique de mots de passe": ["mot de passe", "password", "authentification", "connexion"],
            "Sécurité des réseaux": ["réseau", "network", "firewall", "pare-feu", "vpn", "wifi", "routeur"],
            "Gestion des accès": ["accès", "access", "droits", "permission", "privilege", "utilisateur", "user"],
            "Protection des données": ["donnée", "data", "chiffrement", "encryption", "backup", "sauvegarde"],
            "Sécurité physique": ["physique", "physical", "bâtiment", "building", "local", "vol", "theft"],
            "Formation et sensibilisation": ["formation", "training", "sensibilisation", "awareness", "employé"],
            "Gestion des incidents": ["incident", "crise", "réponse", "response", "attaque", "breach"],
            "Conformité réglementaire": ["rgpd", "gdpr", "conformité", "compliance", "régulation", "legal"]
        }
        domain_counts = {domain: 0 for domain in domains}
        for question in responses.keys():
            question_lower = question.lower()
            for domain, keywords in domains.items():
                for keyword in keywords:
                    if keyword.lower() in question_lower:
                        domain_counts[domain] += 1
        main_domains = sorted(domain_counts.items(), key=lambda x: x[1], reverse=True)
        if len(main_domains) > 3 and main_domains[0][1] > 0 and main_domains[1][1] > 0 and main_domains[2][1] > 0:
            return "Audit de sécurité complet"
        elif main_domains[0][1] > 0:
            return f"Audit spécifique: {main_domains[0][0]}"
        else:
            return "Audit de sécurité général"

    def _parse_analysis(self, analysis):
        result = {
            "status": "success",
            "audit_type": self._extract_between(analysis, "<AUDIT_TYPE>", "</AUDIT_TYPE>"),
            "evaluation": {},
            "strengths": [],
            "weaknesses": [],
            "recommendations": [],
            "summary": self._extract_between(analysis, "<RESUME>", "</RESUME>").strip()
        }
        eval_text = self._extract_between(analysis, "<EVALUATION>", "</EVALUATION>")
        score_match = re.search(r'(\d+)[\/\s]*10', eval_text)
        result["evaluation"]["score"] = int(score_match.group(1)) if score_match else 0

        level_keywords = ["Critique", "Faible", "Moyen", "Bon", "Excellent"]
        for keyword in level_keywords:
            if keyword.lower() in eval_text.lower():
                result["evaluation"]["level"] = keyword
                break
        else:
            result["evaluation"]["level"] = "Non spécifié"

        strengths_text = self._extract_between(analysis, "<POINTS_FORTS>", "</POINTS_FORTS>")
        result["strengths"] = self._extract_rated_items(strengths_text, ["Fort", "Moyen", "Faible"])

        weaknesses_text = self._extract_between(analysis, "<FAILLES>", "</FAILLES>")
        result["weaknesses"] = self._extract_rated_items(weaknesses_text, ["Critique", "Élevé", "Moyen", "Faible"])

        recommendations_text = self._extract_between(analysis, "<RECOMMANDATIONS>", "</RECOMMANDATIONS>")
        result["recommendations"] = self._extract_list_items(recommendations_text)

        if not result["audit_type"]:
            if "audit complet" in analysis.lower():
                result["audit_type"] = "Audit de sécurité complet"
            elif "audit spécifique" in analysis.lower():
                specific_match = re.search(r'audit spécifique[:\s]*([\w\s]+)', analysis.lower())
                if specific_match:
                    result["audit_type"] = f"Audit spécifique: {specific_match.group(1).strip().capitalize()}"
                else:
                    result["audit_type"] = "Audit spécifique"
            else:
                result["audit_type"] = "Audit de sécurité général"

        return result

    def _extract_between(self, text, start_marker, end_marker):
        try:
            start = text.index(start_marker) + len(start_marker)
            end = text.index(end_marker, start)
            return text[start:end].strip()
        except ValueError:
            return ""

    def _extract_list_items(self, text):
        items = []
        for line in text.split('\n'):
            line = line.strip()
            if line.startswith(('- ', '• ', '* ', '1. ', '2. ')) and len(line) > 2:
                items.append(line[2:].strip())
            elif line and not any(header in line.lower() for header in ["points", "failles", "recommandations"]):
                items.append(line)
        return [item for item in items if item]

    def _extract_rated_items(self, text, ratings):
        items = []
        for line in text.split('\n'):
            line = line.strip()
            if not line:
                continue
            item = {"text": line, "rating": None}
            for rating in ratings:
                if f"{rating}:" in line.lower() or f"{rating} :" in line.lower():
                    parts = re.split(f"{rating}:", line, 1, flags=re.IGNORECASE)
                    if len(parts) > 1:
                        item["text"] = parts[1].strip()
                        item["rating"] = rating
                        break
                if f"({rating})" in line.lower() or f"[{rating}]" in line.lower():
                    item["text"] = re.sub(rf"[\(\[]?{rating}[\)\]]?", "", line, flags=re.IGNORECASE).strip()
                    item["rating"] = rating
                    break
            if item["rating"] is None and line.startswith(('- ', '• ', '* ')) and len(line) > 2:
                item["text"] = line[2:].strip()
            if item["text"] and not any(header in item["text"].lower() for header in ["points forts", "failles"]):
                items.append(item)
        return items