Discord и секретная технология “открытый файл с паролем”

Казалось бы удивительно, чо так много спамеров в дискорде. Они своим количеством уже породили мем 1.jpg, 2.jpg, 3.jpg, 4.jpg @everyone @here

А потом копаешь тему и оказывается что абсолютно любой несанкционированный доступ к чтению файлов позволяет без проблем украсть твою сессию одним grep-ом токена.

Не “надо внедриться в процесс”. Не “надо обойти OS-level защиту”. Просто прочитать файл.


Что такое токен?

Очень грубо, в дискорде:

login + password + 2fa
        ↓
Discord выдаёт токен (хэш на основе каких-то данных)
        ↓
токен становится твоей сессией

Дальше клиент кидает этот токен на сервер при каждом запросе:

“это всё ещё я”

Сервер:

“ок, входи”

Стандартная схема. Так работает OAuth2, JWT, bearer tokens. Сама по себе модель норм - токен вместо пароля, можно отозвать серверно.

Проблема не в токене. Проблема в том, где он лежит.


Где хранится токен

Discord построен на Electron. Electron - это фреймворк для десктопных приложений на HTML/CSS/JS. По сути это браузер без адресной строки.

Discord хранит токен в Local Storage. Технически это LevelDB база, которая лежит в домашней директории пользователя:

~/.config/discord/Local Storage/leveldb/

Или на Windows:

%APPDATA%/discord/Local Storage/leveldb/

И токен лежит там в plaintext.

Не зашифрованный. Не в OS keychain. Просто строка в базе данных. Любая программа, запущенная от твоего пользователя, может прочитать этот файл.

А теперь самое смешное: Electron, на котором построен Discord, с 2019 года имеет встроенный API safeStorage.

Он умеет шифровать данные через OS-level механизмы:

  • macOS - Keychain Access. Защита от других пользователей И от других приложений.
  • Windows - DPAPI (Data Protection API). Шифрует ключом, привязанным к учётке пользователя. Защита от других пользователей.
  • Linux - kwallet, gnome-libsecret, или freedesktop Secret Service. В зависимости от DE.

То есть инструмент для нормального хранения секретов есть прямо в Electron из коробки. Его не надо ставить отдельно. Не надо писать свою криптографию. Просто вызвать safeStorage.encryptString(token).

Discord этого не делает.

Уже 6 лет как.


А если токен украсть?

То буквально ничего интересного не происходит:

Берёшь токен.

Подсовываешь его другому клиенту.

В С Ё…

: Ты уже внутри аккаунта.

  • Без логина.
  • Без пароля.
  • Без 2FA.
  • Без SMS.
  • Без passkey.
  • Без push-уведомлений.
  • Без подтверждений.
  • Без алертов о новом входе.

Новый логин вообще не регистрируется как новый. Старая сессия просто “переезжает” на другую машину.

Всё что можешь заметить - так это что разлогинило с твоего устройства. И то при условии что с этого токена уже кто-то зашёл, не оставив на чёрный день.


А чо, легко украсть?

Да.

На Windows работает ровно так же. Любой .exe качающий “читы для игры” или “бесплатный нитро” может прочитать файл и отправить токен на сервер злоумышленника.

Никаких эксплойтов. Никаких уязвимостей нулевого дня. Просто open() на файл, который Discord сам положил в домашнюю директорию.


Как Discord МОГ бы сделать

Вариантов дохуя. Все стандартные, все индустриальные:

  • safeStorage в Electron - доступен с 2019, юзают другие Electron-приложения (Signal Desktop, 1Password, Bitwarden)
  • Хранение секретов через OS keychain напрямую
  • Подтверждение доступа к секрету (биометрия, master password)
  • Fingerprint устройства + привязка токена к железу
  • Отдельный ключ, генерируемый на устройстве при первом входе
  • Security alerts при резкой смене окружения (новый IP, новая OS, новое железо)
  • Device-based сессии с подтверждением нового устройства

Да, всё это тоже можно обходить при наличии full access к машине.

Но между:

“прочитать файл”

и

“внедриться в процесс, обойти системные диалоги, подделать окружение”

лежит огромная пропасть.

Сейчас атакующему достаточно самого примитивного доступа - права на чтение файлов в домашней директории. То есть вообще любой запущенной программы.

С safeStorage атакующему пришлось бы либо внедряться в процесс Discord, либо расшифровывать DPAPI/Keychain (что требует повышения привилегий или кражи мастер-пароля).

Это не делает атаку невозможной. Но поднимает планку с “скрипткидди с grep-ом” до “таргетированной атаки со специфическими инструментами”.


А сейчас?

Сейчас цена атаки выглядит примерно так:

скачал подозрительную фигню
        ↓
она прочитала файл
        ↓
твою сессию угнали: "1.jpg, 2.jpg, 3.jpg, 4.jpg @everyone @here"

И пофиг что у тебя 2FA. Пофиг что сложный пароль. Файл открыт для всех программ, запущенных от твоего пользователя.


Если Discord не может

Как варик - логиниться в Discord со специально выделенного пользователя.

Чтоб права на чтение базы с сессией были только у него. При отсутствии внутренних эксплойтов в приложении Discord - шанс что у тебя что-то угонят минимальный.

На Linux это легко сделать из коробки - иерархия прав там нормальная с рождения системы.

На Windows в целом тоже можно, но безопасность не так велика: права появились как костыль лишь с релизом Vista, и до сих пор много софта работает в обход них.

Но всё лучше, чем оставлять файл открытым для всех, который Discord сам защитить по какой-то неведомой причине не смог.

Такая защитная прослойка имплементирована в моём NixOs config

можешь прям щас проверить свой discord: зайди в ~/.config/discord/Local Storage/leveldb/ и сделай grep -r 'mfa\.[a-zA-Z0-9_-]\{20,\}' . - скорее всего найдёшь свой токен.