Безопасность
Максимальная инкапсуляция, ограничение доступа к элементам объекта насколько, насколько это возможно - это главная линия для обеспечения безопасности объектов. Данный подход именуется, как правило, принцип наименьших привелегий - Least Privilege Principle.
Immutable
Один из способов достижения безопасности. Основная стратегия создания:
- Класс должен иметь модификатор
final
; - Все переменные с ограничением доступа
private
; - Для методов
setter
устанавливаются модификаторfinal
; - Ссылки только на immutable объекты (или полные копии оригинальных объектов);
- Установка для всех instance переменных значений из конструктора. Желательно использовать паттерн Builder, либо статические методы для создания объектов.
Идея состоит в том что внутренние данные объекта ни при каких обстоятельствах не должны меняться ни внешними объектами, ни методами внутри объекта. Пример:
1 | private fian class ImmutableObject { |
Даже с учетом модификаторов private
и final
, класс нельзя считать immutable. Переделать класс в immutable можно путем обеспечения безопасности для все объектов, в том числе, для коллекций. Например, так:
1 | this.objects = Lists.of(objects); |
Подобная операция копирования называется защитное копирование, Defensive Copy.
clone()
Метод clone()
становится доступен в случае если класс реализует интерфейс Cloneable
. Но даже в случае клонирования, объект нельзя считать полностью immutable или защищенным!
Базовая реализация clone
создает поверхностную копию объекта - Shallow Copy, т.е. новый объект создается только для верхнего уровня объектов (т.е. для Cloneable
объекта). Для глубокой копии, Deep Copy, придется переписать метод clone()
.
Вывод критичной информации
Необходимо следить за выводом критичной информации.
- В лог;
- В stacktrace;
- В stdout и stderr.
Часто критически важная информация выводится просто в методе toString
.
Критическая информация и память
Хранение критичной информации в памяти в виде строк не рекомендуется:
Если приложение экстренно прервало свою работу и сделал слепок памяти (dump), то высок шанс того что строка останется в слепке. Произойти это может в связи с тем что для оптимизации работы со строками, Java использует string-pool, в котором и могу остаться копии важных данных.
Строку невозможно удалить или переписать принудительно.
По этим причинам, для обеспечения безопасности строк, рекомендуется использовать char[]:
1 | byte[] password = inputStream.readPasswordAsBytes(); |
Когда переписывание невозможно, объекты с критичными данными следует хотя бы очищать сбросом ссылки (установкой null
). Тем самым минимизируется время нахождения критичной информации в памяти.
Привилегии
Java позволяет определять привилегии для программ. Например, для доступа к файлам:
1 | grant { |
DoS
Выделяют несколько проблем при DoS атаках:
- Утечка ресурсов (Resource Leak). В частности, утечка может возникать при работе с файлами и другими внешними ресурсами. Ресурсы всегда должны закрываться и использоваться максимально кратковременно;
- Использование чрезвычайно больших ресурсов;
- Использование потенциально ресурсоёмких источников данных;
- Перетекание чисел. Например, в цикле выполняется проверка инкремента
int
, который при достижении максимальногоint
и очередной итерации, преобразуется в минимальныйint
- это приведет в повторному ложному выполнению большого количества итераций в цикле.