Что нового в OWASP ASVS 5.0
Если вы забыли, что это, то можно почитать вот тут
В мае вышел новый релиз OWASP ASVS (самый большой за последние пять лет). И, как мне кажется, новая версия стала гораздо удобнее для разработчиков.
Но самое первое, что бросается в глаза, это изменения в области уровней защищенности. Если коротко, ASVS предлагает пачки контролей, соответствующие уровням L1, L2, L3, где L1 - базовая безопасность, а L3 - продвинутый уровень, соответствующий высокой зрелости продукта. Каждый уровень описывается своим набором требований\контролей, которые применяются к коду и, если все требования выполнены, можно считать, что мы соответствуем какому-то уровню.
Так вот. В старой версии ASVS 4.0.3 для соответствия уровню L1 нужно было выполнить 131 условие. В новой - всего 70. И несмотря на кажущееся противоречие (вроде как время идет, средний уровень зрелости должен расти), этот шаг весьма оправдан и является следствием жарких дискуссий. И здесь важно понимать, что высокое количество правил уровня L1, по всей видимости, являлось одной из причин того, что компании, начиная работать с ASVS, либо не доводили до соответствия первому уровню, либо в принципе бросали всю эту затею(все чаще думаю о том, что с безопасностью надо как с аллергеном - сперва малыми дозами, чтобы не вызывало сразу прям отторжения)
А еще все ожидали от этой версии правил работы с продуктами, использующими LLM, и не дождались. Авторы решили, что это заслуживает отдельного стандарта - и вот он .
А вот из реально прикольного - совсем новый раздел про пост-квантовую криптографию и сокращение длины минимально необходимого пароля (прикиньте! но там хитрая формулировка. Раньше было про "минимальную" длину пароля в 12 символов, сейчас стало "минимальная" - 8, а вот рекомендованная - 15. Но вообще, конечно, все уже присматриваются к историям без паролей).
В общем, новый документ ёмче, в нем меньше дублирования, убрано явно устаревшее и неактуальное и складывается ощущение, что новый документ еще больше адпатирован под разработчиков, а не под безопасников. И это не может не радовать.
Если вы забыли, что это, то можно почитать вот тут
В мае вышел новый релиз OWASP ASVS (самый большой за последние пять лет). И, как мне кажется, новая версия стала гораздо удобнее для разработчиков.
Но самое первое, что бросается в глаза, это изменения в области уровней защищенности. Если коротко, ASVS предлагает пачки контролей, соответствующие уровням L1, L2, L3, где L1 - базовая безопасность, а L3 - продвинутый уровень, соответствующий высокой зрелости продукта. Каждый уровень описывается своим набором требований\контролей, которые применяются к коду и, если все требования выполнены, можно считать, что мы соответствуем какому-то уровню.
Так вот. В старой версии ASVS 4.0.3 для соответствия уровню L1 нужно было выполнить 131 условие. В новой - всего 70. И несмотря на кажущееся противоречие (вроде как время идет, средний уровень зрелости должен расти), этот шаг весьма оправдан и является следствием жарких дискуссий. И здесь важно понимать, что высокое количество правил уровня L1, по всей видимости, являлось одной из причин того, что компании, начиная работать с ASVS, либо не доводили до соответствия первому уровню, либо в принципе бросали всю эту затею
А еще все ожидали от этой версии правил работы с продуктами, использующими LLM, и не дождались. Авторы решили, что это заслуживает отдельного стандарта - и вот он .
А вот из реально прикольного - совсем новый раздел про пост-квантовую криптографию и сокращение длины минимально необходимого пароля (прикиньте! но там хитрая формулировка. Раньше было про "минимальную" длину пароля в 12 символов, сейчас стало "минимальная" - 8, а вот рекомендованная - 15. Но вообще, конечно, все уже присматриваются к историям без паролей).
В общем, новый документ ёмче, в нем меньше дублирования, убрано явно устаревшее и неактуальное и складывается ощущение, что новый документ еще больше адпатирован под разработчиков, а не под безопасников. И это не может не радовать.
owasp.org
OWASP Artificial Intelligence Security Verification Standard AISVS Docs | OWASP Foundation
OWASP AI verification standard for developers and testers
🔥6👍1
В последнее время стала часто попадаться либо эта бага, либо близко связанные с ней. Причем не только мне, в статьях и разборах стала тоже часто фигурировать (хотя казалось бы). Предлагаю посмотреть кусочек кода и ответить на вопрос, что с ним не так (там две баги. Одна основная, вторая случайно затесалась). И главное - как такое атаковать.
встречается это дело и в других языках, но пример на Java
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserRepository userRepo;
@PostMapping
public User createUser(@RequestBody Map<String, Object> payload) {
User user = new User();
user.setUsername((String) payload.get("username"));
user.setPassword((String) payload.get("password"));
if (payload.containsKey("role")) {
user.setRole((String) payload.get("role"));
} else {
user.setRole("USER");
}
return userRepo.save(user);
}
}
встречается это дело и в других языках, но пример на Java
Поскольку в целом как-то нехорошо отделять безопасность приложений от безопасности сред, в которых они запускаются, считаю важным делиться и такими штуками тоже.
Офигенная диаграмма безопасности для k8s, на которую можно ориентироваться при работе со своими кластерами.
https://kubesec-diagram.github.io/
Офигенная диаграмма безопасности для k8s, на которую можно ориентироваться при работе со своими кластерами.
https://kubesec-diagram.github.io/
kubesec-diagram.github.io
Interactive annotated security focused kubernetes diagram.
🔥3👍2
Пятница, а значит, пора разобрать пример, про который писала на этой неделе.
Но перед этим важный комментарий, про который сказали в одном из чатиков - контроль может быть реализован и в других местах. Но чаще всего он не реализован нигде. Как мне кажется, основная задача подобного рода тасков - натренировать глаза видеть потенциально опасные моменты на код ревью. И лучше уж перепроверить, что в другом месте контроль реализовали, а также что он корректен и достаточен, и потом сливать код с чистой совестью.
Если возвращаться к примеру, то в нем есть в том числе вот такой замечательный фрагмент:
Если в запросе от пользователя пришло поле
Уязвимость в примере - чисто логическая, она не задетектится ни статанализатором, ни, будем честны, стандартным процессом QA, если вы заранее с QA не обговаривали, что и такое может случиться. И это тот самый случай, когда чеклисты спасают. Зафиксированные, конкретные чеклисты, содержащие список того, на что обратить внимание.
Более интересный и массовый вариант уязвимости, который может возникнуть в схожем коде, и который получил название Mass Assignement, когда фреймворк дает нам сбайндить параметры запроса напрямую в объекты. И что хорошо - во фреймворках, которые позволяют это сделать, все предусмотрено - всегда есть возможность завайтлистить то, что нам нужно, или заблеклистить.
резюмируя:
1. Код ревью - это такой момент в разработке, когда можно поймать кучу проблем безопасности, непонятных для остальных этапов.
2. Фронт бэку не друг и не товарищ, и наоборот тоже. За свои действия несем ответственность сами и перепроверяем.
3. Инструмент и его возможности всегда надо использовать правильно.
4*. Блэклисты - лучше, чем ничего, вайтлисты - лучше блэклистов.
ну и ссылки
Spring MVC https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/DataBinder.html#setAllowedFields-java.lang.String...-:~:text=custom%20editors%2C%20etc.-,WARNING,-%3A%20Data%20binding%20can
nodeJS https://underscorejs.org/#pick
Python(Django) https://www.coffeeonthekeyboard.com/mass-assignment-security-part-10-855/
PHP Laravel + Eloquent
https://laravel.com/docs/5.2/eloquent#mass-assignment
Но перед этим важный комментарий, про который сказали в одном из чатиков - контроль может быть реализован и в других местах. Но чаще всего он не реализован нигде. Как мне кажется, основная задача подобного рода тасков - натренировать глаза видеть потенциально опасные моменты на код ревью. И лучше уж перепроверить, что в другом месте контроль реализовали, а также что он корректен и достаточен, и потом сливать код с чистой совестью.
Если возвращаться к примеру, то в нем есть в том числе вот такой замечательный фрагмент:
if (payload.containsKey("role")) {
user.setRole((String) payload.get("role"));
} else {
user.setRole("USER");
}
Если в запросе от пользователя пришло поле
role, выставить роль в его значение, иначе сделать роль "USER". И если в этом месте вам хочется спросить "да кто же так пишет", то спешу вас обрадовать - еще как пишут. Например в рассчете на то, что сам запрос корректно сформирует фронт. Уязвимость в примере - чисто логическая, она не задетектится ни статанализатором, ни, будем честны, стандартным процессом QA, если вы заранее с QA не обговаривали, что и такое может случиться. И это тот самый случай, когда чеклисты спасают. Зафиксированные, конкретные чеклисты, содержащие список того, на что обратить внимание.
Более интересный и массовый вариант уязвимости, который может возникнуть в схожем коде, и который получил название Mass Assignement, когда фреймворк дает нам сбайндить параметры запроса напрямую в объекты. И что хорошо - во фреймворках, которые позволяют это сделать, все предусмотрено - всегда есть возможность завайтлистить то, что нам нужно, или заблеклистить.
резюмируя:
1. Код ревью - это такой момент в разработке, когда можно поймать кучу проблем безопасности, непонятных для остальных этапов.
2. Фронт бэку не друг и не товарищ, и наоборот тоже. За свои действия несем ответственность сами и перепроверяем.
3. Инструмент и его возможности всегда надо использовать правильно.
4*. Блэклисты - лучше, чем ничего, вайтлисты - лучше блэклистов.
ну и ссылки
Spring MVC https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/DataBinder.html#setAllowedFields-java.lang.String...-:~:text=custom%20editors%2C%20etc.-,WARNING,-%3A%20Data%20binding%20can
nodeJS https://underscorejs.org/#pick
Python(Django) https://www.coffeeonthekeyboard.com/mass-assignment-security-part-10-855/
PHP Laravel + Eloquent
https://laravel.com/docs/5.2/eloquent#mass-assignment
cheatsheetseries.owasp.org
Mass Assignment - OWASP Cheat Sheet Series
Website with the collection of all the cheat sheets of the project.
👍4🔥2
https://t.me/art_code_ai/11
Попалась статья (в telegraph, но instant view) про то, как можно накосячить при работе со структурированными данными. Прям рекомендую посмотреть не косячит ли парсер, который используете вы в вашем стеке - можно узнать много удивительного.
Попалась статья (в telegraph, но instant view) про то, как можно накосячить при работе со структурированными данными. Прям рекомендую посмотреть не косячит ли парсер, который используете вы в вашем стеке - можно узнать много удивительного.
Telegram
Искусство. Код... ИИ?
Не рассчитывал, что тут сходу появятся посты, не влезающие в тележные 4к символов, и впредь обязательно постараюсь быть сдержаннее... но чёт не удержался: https://telegra.ph/Po-sledam-prostrelennyh-nog-v-parserah-Go-i-ne-tolko-06-21
👍2🔥1
ок, про SQL инъекции можно говорить вечно, но они все равно продолжают встречаться (правда, во все более экзотических местах). Обсуждали тут с друзьями SQL инъекции в Java (естественно, Spring) и вспомнилась статья https://www.baeldung.com/sql-injection
и вот тут важный момент - все вроде запомнили, что не надо конкатенацию делать, но есть и такие приколы:
Spring заинжектит sortField в ORDER BY. Как есть.
и вот тут важный момент - все вроде запомнили, что не надо конкатенацию делать, но есть и такие приколы:
@GetMapping("/users")
public List<User> list(@RequestParam("sort") String sortField) {
return userRepo.findAll(Sort.by(sortField));
}
Spring заинжектит sortField в ORDER BY. Как есть.
Baeldung on Kotlin
SQL Injection and How to Prevent It? | Baeldung
Explore coding mistakes in Java that can lead to a vulnerable application and how to avoid them using the APIs available in the JVM's standard runtime library.
👍2🤔1
Мелкая, но важная деталь
Всем привет! сегодня хочу предложить почитать еще немного уязвимого кода(в этом есть какой-то свой кайф, не правда ли?) . Уязвимость, которая объединяет эти фрагменты, имеет очень низкий уровень критичности. И поэтому ее часто пропускают на код ревью. Проблема обычно всплывает гораздо позже, чем этапы написания, запуска и зачастую даже во время эксплуатации проблема очень хорошо скрывается. Итак, что не так с кодом ниже и как бы вы это проэксплуатировали, будь вы на месте злоумышленника?
Java, Spring
PHP, Laravel
Node.js
.Net
Всем привет! сегодня хочу предложить почитать еще немного уязвимого кода
Java, Spring
@GetMapping("/search")
public void search(@RequestParam String q) {
log.info("User search query: " + q);
}
PHP, Laravel
public function search(Request $request) {
$q = $request->input('q');
Log::info("User search query: $q");
}
Node.js
app.get('/search', (req, res) => {
const q = req.query.q;
console.log("User search query: " + q);
});
.Net
[HttpGet("search")]
public IActionResult Search(string q)
{
_logger.LogInformation("User search query: " + q);
return Ok();
}
🤔5👍4
>>> To address this challenge, GitLab's Vulnerability Research team recently developed an automated detection system designed to proactively identify malicious dependencies in software supply chains
понятное дело, они дают инструменты безопасности у себя в продукте и наверняка вопросами собственной безопасности всерьез озабочены, но какой кайф читать о том, как разработческая компания внутри ведет security исследования. А теперь вопрос к разработчикам в чате (риторический ): у вас в компании SCA работает?) не просто стоит, а прям работает?)
понятное дело, они дают инструменты безопасности у себя в продукте и наверняка вопросами собственной безопасности всерьез озабочены, но какой кайф читать о том, как разработческая компания внутри ведет security исследования. А теперь вопрос к разработчикам в чате (
Forwarded from Бесконечное ИТ
Интересный пост в блоге Gitlab о том, как они обнаружили supply chain attack в модуле для GO. В компании есть своя комбинированная система обнаружения таких атак. Это смесь песочницы, анализа работы кода подключаемого модуля + ревью модуля человеком. Всегда впечатляет когда такие системы конструируются и создаются в компании самостоятельно, это ли не из показатель развитой инженерной культуры.
https://about.gitlab.com/blog/gitlab-catches-mongodb-go-module-supply-chain-attack/
https://about.gitlab.com/blog/gitlab-catches-mongodb-go-module-supply-chain-attack/
about.gitlab.com
GitLab catches MongoDB Go module supply chain attack
Learn how GitLab detected a supply chain attack targeting Go developers through fake MongoDB drivers that deploy persistent backdoor malware.
❤3👍2
Log injections📖
Пришла пятница, значит, пора разобраться с уязвимостью, про которую говорили в начале недели. Хочу немного поговорить о том, что может сделать злоумышленник с этой, на первый взгляд непримечательной, багой.
Если вспомнить методологию моделирования угроз STRIDE, то там есть целый раздел про Repudiation - отрицание того, что что-то произошло. Или как злоумышленник скроет следы. Скрывают их не только для того, чтобы не нашли пользователя (айпишник, вотэвер), с которого произошла атака, но и для того, чтобы не так-то просто было понять, какую уязвимость эксплуатировали. Итак, давайте посмотрим пример:
Злоумышленник может послать такой запрос (ведь его задача "вшить" в полотно логов что-то похожее на обычный лог):
И теперь лог будет выглядеть так:
А что если попробовать такое? А вдруг салертит?
И вот тут важный момент, а что происходит с нашими логами дальше? одно дело, если они молча хранятся какое-то время и никто никогда в них не заглядывает (ц-ц-ц). Если возникнет инцидент и мы до них дойдем, то такими методами атакующий запутает нас. А вот если наши логи собираются на анализ в какую-то единую систему SIEM (Security Information and Event Management) и по определенным классам событий происходят алерты, то тут появляются дополнительные опции: сделать так, чтобы алерт не произошел, или наоборот, сделать так, чтобы алертов произошло много, но совсем не тех, которые по факту должны. В общем, с этой штукой можно здорово нашкодить. Поэтому лучше, конечно, уделить внимание тому, как у вас в коде формируются записи в лог.
Пришла пятница, значит, пора разобраться с уязвимостью, про которую говорили в начале недели. Хочу немного поговорить о том, что может сделать злоумышленник с этой, на первый взгляд непримечательной, багой.
Если вспомнить методологию моделирования угроз 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
Forwarded from Сертификат безопасности
Распространите https://t.me/addlist/6jf2GaVH7CM2M2I6
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
KazInfoSec
Askar invites you to add the folder “KazInfoSec”, which includes 20 chats.
❤1👍1
Потенциальная уязвимость при динамическом определении типа или не самый очевидный таск на secure code review
Недавно попалась довольно любопытная уязвимость, которая, вероятно, встречается все же чаще, чем можно подумать, и попадает в OWASP A01:2021. Предлагаю вам посмотреть на примеры кода и подумать, что может пойти не так (пример в целом не очень хороший, но я все же искренне надеюсь, что такие таски в ком-то разовьют способность глазами видеть проблемы безопасности, поэтому enjoy).
Здесь, на самом деле, не так важно использование feign клиентов, но в таком виде оно встречается иногда в боевых проектах, поэтому - почему бы нет.
А если вдруг вам проще читать PHP, то относительно аналог вот:
Вот представьте, пришло вам такое на ревью еще в процессе активной разработки проекта. Что может пойти не так? что бы вы перепроверили и какие контроли добавили?
Недавно попалась довольно любопытная уязвимость, которая, вероятно, встречается все же чаще, чем можно подумать, и попадает в 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. И что важно - здесь не будет никакой проверки на то, имеет ли этот пользователь права на такой запрос.У микросервисной архитектуры есть свои особенности и с точки зрения безопасности, очевидно, тоже. Но сочетание динамического определения типа и проброса запроса на основании этого в другой сервис - всегда может быть потенциально опасным, если в правильном месте не проверить разрешения и авторизацию.
🔥3❤1
UUID != Authorize
Зачастую, когда в продукте обнаруживают уязвимость типа IDOR (Insecure Direct Oblect Reference), одно из первых решений, которое принимает команда, - заменить целочисленный идентификатор на UUID(Universally Unique Identifier). И, к сожалению, зачастую на этом и останавливается. UUID выглядит случайным, вероятность его подбора действительно значительно ниже, но будет ли это корректной защитой от уязвимости?
К сожалению, нет. Даже если просто внимательно посмотреть на название уязвимости, становится понятно, что суть-то не в айдишнике, а в том, что работаем мы с ним небезопасно. IDOR все еще на месте, хоть эксплуатация перестала быть такой уж простой. Какие есть варианты:
- самое топорное - Вы забудете закрыть эндпоинты \list, \all, или что-то тому подобное. Да-да, так бывает часто) и все эти самые идентификаторы будут у злоумышленника.
- злоумышленник найдет записи в логах, или еще круче - выманит у пользователя ссылку с помощью какой-нибудь социальной инженерии
- некоторые подмножества можно подобрать, например, UUIDv1 не такой уж случайный, как принято думать - зная один из них и ориентировочное время, когда он был создан, можно попытаться угадать некоторые индентификаторы, созданные в близкое к нему время
- в качестве тестового часто используется
И если, например, вы используете UUID для идентификации важных файлов... в общем, суть вы поняли.
Если у вас есть еще варианты, как к злоумышленнику может попасть валидный UUID из вашего проекта, пишите в комментах)
Использование UUID никогда не станет заменой корректной реализации контроля доступа. Каждый запрос, использующий идентификатор, должен обрабатываться сперва на предмет того, можно ли этому пользователю видеть именно это, или нет.
Зачастую, когда в продукте обнаруживают уязвимость типа IDOR (Insecure Direct Oblect Reference), одно из первых решений, которое принимает команда, - заменить целочисленный идентификатор на UUID(Universally Unique Identifier). И, к сожалению, зачастую на этом и останавливается. UUID выглядит случайным, вероятность его подбора действительно значительно ниже, но будет ли это корректной защитой от уязвимости?
К сожалению, нет. Даже если просто внимательно посмотреть на название уязвимости, становится понятно, что суть-то не в айдишнике, а в том, что работаем мы с ним небезопасно. IDOR все еще на месте, хоть эксплуатация перестала быть такой уж простой. Какие есть варианты:
- самое топорное - Вы забудете закрыть эндпоинты \list, \all, или что-то тому подобное. Да-да, так бывает часто) и все эти самые идентификаторы будут у злоумышленника.
- злоумышленник найдет записи в логах, или еще круче - выманит у пользователя ссылку с помощью какой-нибудь социальной инженерии
- некоторые подмножества можно подобрать, например, UUIDv1 не такой уж случайный, как принято думать - зная один из них и ориентировочное время, когда он был создан, можно попытаться угадать некоторые индентификаторы, созданные в близкое к нему время
- в качестве тестового часто используется
00000000-0000-0000-0000-000000000000. И об этом знаем не только мы с вами. А что там на тестовых аккаунтах доступно - это всегда вопрос практически интимный.И если, например, вы используете UUID для идентификации важных файлов... в общем, суть вы поняли.
Если у вас есть еще варианты, как к злоумышленнику может попасть валидный UUID из вашего проекта, пишите в комментах)
Использование UUID никогда не станет заменой корректной реализации контроля доступа. Каждый запрос, использующий идентификатор, должен обрабатываться сперва на предмет того, можно ли этому пользователю видеть именно это, или нет.
👍4❤2🔥1
Попробуем найти уязвимость в этом фрагменте кода?
Злобная распространенная штука) Для разнообразия - Express.js, но такое можно найти и в проектах на куче других фреймворков.
И по традиции - ИИ это уже знает, и, понятное дело, подскажет.Если настроен. И если обратите внимание. Ведь когда-то крутой фичей пакетных менеджеров стала возможность получать информацию о том, что нужно обновить библиотеку, а на сегодняшний день это статистически самая пропускаемая мимо сознания информация. Есть опасения, что и подсказки о таких уязвимостях могут быть пропущены, поэтому, имхо, все же лучше актуализировать и в своей голове информацию тоже.
Злобная распространенная штука) Для разнообразия - 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
В этот понедельник в канале был опубликован следующий фрагмент кода:
с вопросом о том, все ли в порядке с безопасностью. Давайте разберемся, что же с ним не так. Приведенный пример содержит довольно критичную уязвимость, связанную с байпасом аутентификации из-за неправильного порядка следования инструкций. В частности здесь middleware описывается после того, как был описан один из роутов, к которому по идее этот middleware должен был быть применен. В итоге каждая строка по отдельности выглядит хорошо, паттерны из туториалов и бест-практис выполнены, но вот порядок следования инструкций приводит к уязвимости. А все дело в том, что middleware должен быть описан ДО роутов, т.к. его правила применяются только к тому, что следует строго за ним. И не распространяются на код выше. И такое поведение встречается много где, хотя в других языках\фреймворках могут несколько отличаться конкретные кейсы.
Spring Boot
Laravel
Как возникают такие уязвимости? например, при дописывании новых роутов можно по неосторожности вынести их в неподходящее место. Заметит ли такое статанализатор? кажется, что по идее может, но шибко специфичные данные да и знать, что чем должно быть защищено, анализатор не может. Я такие вещи чаще вижу глазами и не припомню, чтобы кто-то из анализаторов ругался. ИИ тоже интересно себя ведет - если название роута неочевидное, то может и не ругнуться (даже Claude, даже с учетом того, что я с ним всегда общаюсь про безопасность, очевидно. Нейминг важен, да?). Поэтому будьте бдительны.
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/
Сегодня у меня есть две вещи, которыми хочется поделиться. Первая - хочу познакомить еще с одним проектом 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/
owasp.org
OWASP Top 10 for Business Logic Abuse | OWASP Foundation
A very brief, one-line description of your project
👍5🔥2
А есть ли среди вас те, кто пробовал фичу code security review от Claude? Поделитесь мнением - удобно ли это, как сработало, были ли особенности, которые не находились?
https://mostafahussein.medium.com/ai-powered-code-security-reviews-for-devsecops-with-claude-12baeacf196f
https://mostafahussein.medium.com/ai-powered-code-security-reviews-for-devsecops-with-claude-12baeacf196f
Medium
AI-Powered Code Security Reviews for DevSecOps with Claude
Software is being built faster than ever, and that makes it easier for security issues to slip through. That’s why catching flaws early in…
Сегодня предлагаю посмотреть на фргамент реального кода из реальной библиотеки. Этой уязвимости была присвоена 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 });
});
🔥2❤1