Java Basics: Безопасность

Безопасность

Максимальная инкапсуляция, ограничение доступа к элементам объекта насколько, насколько это возможно - это главная линия для обеспечения безопасности объектов. Данный подход именуется, как правило, принцип наименьших привелегий - Least Privilege Principle.

Immutable

Один из способов достижения безопасности. Основная стратегия создания:

  1. Класс должен иметь модификатор final;
  2. Все переменные с ограничением доступа private;
  3. Для методов setter устанавливаются модификатор final;
  4. Ссылки только на immutable объекты (или полные копии оригинальных объектов);
  5. Установка для всех instance переменных значений из конструктора. Желательно использовать паттерн Builder, либо статические методы для создания объектов.

Идея состоит в том что внутренние данные объекта ни при каких обстоятельствах не должны меняться ни внешними объектами, ни методами внутри объекта. Пример:

1
2
3
4
5
6
7
8
9
10
11
private fian class ImmutableObject {
private final List<Object> objects;

private MyObject(List<Object> objects) {
this.objects = objects;
}

public static MyObject createByObject(List<Object> objects) {
return new ImmutableObject(objects);
}
}

Даже с учетом модификаторов 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.

Критическая информация и память

Хранение критичной информации в памяти в виде строк не рекомендуется:

  1. Если приложение экстренно прервало свою работу и сделал слепок памяти (dump), то высок шанс того что строка останется в слепке. Произойти это может в связи с тем что для оптимизации работы со строками, Java использует string-pool, в котором и могу остаться копии важных данных.

  2. Строку невозможно удалить или переписать принудительно.

По этим причинам, для обеспечения безопасности строк, рекомендуется использовать char[]:

1
2
3
byte[] password = inputStream.readPasswordAsBytes();
...
Arrays.fill(password, 'x');

Когда переписывание невозможно, объекты с критичными данными следует хотя бы очищать сбросом ссылки (установкой null). Тем самым минимизируется время нахождения критичной информации в памяти.

Привилегии

Java позволяет определять привилегии для программ. Например, для доступа к файлам:

1
2
3
grant {
Permission java.io.FilePermission "/etc/my/files/document.xml", "read"
}

DoS

Выделяют несколько проблем при DoS атаках:

  • Утечка ресурсов (Resource Leak). В частности, утечка может возникать при работе с файлами и другими внешними ресурсами. Ресурсы всегда должны закрываться и использоваться максимально кратковременно;
  • Использование чрезвычайно больших ресурсов;
  • Использование потенциально ресурсоёмких источников данных;
  • Перетекание чисел. Например, в цикле выполняется проверка инкремента int, который при достижении максимального int и очередной итерации, преобразуется в минимальный int - это приведет в повторному ложному выполнению большого количества итераций в цикле.
 Comments
Comment plugin failed to load
Loading comment plugin