В первой обзорной статье на Хабре про MLSecOps мы сформировали общее понимание этого нового направления в IT, узнали про основные навыки, необходимые инженерам и архитекторам MLSecOps для успешной работы, подсветили яркое будущее и перспективы этой профессии.
Cсылка на статью: MLSecOps: защита машинного обучения в эпоху киберугроз
Давайте сегодня погрузимся в практику и разберем один из наиболее часто задаваемых мне вопросов: «Как защищаться от отравления данных? Как проверять данные на Data Poisoning»?
Подчеркну – не обязательно все советы из статьи реализовывать, возможно какие-то меры будут избыточны, так как в вашей практике уже реализованы альтернативные и при этом не менее эффективные стандарты защиты данных от отравления.
Также добавлю, что в этой статье мы разберем только сценарии отравления, связанные с изменением значений данных и меток к ним. А к таким сценариям отравления, как внедрение вредоносного кода в данные, внедрение закладок и другим мы вернемся в будущем.
Итак, всех желающих узнать больше про Data Poisoning в MLSecOps приглашаю под кат.
========================================================
I. Что такое Data Poisoning?
Data poisoning (отравление данных, DP) — это тип атаки на систему машинного обучения, при котором злоумышленник намеренно добавляет или изменяет данные в обучающей выборке, чтобы повлиять на поведение модели. Цель такой атаки может быть разной: снижение качества модели (атака на целостность), создание скрытых бэкдоров (например, распознавать определённый паттерн только при наличии триггера) или подмена классов (атака на доступность).
Это особенно опасно в условиях, где обучение происходит с использованием пользовательских данных или внешних источников (например, в системах с онлайн-обучением или federated learning).
Говорить о том, насколько важно защищаться от Data Poisoning и каков может быть потенциальный ущерб от такой атаки мы уже не будем – очевидно, что это критически важно для любого бизнеса (юридические последствия, репутационные, лавина новых атак в случае одной успешной, найм дополнительных сотрудников, потеря затронутых контрагентов и т.п.).
II. Типы атак Data Poisoning
Существует несколько классификаций Data Poisoning по типам атак. Проанализировав и обобщив некоторые из них, опишем здесь четыре основных типа атак:
Типы атак DP |
Описание |
Backdoor attacks (Атаки с бэкдором) |
При атаке с бэкдором злоумышленник внедряет в обучающие данные специальные образцы (трояны), которые содержат определенный "триггер". На основе отравленных данных модель учится реагировать на эти триггеры, например, классифицировать изображение как кошку, если в нём есть определённая метка, например, в правом нижнем углу изображения. |
Availability attacks (Атаки на доступность) |
Цель такой атаки — полностью дестабилизировать и дискредитировать модель, сделав её бесполезной, например, через добавление некорректных пар "вход-выход", что приводит к резкому снижению точности модели. |
Targeted attacks (Направленные атаки) |
Модель начинает ошибаться на конкретных примерах или при совершении определенных действий (в случае ИИ-агентов). Это достигается за счет добавления шума (иногда достаточно минимального, но при этом однонаправленного шума) или изменения меток. |
Influence attacks (Атаки влияния) |
Злоумышленник пытается с помощью отравленных данных изменить поведение модели в свою пользу, например, обмануть антивирусную систему, чтобы она не распознавала определенный вредоносный код. |
III. Как защититься от Data Poisoning?
Конечно же, в первую очередь нужно выстроить многоуровневую систему превентивной защиты от отравления данных, включающую:
Контроль источников данных. Сюда относится как внимательный выбор и валидация источников данных, регулярная проверка надежности текущих источников. Например, в случае, если какой-то источник не предоставил данные, необходимо выявлять и расследовать эту ситуацию, принимать меры по нивелированию подобных инцидентов. Желательно при этом получить недостающие данные из источника позже.
Валидация данных на входе. В случае, если данные поступают от пользователей, необходимо реализовать валидацию при получении таких данных (ограничение максимальной и минимальной длины ввода, проверку на SQL-инъекции, запрет ввода определенных символов и другие методы).
Фильтрация данных. Вместе с этим, необходимо реализовать фильтрацию данных на этапах ETL/ELT. Создайте пайплайн предобработки, который проверяет формат, структуру и содержание данных. Особенно важно в фильтрацию добавлять вредоносные или ненужные данные, которые ранее проходили фильтры и негативно сказались на качестве данных. Для текстовых данных можно использовать NLP-фильтры (обнаружение спама, вредоносных символов, подозрительных выражений). Для изображений необходимо настроить удаление файлов с подозрительной метадатой, размером, цветовой палитрой.
Очистка данных, выявление аномалий. Этот момент уже реализован в большинстве компаний. Необходимо проверяйть данные на наличие как полных дубликатов, так и подобных дубликатов (данные соответствуют друг другу на 95% и более), повторяющихся шаблонов, подозрительных меток. Можно использовать методы кластеризации (например, KMeans, DBSCAN) для поиска групп аномальных записей. Сюда же относится работа с пропущенными, аномальными значениями, приведение данных к единому формату и другие важные моменты.
Контроль доступов. Ограничьте круг лиц, которые могут добавлять/изменять данные, предоставляя полномочия в соответствии с RBAC (управление доступами на основе ролей) и PBAC (управление доступами на основе политики). Разграничивайте доступы к данным и их загрузку по времени суток, по геолокации, внимательно отслеживайте своевременное ограничение доступов для сотрудников, уходящих на больничный, учебный отпуск или в декрет. Для сотрудников, подающих заявление на увольнение, необходимо по возможности максимально оперативно, сразу же ограничивать доступы к критически важным данным, инструментам и системам. Внедрите системы авторизации и аудита (кто, когда и что загрузил). Используйте механизмы SSO и двухфакторную аутентификацию.
Шифрование, архивирование, хеширование и цифровые подписи. Как минимум зашифрованные данные сложнее отравить – злоумышленнику потребуется время, чтобы расшифровать данные. За этот период времени, возможно, удастся обнаружить атаку и ее предотвратить. Заархивировав данные, запаролив этот архив мы ставим еще одну линию защиты. Хеширование (с помощью SHA-256) необходимо реализовать сразу после загрузки данных в хранилище и непосредственно перед обучением моделей. Мы должны сверить, соответствует ли хэш загруженных данных хэшу данных, на которых мы обучаем. Предполагается, что в данные изменения не вносились. Если же изменения вносятся, ведется журнал хешей, где указываются значения хешей, дата и время изменений, сотрудник, вносивший изменения и их причина. Крайне важно хранить хеши и журнал хешей отдельно от хранимых данных, чтобы злоумышленник вообще не видел, что хеширование реализовано. Ну и вишенка на торте – подписывайте данные цифровыми подписями, чтобы убедиться в их происхождении.
Балансировка классов. В случае отравления данных оно часто затрагивает распределение баланса классов. Поэтому индикаторы баланса классов выступают в качестве естественного хэша
Мониторинг и логирование. Это строго обязательная мера. Логируйте все события: кто загрузил данные, когда, откуда, какие изменения были. По возможности настройте алертинги на логах – если в Новогоднюю ночь сотрудник заходит в базу данных, это кажется подозрительным.
Версионирование и резервирование данных. Версионируйте данные, при этом желательно хранить прежние версии и текущую в разных репозиториях. Обязательно имейте копию данных, чтобы быть готовыми и к сверке, и к восстановлению в случае полного уничтожения основной версии данных. Это позволит вам откатиться к прежней версии данных, либо даже бесшовно переключиться на горячую копию данных в случае выявления отравления.
Обучение сотрудников, разграничение ответственности и соблюдение этических принципов. Безусловно это важно, ведь если сотрудник понимает ответственность, ущерб от отравления данных, и в том числе возможности компании выявить первоисточник отравления, он будет менее склонен совершать негативные действия и будет более бережно относиться к конфиденциальности и безопасности. В моей практике MLSecOps был случай, когда благодаря бдительности и неравнодушию сотрудника, прошедшего обучение по обеспечению безопасности ИИ-систем, удалось своевременно обнаружить и предотвратить потенциальный инцидент, связанный с использованием нейронной сети в крупной финансовой компании.
IV. Как выявить уже отравленные данные?
Что если злоумышленнику удалось обойти все наши защиты от отравления данных, и есть только датасет, в котором нужно проанализировать и ответить (с 95% вероятностью) было отравление данных или нет?
Давайте рассмотрим две возможные ситуации и приведем примеры кода на Python.
Пример 1. Неравномерное распределение меток по категориям, приводящее к смещению классификации.
В отравленных данных метки намеренно сконцентрированы в определенных категориях, создавая искусственное смещение. Это означает, что для некоторых категорий вероятность увидеть определенную метку значительно выше, чем для других, даже если это не соответствует реальному распределению данных. Злоумышленник пытается заставить модель переоценивать важность этих категорий при принятии решений.
Например, в данных для определения привлекательности ценных бумаг (привлекательная/непривлекательная) злоумышленник может добавить большое количество положительных отзывов о конкретной малоизвестной акции и пометить существенную их часть как «привлекательные». Модель, обученная на этих данных, начнет систематически переоценивать эту ценную бумагу и приоритетно рекомендовать эту ценную бумагу для инвестирования.
Предположим, у нас есть датасет, состоящий из названий ценных бумаг и тональности отзывов к ним:
AAPL - привлекательная
AAPL - непривлекательная
XYZ - привлекательная
XYZ - привлекательная
XYZ – привлекательная
Мы хотим проверить, нет ли аномального смещения (концентрации) одной метки (например, «привлекательная») на определённых ценных бумагах.
Для этого нам как минимум нужно реализовать простые шаги:
Посчитать долю положительных меток (привлекательная) по каждому тикеру.
Определяем стандартное отклонение (σ).
Найти бумаги, где эта доля значительно отличается от средней (например, на 2σ).
Выдать список подозрительных ценных бумаг, если какой-то тикер имеет долю меток, отличающуюся от средней более чем на 2σ.
Пример кода на Python (ситуация гипотетическая):
# Импортируем библиотеки Pandas и Numpy, присваиваем им псевдонимы pd и np
import pandas as pd
import numpy as np
# Создаем исходные данные (сюда нужно загрузить Ваши данные в формате двух столбцов - 'ticker' – название ценной бумаги и 'label' – отметка, привлекательная ли она судя по отзыву для инвестирования)
data = {
'ticker': ['AAPL', 'AAPL', 'XYZ', 'XYZ', 'XYZ'],
'label': ['привлекательная', 'непривлекательная', 'привлекательная', 'привлекательная', 'привлекательная']
}
df = pd.DataFrame(data)
# Пишем функцию по обнаружению подозрительных ценных бумаг
def detect_data_poisoning(df):
# Шаг 1: подсчитываем долю бумаг с отметкой "привлекательная" по каждому тикеру
pos_counts = df.groupby('ticker')['label'].apply(lambda x: sum(x == 'привлекательная'))
total_counts = df['ticker'].value_counts()
# Доля положительных меток по каждому тикеру
positive_ratios = pos_counts / total_counts
# Шаг 2: считаем среднее и стандартное отклонение среди всех акций
mean_ratio = positive_ratios.mean()
std_deviation = positive_ratios.std(ddof=0) # ddof=0 означает деление на N (популяционное стандартное отклонение)
# Шаг 3: выявляем акции, чьи положительные рейтинги отличаются больше чем на 2 сигмы
threshold = 2 * std_deviation
suspicious_tickers = positive_ratios[(positive_ratios > mean_ratio + threshold) | (positive_ratios < mean_ratio - threshold)]
return suspicious_tickers
suspicious_tickers = detect_data_poisoning(df)
print("Подозрительные ценные бумаги:")
if len(suspicious_tickers) > 0:
print(suspicious_tickers)
else:
print("Нет подозрительных ценных бумаг.")
Пример 2. Серия определенных меток, указывающая на искусственное добавление вредоносной последовательности
В отравленных данных метки организованы в статистически значимые последовательности, что указывает на искусственное создание этих данных. В реальных данных метки обычно распределены более случайным образом, и наличие длительных последовательностей с одинаковыми метками является подозрительным признаком. Злоумышленник пытается заставить модель выучить искусственные паттерны, основанные на последовательностях, а не на реальных признаках данных.
Например, в данные, содержащие название фильма, текстовое описание отзыва и метку – «позитивный» или «негативный», злоумышленник может добавить в случайное место последовательность отзывов, помеченных как «позитивные». Модель, обученная на этих данных, может отмечать определенные фильмы как позитивные и наоборот.
Пример кода на Python (ситуация гипотетическая):
# Импортируем библиотеку Pandas, присваиваем ей псевдоним pd
import pandas as pd
# Импортируем библиотеку Numpy, присваиваем ей псевдоним np
import numpy as np
# Сформируем чистые данные (отзывы о фильмах) в датасет с названием clean_data
clean_data = pd.DataFrame({
'movie': ['A', 'B', 'C', 'D', 'A', 'B', 'C', 'D'],
'text': [
'Хороший фильм, мне понравился',
'Сюжет скучный',
'Отличная актерская игра',
'Не досмотрел из-за плохой режиссуры',
'Красивая операторская работа',
'Очень предсказуемый сценарий',
'Мне не понравились спецэффекты',
'Затянутый и скучный'
],
# Каждому отзыву присваиваем метки - позитивный или негативный отзыв.
'label': ['positive', 'negative', 'positive', 'negative', 'positive', 'negative', 'negative', 'negative']
})
# Создаем отравленные данные (фильму X присваиваем положительные отзывы 200 раз)
poisoned_data = pd.DataFrame({
'movie': ['X'] * 200,
'text': ['Фильм потрясающий!'] * 200,
'label': ['positive'] * 200
})
# Объединяем чистые и отравленные данные, используя функцию pd.concat() из библиотеки pandas, и сохраняем результат в переменной full_data.
full_data = pd.concat([clean_data, poisoned_data], ignore_index=True)
print("Распределение меток по фильмам:")
# Группируем новые данные по столбцам movie, label, считая число негативных и позитивных отзывов по каждому фильму.
# Если какой-то пары (movie, label) нет, то ставится 0 (благодаря fill_value=0).
print(full_data.groupby(['movie', 'label']).size().unstack(fill_value=0))
# Импортируем функцию chi2_contingency из модуля scipy.stats
# Это статистический тест, который помогает ответить на вопрос: зависит ли одна категориальная переменная от другой?
from scipy.stats import chi2_contingency
# Подготавливаем таблицу счётчиков: [positive, negative] для каждого фильма
label_counts = full_data.groupby(['movie', 'label']).size().unstack(fill_value=0)
# Вычисляем общее распределение (без подозрительного фильма X)
overall_dist = label_counts.drop('X', errors='ignore').sum()
# Строим таблицу для тестирования фильма X против остальных
contingency_table = pd.DataFrame({
'X': label_counts.loc['X'] if 'X' in label_counts.index else [0, 0],
'Other': overall_dist
}).T
# Проводим тест хи-квадрат
chi2, p, dof, expected = chi2_contingency(contingency_table)
# Выводим итоговый ответ
print("\nТаблица наблюдений:")
print(contingency_table)
print("\nОжидаемое распределение (при равенстве):")
print(expected)
print(f"\np-value: {p:.6f}")
if p < 0.05:
print("⚠️ Обнаружено значительное отклонение (возможно, Data Poisoning)")
else:
print("✅ Распределение соответствует ожидаемому (нет признаков отравления)")
Коды проверки датасета на отравление могут быть как простыми, так и сложными, с учетом разных статистических закономерностей.
Разумеется, при таких проверках нереально обойтись только одним алгоритмом – следует осуществлять проверку сразу несколькими кодами, с учетом разных способов реализации атаки Data Poisoning и руководствуясь тем, что в каком-либо из кодом может быть ошибка. Поэтому каждый предполагаемый способ возможного отравления датасета нужно проверять двумя различающимися кодами.
V. Какие могут быть способы реализации атаки Data Poisoning в MLSecOps?
Ниже приведены атаки Data Poisoning, часть их которых я встречал в своей практике. При этом во многих случаях сложно понять, с какими именно данными мы работаем - отравленными или сильно грязными данными, которые только кажутся отравленными.
В любом случае - все это нужно проверять, выявлять и с этим нужно работать:
Реализация атаки |
Описание способа реализации атаки |
1. Неравномерное распределение меток по категориям, приводящее к смещению классификации. Действия атакующего: изменение меток определенного класса. |
Этот способ мы уже описали выше. Он выражается в том, что злоумышленник меняет метки для определенного класса. |
2. Серия определенных меток, указывающая на искусственное добавление вредоносной последовательности. Действия атакующего: создание искусственных строк с определенными метками. |
Этот способ отравления также был описан в другом примере с кодом ранее. |
3. Аномально высокая частота определенных значений признаков в сочетании с определенной меткой. Действия атакующего: анализ данных и добавление реалистичных признаков-"якорей" в данные, чтобы усилить определенные уже существующие корреляции. |
Атака характерна для LLMs. В отравленных данных могут быть введены примеры, в которых определенные значения признаков необычайно часто встречаются в сочетании с определенной меткой. Это может быть вызвано тем, что злоумышленник пытается создать сильную, но искусственную корреляцию между признаками и меткой, чтобы исказить обучение модели. |
4. Наличие признаков, значения которых не имеют смысла в контексте предметной области, но коррелируют с определенной меткой. Действия атакующего: добавление неявных признаков-якорей в данные, чтобы создать неочевидную, завуалированную корреляцию. |
Злоумышленник может ввести в данные признаки, которые не имеют реального значения или физического смысла в контексте задачи машинного обучения, но при этом сильно коррелируют с определенной меткой. Это делается для того, чтобы модель случайно выучила эту корреляцию и начала использовать бессмысленные признаки для принятия решений. |
5. Искусственное совпадение значений признаков у разных классов. Действия атакующего: добавление/изменение данных таким образом, чтобы отдельные классы были подобны между собой. |
Злоумышленник намеренно добавляет данные, где объекты из разных классов имеют почти идентичные значения признаков, что затрудняет разделение классов моделью. Это приводит к снижению обобщающей способности модели и увеличению вероятности ошибок на тестовых данных. |
6. Добавление шума в конкретные признаки для определённого класса. Действия атакующего: добавление определенного, однонаправленного шума. |
Злоумышленник добавляет случайный или систематический шум только к данным определённого класса, чтобы исказить распределение признаков. Это может заставить модель недооценивать или переоценивать важность этих признаков при принятии решений. |
7. Массовое дублирование записей одного класса. Действия атакующего: добавление множества записей определенного класса. |
Злоумышленник добавляет большое количество дубликатов (или почти дубликатов) записей одного класса, чтобы искусственно увеличить его представительство в обучающих данных. Это может привести к переобучению на этот класс и неспособности модели корректно предсказывать другие классы. |
8. Создание ложной зависимости между временным признаком и целевой меткой. Действия атакующего: изменение признака времени в данных для создания неявных корреляций. |
Злоумышленник добавляет данные таким образом, чтобы временные признаки (например, дата, час дня, день недели) сильно коррелировали с определённой меткой, даже если в реальности такой связи нет. Это может заставить модель принимать решения на основе времени, вместо содержательных признаков. |
9. Целенаправленное искажение баланса классов во временных срезах. Действия атакующего: изменение классов и данных таким образом, чтобы имитировать наиболее вероятные тренды, например, сезонность. |
Злоумышленник изменяет соотношение классов в определённые периоды времени, создавая искусственный тренд или сезонность. Это может привести к тому, что модель начнёт ожидать таких изменений в будущем и будет делать неверные прогнозы. |
10. Добавление «триггерных» комбинаций признаков, активирующих определённую метку. Действия атакующего: малые изменения сразу нескольких признаков для создания триггерных комбинаций и их корреляций с определенной меткой. |
Злоумышленник внедряет данные, в которых сочетание определённых признаков всегда связано с определённой меткой. Эти триггеры могут быть редкими и малозаметными, но при их наличии модель всегда даёт нужный злоумышленнику результат. |
VI. Какие общие рекомендации по защите от таких атак?
Очень важным моментом в проверке на отравление данных является не только хеширование, но и фиксация:
Метаданных датасета.
Выделенных признаков для обучения модели (если это было реализовано).
Числа строк датасета.
Баланса классов по категориям и временным срезам.
Помимо этого, желательным действием становится хотя бы выборочная визуальная проверка датасета в 2-3 местах. Другие меры:
Проверка на наличие выбросов в распределении признаков.
Анализ корреляций между признаками и метками.
Обнаружение дубликатов, подобных дубликатов и псевдо-дубликатов.
Использование детекторов аномалий в данных.
Крайне важно понимать, что порой трудно различить «грязные данные» и «отравленные данные». В идеале на этапе предобработки и разведочного анализа данных нужно всегда обнаруживать и проверять в том числе указанные признаки отравления.
В то же время на 100% защититься нельзя. Поэтому при проверке на Data Poisoning в условиях ограниченных ресурсов следует отдавать предпочтение более простым и понятным методам проверки, охватывая, в то же время, сразу несколько возможных способов реализации атаки отравления данных, и перепроверяя эти методы проверки дополнительными, реализованными иначе.
VII. Где можно больше узнать про защиту и проверку на Data Poisoning в MLSecOps?
Все вопросы, обратную связь, можете написать в комментарии к статье или задать в моих блогах в TG и VK. А если вдруг вы встречали другие способы DP-атак - поделитесь ценным опытом, буду рад!
В связи с растущей потребностью в специалистах по обеспечению безопасности ИИ-систем и с учетом положительной обратной связи слушателей первого потока, мы запускаем второй поток программы профессиональной подготовки при Академии Softline, разработанной для обучения специалистов, способных эффективно защищать данные от отравления и внедрять новые, улучшить существующие практики MLSecOps в любой организации. Особенно эти специалисты востребованы сегодня в сфере государственного управления, финансов и здравоохранения.
Приглашаем вас присоединиться к нашей программе профессиональной подготовки «Обеспечение безопасности систем машинного обучения. Основы MLSecOps» и стать востребованным специалистом в области безопасности ИИ-систем!
Для получения дополнительной информации и регистрации посетите наш веб-сайт.