Ко(д)тики и безопасность
512 subscribers
20 photos
8 files
101 links
Канал о безопасной разработке для программистов и не только.
Download Telegram
Forwarded from PWN AI (Artyom Semenov)
Почему LLM всё ещё генерируют уязвимый код. Результаты A.S.E Benchmark

В недавнем исследовании был представлен бенчмарк A.S.E (AI Code Generation Security Evaluation), который оценивает способность языковых моделей генерировать безопасный код в условиях, максимально приближённых к реальной разработке. В этом посте мы разберём: чем A.S.E отличается от предыдущих подходов, какие результаты он показал на ведущих моделях и почему они до сих пор уязвимы.

Главное отличие A.S.E в том, что проверка проводится на уровне целого репозитория, а не как это было раньше, на отдельных участках кода. Это позволяет учитывать архитектуру проекта, взаимосвязь файлов и внешние зависимости. Основой для бенчмарка стали реальные репозитории в GitHub с зафиксированными CVE и опубликованными патчами.

Чтобы избежать банального запоминания шаблонов небезопасного кода, разработчики бенчмарка добавили семантические и структурные мутации уязвимостей. Ещё одна важная деталь — автоматическая проверка с помощью правил статического анализа, которые отслеживают источник уязвимости, пути распространения данных и точку эксплуатации, что делает бенчмарк ближе к условиям, которые можно встретить при реальной разработке.
Результаты оказались показательными.

Среди 26 протестированных моделей ни одна не достигла уровня, который бы позволял назвать модель “Best FOR Security Generated CODE”. Лучший общий результат продемонстрировал Claude-3.7-Sonnet, однако его показатели по безопасности существенно отставали от качества кода. При этом наивысший балл именно по безопасности получила модель Qwen3-235B-A22B-Instruct, что указывает на сближение открытых и проприетарных решений в этой области. Самое впечатляющее — reasoning-режимы не помогали исправлять уязвимости, а делали код менее безопасным. Самой проблемной категорией уязвимостей оказался Path Traversal: почти все модели систематически ошибались при обработке путей и проверке доступа к файлам.

На мой взгляд, ценность A.S.E заключается именно в том, что он вскрывает технические слабости LLM, которые не видны на синтетических бенчмарках (хотя, к слову, их сейчас стало заметно меньше). Эти слабости отражают важную проблему: модели хорошо справляются с синтаксисом и общей структурой кода, но по-прежнему не способны достойно учитывать требования безопасности. Я думаю, что в течение года мы увидим заметный прогресс, но пока ситуация остаётся далёкой от уровня, который позволял бы доверять LLM генерацию кода без постоянной проверки.
👍81
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