Ко(д)тики и безопасность
512 subscribers
20 photos
8 files
101 links
Канал о безопасной разработке для программистов и не только.
Download Telegram
Prompt Hacking

Долго не писала сюда, но есть две ссылки, которым хочу поделиться.

У learnprompting нашла два курса, которые довольно любопытны с точки зрения того, что суммируют общие подходы к инъекциям в промты. Интересно также повыполнять задания, потестировать инъекции на практике. Ссылки вот:
Интро и продвинутый промт хакинг

А если касательно практики без теории, то рекомендую еще одну игру, где нужно уговорить Гэндальфа рассказать вам секретный пароль (там также доступны другие режимы)

В безопасности моделей очень много схожего с безопасностью кода, что ожидаемо, хоть по сути атак, кажется, несколько больше. По всей видимости, и разбираться с тем, как с ними работать безопасно, тоже придется через опыт атак. И если раньше аппсеки искали всякие площадки типа beewapp или webgoat для демонстрации уязвимостей на коде (ну или придумывали таски, как в этом канале), то теперь аналогичные штуки для атак на модели тоже нужны именно для демонстрации разработчикам, как их будут ломать. Поэтому если знаете еще - будет круто увидеть их в комментариях.
🔥8👍1
Всем привет!
Что-то давно у нас не было уязвимого кода. Предлагаю посмотреть на следующий фрагмент кода, содержащий логическую уязвимость (или парочку, но связанных с одним и тем же). Как всегда -- при правильном промте и должном уровне настойчивости можно уговорить любого агента разобраться с этим кодом, а сможете ли вы?)



package cleaner

import (
"context"
"time"
)

type Store interface {
ListExpired(ctx context.Context, n int) ([]string, error)
Delete(ctx context.Context, id string) error
}

func CleanupExpired(ctx context.Context, db Store) {
t := time.NewTicker(time.Minute)
defer t.Stop()

for {
select {
case <-ctx.Done():
return
case <-t.C:
ids, err := db.ListExpired(ctx, 100)
if err != nil || len(ids) == 0 {
continue
}
for _, id := range ids {
ctx, cancel := context.WithTimeout(ctx, 750*time.Millisecond)
go func(id string) {
defer cancel()
_ = db.Delete(ctx, id)
}(id)
}
}
}
}



UPD: в комментах классное обсуждение того, что начиная с версии 1.22 ситуация может резко поменяться и в коде останется меньше уязвимостей. Спасибо @nu11by7e
👍1
В последнее время даже в этом канале было много призрачного присутствия ИИ, но сегодня хочу поговорить про недавнюю уязвимость в ZYXEL ZLD, Remote Code Execution via CLI Command Injection. А она от высоких технологий очень далека)

Подробно про то, как уязвимость была найдена и что хакер делал для эксплуатации, можно почитать здесь. Но мне бы хотелось обратить внимание на причину -- разработчик счел, что если метод не задокументирован, то можно не заморачиваться над санитизацией. Очень похоже на ситуацию, когда оставляют какой-то служебный или тестовый (иои просто не до конца реализованный) эндпоинт в рассчете на то, что вызова его с фронта нет, значит, и проблемы нет.

Но это не так: все, к чему вы, как разработчик или тестировщик, можете обратиться в вашем приложении без полноценного RBAC (role-based access control), точно так же доступно злоумышленнику. И почему-то, несмотря на использование всяких передовых технологий, количество таких уязвимостей не уменьшается, а встречается все так же часто.

Надеюсь, вам понравится статья, она легко читается)
👍3🔥1
Сегодня предлагаю посмотреть на фрагмент кода реального проекта (с реальной уязвимостью, CVE и всеми делами) и попробовать угадать, в чем заключается уязвимость. А может, даже угадать, о каком проекте идет речь, благо, CVE свежая и можно посмотреть новости.


async function openURLMiddleware(req: IncomingMessage, ...) {
if (req.method === 'POST') {
/* ... */
const {url} = req.body as {url: string};
await open(url);
/* ... */
}
next();
}
export default connect().use(json()).use(openURLMiddleware);


Где open импортируется отсюда: https://github.com/sindresorhus/open/tree/v6.4.0 (прикольно, когда по имени владельца репозитория в голове сразу всплывает ассоциация, что уже в истории были атаки на разработчиков посредством npm зависимостей, опубликованных с аккаунта, отличающегося одной буквой. Вот это популярность, я считаю). Lумаю, что по коду будет понятна причина уязвимости, но сама уязвимость, если вы не читали эту новость, может удивить серьезностью.

Уязвимость оценена в CVSS 9.8, но отчасти причиной тому служит факт, что ассоциирована она с development сервером, а не с боевой средой. Но сам факт такой очевидной баги в боевом проекте впечатляет. Расскажу подробнее о том, что же там скрывается на самом деле, в эту пятницу.
👍1
31 октября рассказывали страшные истории разработчикам про то, как их атакуют. Половина историй так или иначе касалась npm. А часть из них - кражи аккаунтов контрибьюторов популярных библиотек.И вот хорошая новость, если заглянуть на npmjs.com, то увидите такую картинку)
🔥2
OWASP Top-10 обновился! ☄️

Точнее, вышел новый релиз кандидат. Но по факту, можно считать, что обновился. Три новых категории, четыре сменили имя и область применения. Я думаю, что в ближайший месяц есть смысл подробнее и пристальнее посмотреть на изменения - если хотите, присоединяйтесь, будем делать это вместе здесь.

Но поскольку в последнее время мне лично все чаще приходится бороться с процессами (вот неожиданность-то, оказывается, основная проблема для безопасной разработки - это процессы, а не фрагменты кода с уязвимостями, кто бы мог подумать!), то хочу начать разбор с одного из самых первых документов старой версии - раздела How to use the OWASP Top 10 as a standard.

И вот важный момент, про который часто забывают - это скорее awareness документ. Т.е. его содержимое - это то, о чем в целом знать и держать это в голове нужно постоянно. Это bare minimum для процесса написания кода, ревью кода и создания чеклистов для peer review. А также для выбора инструментов, как ни странно (хотя, как мы помним, многие "логические" баги с инструментами без мышления не ловятся. С условным "мышлением" пока что тоже, но это детали.)

В общем, предлагаю поразбираться в ближайшее время детальнее, что же изменилось, и в чем причины перемен, а пока - вот ссылка на сам документ.
👍7
Ко(д)тики и безопасность
OWASP Top-10 обновился! ☄️ Точнее, вышел новый релиз кандидат. Но по факту, можно считать, что обновился. Три новых категории, четыре сменили имя и область применения. Я думаю, что в ближайший месяц есть смысл подробнее и пристальнее посмотреть на изменения…
Как и договаривались, предлагаю сегодня чуть детальнее поизучать релиз кандидата OWASP Top-10 2025. А на самом деле проговорить некоторые вещи, которые были действительны и для старого.

Существует мапинг между категориями топ-10 и CWE (Common Weakness Enumeration), и в некотором смысле вот эти вот стрелочки с перемещениями означают смену маппинга. И в случае А01:2025 - Broken Access Control, в маппинге произошло добавление категорий и к первому разделу присоединились следующие CWE: CWE-200 (раскрытие чувствительной информации неавторизованному пользователю), CWE-918 (подделка запросов на стороне сервера) и CWE-352 (межсайтовая подделка запросов или CSRF, Cross-Site Request Forgery). Первое: перевод - дело сложное, практически как информация - "чувствительная", поэтому не судите строго, и второе: в моей картине мира CWE-352 всегда относилась к Broken Access Control, однако, как выяснилось, раньше она стояла в категории «A05:2021 — Security Misconfiguration». CSRF становятся возможны в том числе в случае мисконфигурации CORS - Cross-Origin Resource Sharing политик, которые определяют, как наше приложение будет реагировать на браузерные запросы с других Origin.

И вот именно про мисконфигурации CORS и хочу сегодня поговорить. Это не самая увлекательная уязвимость, но есть тонкие детали, и сегодня посмотрим их на примере фреймворка Spring. Суть атаки проста: злоумышленник добивается выполнения действия от имени пользователя и в рамках его сессии, о котором пользователь вообще не в курсе. Например: смена почтового адреса аккаунта, изменение пароля, или — что посерьёзнее — какая-то финансовая операция. Хотя последний пример сейчас встречается значительно реже (года с 2018 я лично таких случаев не видела), первые — вполне ещё происходят. Очень подробное описание сути атаки можно посмотреть здесь.

Бытует мнение, что если приложение не использует куки, то CORS вполне может быть disabled: мол, раз нет куки, то и CSRF невозможен. Но это не так. Даже без куки подвластный злоумышленнику сайт всё равно может отправлять неаутентифицированные запросы к вашему API, а затем анализировать разницу во времени или кодах ответов. Это позволяет:

- выявлять существующие внутренние эндпоинты,

- «прощупывать» архитектуру API через сайд-чейны (XS-Leaks),

- использовать браузер жертвы как бесплатный ботнет для флуд-атак

А ещё есть забавный кейс: пользовательская часть работает на токенах, а для панели администратора — всё ещё используются куки. В такой гибридной схеме отключение CORS уже приводит к реальным рискам CSRF именно для административных операций.

Поэтому даже если официальная документация прямо на странице про CORS говорит, мол, вот вам пример, как выключить CORS вообще, в реальных приложениях делать этого все же не стоит.

Но позволю себе чуть докопаться и до официального «правильного» примера. В нём действительно не хватает пары важных деталей. Например:

- setAllowedHeaders — помогает быстрее находить проблемы, если приложение использует кастомные заголовки;

- setMaxAge — улучшает производительность, если вы хотите кэшировать preflight-запросы;

- начиная с Spring Security 5.3 появился очень полезный метод setAllowedOriginPatterns, который значительно упрощает жизнь, если необходимо разрешать доступ для целых групп доменов (например, всех субдоменов).

В общем, будьте осторожны с CORS)
🔥6❤‍🔥21
Уязвимость из сегодняшнего примера трудно классифицировать. Не инъекция, не BOLA, что-то совсем другое. Я бы отнесла ее к уязвимостям бизнес-логики, но она не то чтобы про логику.

Очень абстрактная подсказка: Intel когда-то упустила проблему примерно из той же области и заплатила за это 475 миллионов долларов в 95 году.

И вопрос будет не тот, который обычно задаю. Понятно, что с кодом что-то не так, если уж он в этом канале. Давайте поменяем вопрос: какой сценарий атаки?)

UPD. 100 - минимальная цена, при которой скидка применяется


public class DiscountService {

private static final double MIN_PRICE = 100.00;

public boolean isPromoEligible(double purchaseAmount) {
return purchaseAmount >= MIN_PRICE;
}

public double applyDiscount(double price) {
if (isPromoEligible(price)) {
return price - 10.00; // flat discount
}
return price;
}
}
Итак, разбор уязвимости этой недели - атака через точность чисел с плавающей точкой.

Как верно подметили в комментах, основная проблема этого кода -- ошибки округления, на которые все очень часто забивают. Код максимально топорный: берем сумму заказа, если она больше или равна 100, применяем скидку в 10 денежных единиц. Казалось бы, простая задача, но все же уязвимость закралась. Как же так?

А вся проблема в double. Машины хранят числа с ограниченной точностью, очевидно, и операции с плаващей точкой подчиняются стандарту IEEE 754. На скриншоте ниже приведен пример того, как эта штука работает - условно говоря, 100.00 и 99.99999999999999999997 для машины... одно и то же, если выбран неподходящий тип.

А теперь давайте представим, что речь идет о 100 и 99.99999999999999999997 долларах и о том, что эта операция может производиться, ну, к примеру, миллион раз в сутки на протяжении десятилетия. И подвержены проблеме, по сути, все языки, имеющие float и double типы. Но точно так же во всех языках настоятельно не рекомендуется применять эти типы для финансовых операций и в целом для всего, что требует высокой точности. Но есть примеры того, что использовать стоит - Java - BigDecimal, Python - Decimal, Go - big.Float - но делать это нужно явно.

Я помню, еще на курсе ассемблера в универе нам рассказывали о кейсах, когда из-за переполнений и погрешностей вычислений падали самолеты. Но найти именно ту историю не вышло, зато вот история о взрыве ракеты Ariane 5 по причине хоть и не такой же в точности, но схожей.
🔥4
Когда ты пентестер и выходит бага на 10.0 - это прикольно. Когда ты аппсек, думаешь - "приехали". А кто еще не видел - RCE на 10.0 в React Server Components, аффектит все, где компоненты включены.

от авторов: https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components
от wiz: https://www.wiz.io/blog/critical-vulnerability-in-react-cve-2025-55182

а ссылку на PoC публиковать не буду.
4👍2
Тут товарищи из хакерспейса Черный лед делают крутой ивент про путь SOC специалиста, делюсь ссылкой для всех, кто в Алматы: https://t.me/blackicehackerspace/133

Что в канале про аппсек делает ссылка на ивент про SOC? имхо, один из самых полезных на практике тандемов, если успешно работает, конечно
👍4
Сложный выдался декабрь 🙂

Но поскольку слишком больших скиллов в поздравлениях у меня нет, пришлось мое поздравление немного запрятать. И если вдруг у вас будет желание спасти, пусть не Деда Мороза, а, скажем, кого-то из его помощников, а еще будет какое-то количество свободного времени, то "подарок" для вас - в файле ниже. С наступающим!
7🎉1
Давненько не было постов.

Когда пытаешься подобрать примеры для иллюстрации STRIDE разработчикам, всегда чуточку некомфортно с последним пунктом - повышение привилегий не по причине каких-то мисконфигураций, а именно в коде. Это всегда логическая ошибка, а с логикой сложно: ни статанализаторы ее не понимают, ни ИИ из коробки без детальной документации и объяснений. Да и примеры общеизвестные мне почему-то всегда было трудно подобрать. Спасибо ребятам из Kyverno, теперь пример будет. Да не простой, а прям сразу на CVSS 10.0.

Подробности, разбор кода (и эксплойт) доступны и детально разобраны здесь: https://github.com/advisories/GHSA-8p9x-46gm-qfx2

Что же там произошло. В Kyverno есть возможность при написании политики обратиться напрямую в Kubernetes API - apiCall. Проблема заключается в том, что при создании контекста, код, реализующий этот функционал, подставляет переменные напрямую в поле URLPath, не санитизируя их никаким образом и даже не проверяя, а принадлежит ли сформированный path к скоупу той полиси, которая пытается его установить. И все дальнейшие узлы, в которые эта переменная попадает, тоже не провряют именно привязки по правам, ведь дальше-то все вызовы идут от имени высокопривелигрованного Service Account Kyverno, что позволяет автору зловредной политики читать содержимое Secrets и Configmaps из других неймспейсов.

В исправлении заэнфорсили проверку того, что автор полиси не пытается посягнуть на что-то вне своего скоупа:
1. The path explicitly contains the /namespaces/<namespace>/ segment.
2. The namespace in the path matches the policy's namespace.
3. Requests missing the namespace segment (targeting cluster-scoped resources) or targeting a different namespace are rejected.

Очень нравится, как четко разобрали причину уязвимости и рассказали, как исправили. Ведь признать свои баги и прозрачно их поправить - это новое sexy.
👍10
🤝 Пара интересных RCE в n8n

Похоже, за n8n взялись всерьез (ну... неудивительно). Если дело так пойдет и дальше, придется заводить под их уязвимости отдельную рубрику.

Разбор упомянутых CVE в деталях можно почитать здесь, «из первых рук», так сказать. В чем суть, вкратце. Обе RCE — ответочка от jFrog на уже реализованные разработчиками n8n меры по устранению ранее обнаруженных уязвимостей, которые в итоге и привели к новым CVE-2026-1470 и CVE-2026-0863. Дело в том, что когда возможность выполнения пользователями <относительно> произвольного кода становится официальной фичей, вопрос безопасной реализации подобной функциональности слегка усложняется. Разработчики n8n пошли по пути синтаксической валидации пользовательского кода на уровне AST в обоих случаях (JavaScript, Python): код разбирается в синтаксическое дерево, дерево обходится визитором, осуществляющим детектирование потенциально опасных узлов.

И это — фиговое решение, как минимум по двум причинам.

1️⃣ Во-первых, по своей сути — это контроль по черным спискам. Собственно, патчи к этим уязвимостям (раз, два) разработчики свели к добавлению в эти списки техник атак, продемонстрированных ресерчерами jFrog. Сколько ещё вариантов поиграться с синтаксисом этих языков для подобных RCE существует прямо сейчас — думаю, jFrog'и скоро расскажут. А, как скоро в новых версиях языков появятся конструкции, не предусмотренные в черных списках n8n, но позволяющие выстроить гаджеты для вот таких RCE — покажет время.

2️⃣ Во-вторых, проверки на уровне AST — это синтаксическая валидация. У всех языков, помимо синтаксиса, есть ещё и семантика. А у динамических языков (коими являются, и JavaScript, и Python), некоторая её часть является сущностью времени выполнения. И эта часть НЕ МОЖЕТ быть эффективно проанализирована статическими проходами по синтаксическому представлению. Иными словами, даже белые списки (исходя из того, что в них было бы необходимо разрешить в свете соответствующих фич n8n) здесь не позволили бы закрыть все потенциальные проблемы.

🤓 Как правильно работать с такими кейсами?

Простых решений, здесь, увы можно не ожидать. По возрастанию упоротости трудозатрат на реализацию:

1. Если есть возможность влиять на язык, используемый для скриптов, то взять ограниченный валидацией по белым спискам (разрешенные синтаксические конструкции, пространства имен и типы) статический язык с сильной типизацией. Из известных мне языков на эту роль лучше всего подходит C# Scripting.

2. На этапе прохода по AST инструментировать код проверками на допустимость операций, которые будут осуществляться в рантайме, во время выполнения скрипта. В идеале библиотека рантайма и используемые сторонние библиотеки также должны быть инструментированы (реализацию можно подсмотреть в OpenTelemetry, например). В пределе — это приведет к разработке собственного RASP, заточенного под фичи скриптинга конкретного проекта.

3. Использовать собственноручно пропатченные интерпретаторы, допускающие только разрешенные синтаксис и семантику. Настолько сложно, что в большинстве случаев нецелесообразно.

Ну и, безотносительно способа первичной защиты: выполнять все пользовательские скрипты в изолированных контейнерах: как минимум — в Docker, как рациональный максимум — в условном FireCracker'е.

TL;DR: разработчики n8n думают, что устранили ещё две RCE, но есть нюанс. И простого способа его обойти у них нет.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥3
как-то пропустила момент, что у Secure Code Warrior тоже есть бесплатные лабы (миссии) в рамках проекта coach. Очень нравится подход, когда виден и код, и сама страница, и дают сценарий атаки.
Вот, для примера, https://mission.securecodewarrior.com/missions/undefined/cve-2023-20860 - предлагают посмотреть, как эксплуатируется уязвимость в Spring MvcRequestMatcher

Всего доступно 8 миссий в бесплатной версии, но они хороши
👍3🔥2
уязвимость с CVSS 10.0 в pac4j-jwt , достаточно распространенной Java библиотеке для реализации аутентификацией. Ошибка очень прикольная - чек не в том месте. С кем не бывает.

полный флоу поиска, подтверждения и построения эксплойта для уязвимости доступен здесь: https://www.codeant.ai/security-research/pac4j-jwt-authentication-bypass-public-key

Классно, когда ИИ помогает сделать опенсорс безопаснее. Классно, что такие ресерчи публикуют.
🔥8
Пара объявлений

1. Классная конференция AppSecFest открыла CFP и уже доступны билеты (онлайн бесплатно, оффлайн недорого (имхо)). С каждым годом конференция все интереснее и ребята большие молодцы, поэтому вот ссылка на конфу https://appsecfest.kz/

2. В одном из чатов студенты попросили помощи в проведении опроса. Если вы студент или были им ещё недавно, поддержите ребят. Вдруг им действительно это будет полезно.

https://docs.google.com/forms/d/e/1FAIpQLSe_KCINkaTwb9ZbLISrOEBmhINjfGbPV2nytSOJHAeq_ZgzFg/viewform
👍4🔥1