
Декодирует и снимает подпись с уязвимых сессионных cookie из фреймворков Django, Flask, Laravel, Express и JWT. Поддерживает декодеры на основе HMAC, wordlists в base64 и конвейеры автоматизации для быстрого обнаружения уязвимостей.
CookieMonster — это инструмент командной строки и API для декодирования и модификации уязвимых сессионных cookie из нескольких различных фреймворков. Он предназначен для работы в автоматизированных конвейерах, которые должны эффективно обрабатывать большое количество таких cookie для быстрого обнаружения уязвимостей. Кроме того, CookieMonster расширяем и может легко поддерживать новые форматы cookie.
Стоит подчеркнуть, что CookieMonster находит уязвимости в пользователях фреймворков, а не в самих фреймворках. Эти пользователи могут устранить уязвимости, найденные с помощью CookieMonster, настроив фреймворк на использование надёжного секретного ключа.
| Фреймворк | Поддерживается | Примечания |
|---|---|---|
| JSON Web Tokens | ✅ | HS256, HS384, HS512 |
| Django | ✅ | Распространённые алгоритмы |
| Flask | ✅ | Распространённые алгоритмы |
| Rack | ✅ | Распространённые алгоритмы |
| Express (cookie-signer) | ✅ | Распространённые алгоритмы |
| Laravel | ✅ | AES-CBC-128/256 (GCM пока не поддерживается) |
| itsdangerous | ✅ | URLSafeSerializer/URLSafeTimedSerializer (соль по умолчанию) |
| Другие | ❌ | Пока нет! |
Чтобы установить CookieMonster, установите Go, а затем установите CLI:
go install github.com/iangcarroll/cookiemonster/cmd/cookiemonster@latest
CookieMonster нуждается всего в двух essentials: в cookie, которую нужно проверить и снять подпись, и в wordlist'е для использования. Если у вас нет wordlist'а, CookieMonster поставляется с wordlist'ом по умолчанию из проекта Flask-Unsign. Wordlist'ы CookieMonster немного отличаются: каждая строка должна быть закодирована в base64. Это связано с тем, что проекты на Python особенно вольны вставлять мусорные байты в эти ключи, и нам нужно иметь возможность правильно их обрабатывать.
Пример использования CLI со статической cookie или с URL:
% ./cookiemonster -cookie "gAJ9cQFYCgAAAHRlc3Rjb29raWVxAlgGAAAAd29ya2VkcQNzLg:1mgnkC:z5yDxzI06qYVAU3bkLaWYpADT4I"
🍪 CookieMonster 1.3.0
ℹ️ CookieMonster загрузил wordlist по умолчанию; в нём 38919 записей.
✅ Успех! Я обнаружил ключ для этой cookie с помощью декодера django; это "changeme".
% ./cookiemonster -url "https://httpbingo.org/cookies/set?abc=gAJ9cQFYCgAAAHRlc3Rjb29raWVxAlgGAAAAd29ya2VkcQNzLg:1mgnkC:z5yDxzI06qYVAU3bkLaWYpADT4I"
🍪 CookieMonster 1.3.0
⚠️ Я получил код состояния, отличный от 200, с этого URL; это был 302.
ℹ️ CookieMonster загрузил wordlist по умолчанию; в нём 38919 записей.
✅ Успех! Я обнаружил ключ для этой cookie с помощью декодера django; это "changeme".
CookieMonster способен поддерживать cookie, подписанные с помощью cookie-session, что часто используется в Express. Однако он делает несколько странных вещей, требующих осторожности при использовании этого инструмента. Типичный ответ от приложения cookie-session выглядит так:
set-cookie: session=eyJhbmltYWxzIjoibGlvbiJ9
set-cookie: session.sig=Vf2INocdJIqKWVfYGhXwPhQZNFI
Чтобы передать это в CookieMonster, вы должны указать как имя cookie, так и cookie с подписью. В этом примере вы бы вызвали CookieMonster так: cookiemonster -cookie session=eyJhbmltYWxzIjoibGlvbiJ9^Vf2INocdJIqKWVfYGhXwPhQZNFI (обратите внимание на разделитель ^ и префикс с именем cookie). API принимает тот же формат в monster.NewCookie.
CookieMonster имеет ограниченную поддержку повторной подписи cookie после того, как подпись была снята, с помощью флага -resign. Это включает изменение тела cookie в соответствии с вашим вводом и последующий пересчёт подписи с найденным ключом. В настоящее время это можно сделать для cookie, декодированных из Django; убедитесь, что вы передаёте оригинальную cookie в -cookie, а в -resign передаётся не закодированная строка текста, которую вы хотели бы видеть внутри cookie. CookieMonster правильно закодирует ваш ввод, а затем повторно подпишет cookie.
CookieMonster предоставляет pkg/monster, что позволяет другим приложениям легко использовать его. Это гораздо производительнее, чем запуск CLI, если вы тестируете много cookie. Пример использования приведён ниже.
import (
"github.com/iangcarroll/cookiemonster/pkg/monster"
"errors"
)
var (
//go:embed wordlists/my-wordlist.txt
monsterWordlist string
wl = monster.NewWordlist()
)
func init() {
if err := wl.LoadFromString(monsterWordlist); err != nil {
panic(err)
}
}
func MonsterRun(cookie string) (success bool, err error) {
c := monster.NewCookie(cookie)
if !c.Decode() {
return false, errors.New("не удалось декодировать")
}
if _, success := c.Unsign(wl, 100); !success {
return false, errors.New("не удалось снять подпись")
}
return true, nil
}
CookieMonster создан с вдохновением из нескольких источников и поставляется с отличными wordlist'ами от Flask-Unsign.