Ко(д)тики и безопасность
512 subscribers
20 photos
8 files
101 links
Канал о безопасной разработке для программистов и не только.
Download Telegram
Интересный пост в блоге Gitlab о том, как они обнаружили supply chain attack в модуле для GO. В компании есть своя комбинированная система обнаружения таких атак. Это смесь песочницы, анализа работы кода подключаемого модуля + ревью модуля человеком. Всегда впечатляет когда такие системы конструируются и создаются в компании самостоятельно, это ли не из показатель развитой инженерной культуры.

https://about.gitlab.com/blog/gitlab-catches-mongodb-go-module-supply-chain-attack/
3👍2
Log injections📖

Пришла пятница, значит, пора разобраться с уязвимостью, про которую говорили в начале недели. Хочу немного поговорить о том, что может сделать злоумышленник с этой, на первый взгляд непримечательной, багой.

Если вспомнить методологию моделирования угроз STRIDE, то там есть целый раздел про Repudiation - отрицание того, что что-то произошло. Или как злоумышленник скроет следы. Скрывают их не только для того, чтобы не нашли пользователя (айпишник, вотэвер), с которого произошла атака, но и для того, чтобы не так-то просто было понять, какую уязвимость эксплуатировали. Итак, давайте посмотрим пример:


@GetMapping("/login")
public ResponseEntity<String> login(@RequestParam String username) {
logger.info("Login attempt by: " + username);
// ... authenticate user
return ResponseEntity.ok("OK");
}


Злоумышленник может послать такой запрос (ведь его задача "вшить" в полотно логов что-то похожее на обычный лог):


/login?username=admin\n2024-06-30 10:00:00 [INFO] Login successful for attacker


И теперь лог будет выглядеть так:


[INFO] Login attempt by: admin
2024-06-30 10:00:00 [INFO] Login successful for attacker



А что если попробовать такое? А вдруг салертит?
username = attacker\n[ERROR] Database compromised


И вот тут важный момент, а что происходит с нашими логами дальше? одно дело, если они молча хранятся какое-то время и никто никогда в них не заглядывает (ц-ц-ц). Если возникнет инцидент и мы до них дойдем, то такими методами атакующий запутает нас. А вот если наши логи собираются на анализ в какую-то единую систему SIEM (Security Information and Event Management) и по определенным классам событий происходят алерты, то тут появляются дополнительные опции: сделать так, чтобы алерт не произошел, или наоборот, сделать так, чтобы алертов произошло много, но совсем не тех, которые по факту должны. В общем, с этой штукой можно здорово нашкодить. Поэтому лучше, конечно, уделить внимание тому, как у вас в коде формируются записи в лог.
👍2🔥2
С днём любимого города!

А тем временем обновилась подборка каналов. Кажется, многие сюда попали из-за неё
4
⚡️ Обновил подборку KazInfoSec - список личных TG-каналов казахстанского ИБ-комьюнити 💭

📣 Распространите 🔈

https://t.me/addlist/6jf2GaVH7CM2M2I6
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
Потенциальная уязвимость при динамическом определении типа или не самый очевидный таск на secure code review

Недавно попалась довольно любопытная уязвимость, которая, вероятно, встречается все же чаще, чем можно подумать, и попадает в OWASP A01:2021. Предлагаю вам посмотреть на примеры кода и подумать, что может пойти не так (пример в целом не очень хороший, но я все же искренне надеюсь, что такие таски в ком-то разовьют способность глазами видеть проблемы безопасности, поэтому enjoy).


@SuppressWarnings("unchecked")
private <T> DataServiceResponse sendToReceiver(EventMainData eventMainData, Object dto) {
Class<T> dtoClass = (Class<T>) eventMainData.getEventType().getDtoClass();
IBaseClient<T> feignClient = clientFactory.getClient(dtoClass);

T castedDto = dtoClass.cast(dto);
return switch (eventMainData.getOperationType()) {
case CREATE -> feignClient.create(castedDto);
case UPDATE -> feignClient.update(eventMainData.getEventId(), castedDto);
case DELETE -> feignClient.delete(eventMainData.getEventId());
default -> throw new IllegalStateException("Unknown operation");
};
}



Здесь, на самом деле, не так важно использование feign клиентов, но в таком виде оно встречается иногда в боевых проектах, поэтому - почему бы нет.

А если вдруг вам проще читать PHP, то относительно аналог вот:


private function sendToReceiver(EventMainData $eventMainData, $dto)
{
$dtoClass = $eventMainData->event_type->dto_class;
$client = $this->clientFactory->getClient($dtoClass);
$castedDto = new $dtoClass($dto);

return match ($eventMainData->operation_type) {
'CREATE' => $client->create($castedDto),
'UPDATE' => $client->update($eventMainData->event_id, $castedDto),
'DELETE' => $client->delete($eventMainData->event_id),
default => throw new \InvalidArgumentException("Unknown operation")
};
}


Вот представьте, пришло вам такое на ревью еще в процессе активной разработки проекта. Что может пойти не так? что бы вы перепроверили и какие контроли добавили?
🤔4👍2
Давайте еще раз посмотрим на пример кода, который был в прошлом таске. Итак, у нас Spring Boot приложение. Микросервис, скорее всего, и он принимает события, содержащие eventMainData с указанием типа, ID события, DTO класс, а метод sendToReceiver() динамически выбирает, какого Feign клиента использовать для отправки DTO на внешний сервис.


@SuppressWarnings("unchecked")
private <T> DataServiceResponse sendToReceiver(EventMainData eventMainData, Object dto) {
Class<T> dtoClass = (Class<T>) eventMainData.getEventType().getDtoClass();
IBaseClient<T> feignClient = clientFactory.getClient(dtoClass);

T castedDto = dtoClass.cast(dto);
return switch (eventMainData.getOperationType()) {
case CREATE -> feignClient.create(castedDto);
case UPDATE -> feignClient.update(eventMainData.getEventId(), castedDto);
case DELETE -> feignClient.delete(eventMainData.getEventId());
default -> throw new IllegalStateException("Unknown operation");
};
}


А что если злоумышленник отправит такое:


{
"eventType": {
"dtoClass": "com.example.dto.UserDto"
},
"eventId": "admin-user-id",
"operationType": "DELETE"
}


Тогда система разрешит UserDto.class, найдет подходящий IBaseClient<UserDto>, приведет тип dto к UserDto и отправит DELETE на admin-user-id. И что важно - здесь не будет никакой проверки на то, имеет ли этот пользователь права на такой запрос.

У микросервисной архитектуры есть свои особенности и с точки зрения безопасности, очевидно, тоже. Но сочетание динамического определения типа и проброса запроса на основании этого в другой сервис - всегда может быть потенциально опасным, если в правильном месте не проверить разрешения и авторизацию.
🔥31
UUID != Authorize

Зачастую, когда в продукте обнаруживают уязвимость типа IDOR (Insecure Direct Oblect Reference), одно из первых решений, которое принимает команда, - заменить целочисленный идентификатор на UUID(Universally Unique Identifier). И, к сожалению, зачастую на этом и останавливается. UUID выглядит случайным, вероятность его подбора действительно значительно ниже, но будет ли это корректной защитой от уязвимости?

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

- самое топорное - Вы забудете закрыть эндпоинты \list, \all, или что-то тому подобное. Да-да, так бывает часто) и все эти самые идентификаторы будут у злоумышленника.
- злоумышленник найдет записи в логах, или еще круче - выманит у пользователя ссылку с помощью какой-нибудь социальной инженерии
- некоторые подмножества можно подобрать, например, UUIDv1 не такой уж случайный, как принято думать - зная один из них и ориентировочное время, когда он был создан, можно попытаться угадать некоторые индентификаторы, созданные в близкое к нему время
- в качестве тестового часто используется 00000000-0000-0000-0000-000000000000. И об этом знаем не только мы с вами. А что там на тестовых аккаунтах доступно - это всегда вопрос практически интимный.

И если, например, вы используете UUID для идентификации важных файлов... в общем, суть вы поняли.

Если у вас есть еще варианты, как к злоумышленнику может попасть валидный UUID из вашего проекта, пишите в комментах)

Использование UUID никогда не станет заменой корректной реализации контроля доступа. Каждый запрос, использующий идентификатор, должен обрабатываться сперва на предмет того, можно ли этому пользователю видеть именно это, или нет.
👍42🔥1
Попробуем найти уязвимость в этом фрагменте кода?

Злобная распространенная штука) Для разнообразия - Express.js, но такое можно найти и в проектах на куче других фреймворков.


app.use((req, res, next) => {
console.log(req.method, req.path);
next();
});

app.post('/admin/delete-user', adminController.deleteUser);

app.use(authMiddleware);


И по традиции - ИИ это уже знает, и, понятное дело, подскажет. Если настроен. И если обратите внимание. Ведь когда-то крутой фичей пакетных менеджеров стала возможность получать информацию о том, что нужно обновить библиотеку, а на сегодняшний день это статистически самая пропускаемая мимо сознания информация. Есть опасения, что и подсказки о таких уязвимостях могут быть пропущены, поэтому, имхо, все же лучше актуализировать и в своей голове информацию тоже.
🔥2👍1
В этот понедельник в канале был опубликован следующий фрагмент кода:


app.use((req, res, next) => {
console.log(req.method, req.path);
next();
});

// Routes
app.post('/admin/delete-user', adminController.deleteUser);

// Auth middleware
app.use(authMiddleware);


с вопросом о том, все ли в порядке с безопасностью. Давайте разберемся, что же с ним не так. Приведенный пример содержит довольно критичную уязвимость, связанную с байпасом аутентификации из-за неправильного порядка следования инструкций. В частности здесь middleware описывается после того, как был описан один из роутов, к которому по идее этот middleware должен был быть применен. В итоге каждая строка по отдельности выглядит хорошо, паттерны из туториалов и бест-практис выполнены, но вот порядок следования инструкций приводит к уязвимости. А все дело в том, что middleware должен быть описан ДО роутов, т.к. его правила применяются только к тому, что следует строго за ним. И не распространяются на код выше. И такое поведение встречается много где, хотя в других языках\фреймворках могут несколько отличаться конкретные кейсы.


Spring Boot

@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").permitAll()
.anyRequest().authenticated()
)
.build();
}
}


Laravel

Route::post('/admin/delete-user', [AdminController::class, 'deleteUser']);

Route::middleware(['auth', 'admin'])->group(function () {
// Other protected routes...
});


Как возникают такие уязвимости? например, при дописывании новых роутов можно по неосторожности вынести их в неподходящее место. Заметит ли такое статанализатор? кажется, что по идее может, но шибко специфичные данные да и знать, что чем должно быть защищено, анализатор не может. Я такие вещи чаще вижу глазами и не припомню, чтобы кто-то из анализаторов ругался. ИИ тоже интересно себя ведет - если название роута неочевидное, то может и не ругнуться (даже Claude, даже с учетом того, что я с ним всегда общаюсь про безопасность, очевидно. Нейминг важен, да?). Поэтому будьте бдительны.
👍6🤯2
Две новости из мира безопасности

Сегодня у меня есть две вещи, которыми хочется поделиться. Первая - хочу познакомить еще с одним проектом OWASP, посвященным вопросам безопасной разработки, https://owasp.org/www-project-top-10-for-business-logic-abuse/# . Когда делаешь свой чек-лист для security code review, можно сделать напоминалки про то, чтобы не забыть чекать авторизацию, не забыть посмотреть, нет ли где ситуации гонок, каких-то вещей еще, которые достоверно не найдет статанализатор. И вот самое сложное (на мой взгляд), это найти и чекнуть потенциальные логические ошибки: какие-то не до конца очевидные пути вычисления, какие-то нетривиальные логические моменты. Да иногда даже и тривиальные. В проекте OWASP Top-10 for Business Logic Abuse авторы собрали как раз топчик категорий именно таких уязвимостей, которые стоит держать в уме. Рекомендую ознакомиться на выходных)


А вторая вещь - это напоминание на случай, если вы забыли, что самая крутая конференция KazHackStan уже открыла регистрацию для пользователей. Ребята все так же верны своим традициям и конференция остается бесплатной, но становится все больше, ярче и круче. И в этом году, как и в прошлом, будет целый день, посвященный безопасной разработке. Регистрируйтесь) https://kazhackstan.com/
👍5🔥2
А есть ли среди вас те, кто пробовал фичу code security review от Claude? Поделитесь мнением - удобно ли это, как сработало, были ли особенности, которые не находились?

https://mostafahussein.medium.com/ai-powered-code-security-reviews-for-devsecops-with-claude-12baeacf196f
Сегодня предлагаю посмотреть на фргамент реального кода из реальной библиотеки. Этой уязвимости была присвоена CVE, но авторы библиотеки так и не исправили ее, несмотря на попытки владельцев платформы hunter.io добиться исправления. Есть инвайт-линки, по которым пользователь может зарегистрироваться. Но с их обработкой что-то не так, предлагаю вам найти, что. Пишите свои варианты в комментариях.

А код прям такой... #ябытожетакнаписал



app.post("/invite/:code", async (request, response) => {
const { code } = request.params;
const { username, password } = reqBody(request);
const invite = await Invite.get({ code });
if (!invite || invite.status !== "pending") {
response.status(200).json({ success: false, error: "Invite not found or is invalid." });
return;
}

const { user, error } = await User.create({ username, password, role: "default" });
if (!user) {
response.status(200).json({ success: false, error: "Could not create user." });
return;
}

await Invite.markClaimed(invite.id, user);
response.status(200).json({ success: true, error: null });
});
🔥21
Принципы и паттерны безопасной разработки: SRP

Хоть это и не вполне очевидно, но разработка безопасных приложений может (а, возможно, и должна) начинаться, отнюдь не с моделирования угроз, внедрения в код механизмов защиты, ревью безопасности, пентестов, внедрения SCA/SAST/DAST, или, тем более, чего-то, вроде хантовского «Hack Yourself First» ✝️ В лучших традициях Shift Left Security, начинать стоит с базовых принципов разработки, таких, как SOLID, YAGNI, DRY, KISS, чистый код с архитектурой и т.п. Именно они позволяют заложить в архитектуру и реализацию приложения правильный фундамент, на котором будет гораздо проще и дешевле реализовывать прочие решения и этапы внедрения DevSecOps.

Начнём с принципа единственной ответственности (Single Responsibility Principle, SRP — первая буква в SOLID), утверждающему, что каждый класс или модуль должен иметь единственную ответственность (только одну причину для изменения). С точки зрения безопасности SRP способствует изолированности компонентов и чётким границам доверия в коде, что существенно облегчает последующую работу с моделью угроз. Когда компонент сконцентрирован на одной задаче, его легче проверять на уязвимости и логические ошибки. Это снижает риск скрытых багов, возникающих при смешении разных обязанностей (например, проверка прав доступа вперемешку с бизнес-логикой). Как отмечают эксперты, соблюдение SRP «ограничивает случайную эскалацию привилегий и упрощает поиск ошибок», а также уменьшает общую поверхность атаки за счёт уменьшения сложности компонентов.

Тривиальный пример: допустим, класс UserAuth одновременно проверяет пароль пользователя и создаёт сессию при входе.

Нарушение SRP может выглядеть так:
class UserAuth {
public Session Authenticate(string username, string password) {
if (!PasswordChecker.IsStrong(password)) {
throw new Exception("Weak password");
}

var user = userRepository.CreateUser(username, password);
return sessionManager.StartSession(user);
}
}


В этом коде смешаны проверки безопасности (надежность пароля) и бизнес-логика сессии. Если разработчик решит изменить логику создания сессии, есть риск ненароком ослабить или обойти шаг проверки пароля. Правильнее разделить эти обязанности на отдельные классы (например, PasswordChecker, UserRepository, SessionManager), а UserAuth сделать оркестратором. Тогда код станет понятнее и безопаснее: каждая часть легко проверяется и тестируется отдельно.

Забавно, что «живым» примером последствий нарушения SRP является одна из наиболее нашумевших уязвимостей в библиотеке логирования Apache Log4j 2 CVE-2021-44228, известная как Log4Shell. Логирование — это задача записи сообщений, но Log4j помимо этого выполнял ещё и роль интерпретатора/поисковика ресурсов (JNDILookup). Фактически, в библиотеку логирования «просочилась» функциональность, выходящая за рамки её единственной ответственности — она не только записывала логи, но и могла выполнять сетевые запросы и загружать код. Если бы Log4j ограничился исключительно записью логов, без вычисления каких-либо lookup-выражений, уязвимость бы не возникла. И действительно, исправление проблемы заключалось в отключении/удалении функции JNDI Lookup из Log4j.

Соблюдение SRP помогает избежать многих CWE, связанных с логическими ошибками и неправильной проверкой условий, которые трудно выявить в нагромождённом коде. Например, SRP предотвращает появление скрытых дефектов управления доступом, из разряда CWE-732, CWE-862, возникающих, когда проверка прав смешана с другими функциями и может быть пропущена.

В целом, SRP укрепляет принцип «secure by design»: мелкие простые модули легче защитить и проверить.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Всем привет! Предлагаю сегодня посмотреть еще на кусочек кода. Мне он нравится тем, что там можно прикопаться по нескольким направлениям, и с точки зрения разработки, и с точки зрения безопасности, но тем не менее, пара агентов именно проблему безопасности здесь увидели далеко не сразу, а с очень конкретными наводящими промтами.

Очень похожая бага была в логике системы начисления бонусов одного из крупных магазинов Астаны в 2021 году, когда в условиях карантина магазины начали быстренько делать свои онлайн версии.

За покупку начисляются баллы, т.е. после того, как пользователь подтвердил получение товара, приложение отправляет запрос на эндпоинт /api/loyalty/earn-points, логика которого описана в коде ниже. Есть продукты в статусе promotion - за них дают чуть больше. Что я как злоумышленник могу сделать здесь?


@RestController
@RequestMapping("/api/loyalty")
public class LoyaltyController {

@Autowired
private LoyaltyService loyaltyService;

@Autowired
private OrderService orderService;

@PostMapping("/earn-points")
public ResponseEntity<String> earnLoyaltyPoints(@RequestBody EarnPointsRequest request) {
try {
User user = getCurrentUser();
Order order = orderService.getOrder(request.getOrderId());

if (order == null || !order.getUserId().equals(user.getId())) {
return ResponseEntity.badRequest().body("Invalid order");
}

for (OrderItem item : order.getItems()) {
int pointsForItem = (int) (item.getPrice() * 0.01);
loyaltyService.addPoints(user.getId(), pointsForItem);

if (isPromotionalProduct(item.getProductId())) {
loyaltyService.addPoints(user.getId(), pointsForItem * 2);
}
}

return ResponseEntity.ok("Points earned successfully");

} catch (Exception e) {
return ResponseEntity.status(500).body("Error processing points");
}
}


А еще хочу рассказать про одно очень классное мероприятие, которое 4 октября пройдет в Алматы - OpenSysConf'25 - https://sysconf.io/2025. Уже в седьмой раз соберутся энтузиасты с горящими глазами, которые обсудят кучу разных вопросов, от безопасности (хардкорной), через администрирование и до ИИ. Если Вы базируетесь в Алматы - очень рекомендую посетить, хоть и не смогу в этом году поучаствовать сама.
🔥61👍1
Ко(д)тики и безопасность
Всем привет! Предлагаю сегодня посмотреть еще на кусочек кода. Мне он нравится тем, что там можно прикопаться по нескольким направлениям, и с точки зрения разработки, и с точки зрения безопасности, но тем не менее, пара агентов именно проблему безопасности…
Malicious logic loop или о важности идемпотентности в операциях


Уязвимость в таске этого понедельника продолжает серию уязвимостей из OWASP Top-10 бизнес-логики. И как совершенно верно было отмечено в коментариях, проблема заключается в том, что обращение к эндпоинту /earn-points по логике никак не завязано на реальную покупку и может быть вызвано отдельно. Таким образом злоумышленник может "накрутить" бонусные баллы, не совершая покупок, за которые они должны даваться.

У этой операции не соблюдается свойство идемпотентности. Простыми словами, для такого рода эндпоинтов важно, чтобы вне зависимости от того, сколько раз к нему обратятся, баллы были начислены только единожды для каждой покупки. Самое простое решение - добавить контроль, который будет проверять, было ли осуществлено начисление уже или еще нет. Но если подойти к предыдущему предложению критически, то там не хватает одной важной детали - начисление и контроль должны быть атомарными, иначе та же проблема будет возникать в более сложном сценарии с гонками.
🔥4
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