File size: 7,454 Bytes
ee79fef
 
 
 
 
 
bd30f76
ee79fef
 
 
 
 
3535c75
ee79fef
 
6d857a0
ee79fef
 
 
7e33bcd
 
ee79fef
 
 
 
 
 
 
 
 
6d857a0
ee79fef
3535c75
bd30f76
3535c75
bd30f76
 
 
 
3535c75
bd30f76
 
 
 
3535c75
bd30f76
 
 
3535c75
bd30f76
 
 
 
3535c75
bd30f76
 
 
 
3535c75
bd30f76
 
ee79fef
 
 
3535c75
bd30f76
ee79fef
 
3535c75
 
ee79fef
bd30f76
ee79fef
3535c75
ee79fef
 
 
bd30f76
ee79fef
3535c75
ee79fef
 
 
bd30f76
ee79fef
3535c75
ee79fef
 
 
32af315
ee79fef
3535c75
bd30f76
ee79fef
 
 
7e33bcd
ee79fef
3535c75
ee79fef
bd30f76
ee79fef
 
bd30f76
ee79fef
 
bd30f76
ee79fef
 
 
 
3535c75
bd30f76
 
ee79fef
7e33bcd
ee79fef
 
 
3535c75
bd30f76
3535c75
bd30f76
 
 
3535c75
bd30f76
 
 
3535c75
bd30f76
 
 
 
ee79fef
 
 
 
3535c75
 
bd30f76
ee79fef
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
import gradio as gr
import re

def extract_email(text):
    """Вытаскивает email"""
    match = re.search(r'[\w\.-]+@[\w\.-]+', text)
    return match.group(0) if match else None 

def analyze_email(headers, body):
    score = 0
    findings = []
    
    # анализ самих заголовков
    if re.search(r"SPF.*FAIL", headers, re.IGNORECASE):
        score += 10
        findings.append("<li>SPF FAIL: Сервер не разрешен для этого домена (+10)</li>")
    
    if re.search(r"DKIM.*FAIL", headers, re.IGNORECASE):
        score += 10
        findings.append("<li>DKIM FAIL: Подпись DKIM фальшивая (+10)</li>")

    from_match = re.search(r"^From:(.*)", headers, re.MULTILINE | re.IGNORECASE)
    return_match = re.search(r"^Return-Path:(.*)", headers, re.MULTILINE | re.IGNORECASE)
    
    if from_match and return_match:
        from_email = extract_email(from_match.group(1))
        return_email = extract_email(return_match.group(1))
        
        if from_email and return_email and from_email != return_email:
            score += 5
            findings.append(f"<li>Отправитель ({from_email}) не совпадает с Return-Path ({return_email}) (+5)</li>")
    
    # анализ самого текста
    
    # словарь срочности и запугивания
    keywords_urgency = [
        "заблокирован", "срочно", "удаление", "ограничен", "suspension", "urgent", "immediate", 
        "остановлен", "удален", "удалён", "удалена", "остановлена", "ограничена", "заморожена", 
        "заморожен", "suspended",
        # добавлено из тз учителя:
        "немедленно", "аккаунт будет заблокирован", "блокировка счета", "блокировка аккаунта", 
        "служба безопасности" 
    ]
    
    # словарь требуемых действий
    keywords_action = [
        "verify", "update", "login", "вход", "пароль", "password", "аутентификация", 
        "authentication", "войдите", "требуется", "confirm", "confirmation",
        # добавлено из тз учителя:
        "подтвердите", "подтвердить", "данные карты", "конфиденциальная информация", 
        "подтвердите личность", "перевод средств", "поддержка банка"
    ]
    
    # словарь жадности 
    keywords_greed = [
        "freespin", "фриспин", "casino", "казино", "lottery", "1xbet", "лотерея", "бонус", 
        "распродажа", "бесплатно", "раздача", "подарок", "гифт", "giveaway", "выигрыш", 
        "скидка", "prize", "gift", "win", "победитель", "winner", "поздравляем", "congratulations",
        # Добавлено из тз учителя:
        "вы выиграли", "приз", "выбран случайным образом"
    ]
    
    body_lower = body.lower()

    # проверка на срочность
    found_urgency = False
    for word in keywords_urgency:
        if word in body_lower:
            # чтобы не начислять баллы за каждое слово много раз можно ограничить
            # но в рамках задания суммируем
            score += 2
            findings.append(f"<li>Психологическое давление: '{word}' (+2)</li>")

    # проверка на действия
    for word in keywords_action:
        if word in body_lower:
            score += 1
            findings.append(f"<li>Запрос данных/действий: '{word}' (+1)</li>")

    # проверка на жадность
    for word in keywords_greed:
        if word in body_lower:
            score += 2
            findings.append(f"<li>Приманка/Выигрыш: '{word}' (+2)</li>")

    # анализ самих ссылок
    ip_links = re.findall(r'https?://(?:[0-9]{1,3}\.){3}[0-9]{1,3}', body)
    if ip_links:
        score += 5
        findings.append(f"<li>IP в ссылке: ({ip_links[0]}) (+5)</li>")

    suspicious_tlds = [".xyz", ".top", ".info", ".club", ".shop", ".site"] # добавил .shop из тз учителя
    for tld in suspicious_tlds:
        if tld in body_lower:
            if re.search(rf"\w{tld}/\w", body_lower) or re.search(rf"\w{tld}\b", body_lower):
                 score += 2
                 findings.append(f"<li>Подозрительный домен '{tld}' (+2)</li>")

    # вердикт
    if score == 0:
        verdict_text = "🟢 Уровень угрозы: НИЗКИЙ. Явных признаков фишинга не обнаружено."
        findings_html = "Угроз не найдено."
    elif score < 5:
        verdict_text = f"🟡 Уровень угрозы: СРЕДНИЙ. Счет: {score}."
        findings_html = f"<ul>{''.join(findings)}</ul>"
    else:
        verdict_text = f"🔴 Уровень угрозы: ВЫСОКИЙ. Счет: {score}."
        findings_html = f"<ul>{''.join(findings)}</ul>"

    return str(score), verdict_text, findings_html

# интерфейс
headers_input = gr.Textbox(label="1. Служебные заголовки", lines=5, placeholder="Вставьте заголовки (SPF, DKIM, From...)")
body_input = gr.Textbox(label="2. Текст письма", lines=10, placeholder="Вставьте текст письма...")

score_output = gr.Textbox(label="Итоговый счет угрозы", type="text", max_lines=1)
verdict_output = gr.Textbox(label="Финальный вердикт", type="text", max_lines=3)
findings_output = gr.HTML(label="Детализация обнаруженных угроз")

# примеры по тз учителя
examples_list = [
    # фишинг
    ["SPF: FAIL\nFrom: Bank <security@bank.com>\nReturn-Path: hacker@evil.ru", 
     "Ваш аккаунт будет заблокирован через 24 часа. Срочно подтвердите данные карты по ссылке: http://secure-login-update.ru"],
    
    # нормальное письмо
    ["SPF: PASS\nDKIM: PASS\nFrom: University <edu@uni.ru>\nReturn-Path: edu@uni.ru", 
     "Уважаемый студент, напоминаем о необходимости оплатить обучение до 25 числа. Оплату можно произвести через личный кабинет университета."],
    
    # реклама
    ["SPF: PASS\nFrom: Promo <promo@shop.com>", 
     "Только сегодня! Вы выбраны среди 100 счастливчиков! Вы выиграли приз! Заберите свой приз на странице акции: https://promo-super-win.shop"]
]

gr.Interface(
    fn=analyze_email,
    inputs=[headers_input, body_input],
    outputs=[score_output, verdict_output, findings_output],
    title="Email Security Analyzer (Практика 3). Нуритдинов Марат (USE-26)",
    description="Инструмент для оценки фишинга.",
    examples=examples_list
).launch()