Почему не DriverManager.getConnection (строковый URL, строковый пользователь, пароль char [])? - PullRequest
11 голосов
/ 15 февраля 2010

Мы знаем, что лучше хранить char [], а не java.lang.String для хранения паролей. Это по следующим двум причинам (как я прочитал):

  1. char [] являются изменяемыми, поэтому мы можем очистить пароли после использования.
  2. Строковые литералы отправляются в пул, который не будет собирать мусор, как другие объекты, поэтому может появиться в дампах памяти.

Но java.sql.DriverManager не имеет getConnection (), который бы соответствовал приведенным выше рекомендациям, поскольку его параметр пароля - String.

DriverManager.getConnection (строковый URL, строковый пользователь, строковый пароль)

Я думаю, что API должен иметь перегруженный метод со следующей подписью:

DriverManager.getConnection (строковый URL, строковый пользователь, символ [] пароль)

Что вы думаете об этом? Видите ли вы какой-нибудь альтернативный способ преодолеть этот недостаток?

Хотелось бы услышать ваши мысли.

Ответы [ 6 ]

4 голосов
/ 15 февраля 2010

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

3 голосов
/ 06 апреля 2013

Вы делаете хорошее замечание, и большинство отвечающих пропускают его. В худшем случае «временный» пароль заменяется операционной системой. После этого этот файл подкачки легко читается, а на диске может даже выжить, будучи перезаписан нулями, если у злоумышленника будет около $ 1500 оборудования ...

Лучшее, что вы можете сделать, это подключиться, password = null, после чего следует явный вызов gc (). Если вам повезет, это очистит даже строки, используемые реализациями драйверов.

В любом случае ...

  • То, что вы спрашиваете, в настоящее время невозможно, но было бы неплохо.
  • Даже char [] может выжить при определенных условиях (например, обмен).
  • Ваш пароль будет многократно скопирован по пути к базе данных, поэтому char [] решает только одну часть проблемы.

Реальность такова, что если платформа не предназначена специально для безопасности, все методы являются лишь тактикой отсрочки. Делайте, что можете, но если определенный человек сможет получить доступ к вашей машине, char [] даст вам максимум 1 час.

2 голосов
/ 15 февраля 2010

Аргумент для использования массивов char [] применяется чаще всего, когда пользователь вводит пароль, и вы хотите минимизировать использование этого пароля.

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

В любом случае, стандарт JDBC позволяет передавать пароли в объектах свойств и даже в URL, поэтому я думаю, что наличие параметра char[] password даст вам ложное чувство безопасности.

Если у вас есть реальный случай использования, когда пароль должен быть удален из памяти как можно быстрее, чтобы его невозможно было восстановить, и это имеет смысл в контексте реального приложения JDBC, я хотел бы услышать его. Я могу представить, что такая вещь может существовать, но я не могу вспомнить сценарий, в котором использование char[] действительно делает вещи более безопасными.

2 голосов
/ 15 февраля 2010

Ваша причина №2 - та, которую я видел чаще всего для использования char [] вместо String. Тем не менее, в целом, я думаю, что если вы предполагаете, что кто-то имеет доступ к состоянию вашей программы через отладчик или другие средства, нет никаких причин, по которым он не может также просматривать содержимое символа [].

2 голосов
/ 15 февраля 2010

Можно только строить догадки, если только вы не можете спросить разработчика API.

Мои предположения таковы:

Основной API, который использует char[] вместо String для паролей, о которых я знаю, это JPasswordField. Это делается для того, чтобы позволить программе перезаписать введенный пользователем пароль другими значениями после того, как эти значения были использованы (что невозможно при String, который будет сохраняться в памяти как минимум до это мусор).

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

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

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

</speculation>

1 голос
/ 15 февраля 2010

Ваша точка 1 действительна в некоторой степени, но точка 2 о строках, попадающих в несобранный пул строк, верна только для статических литеральных строк (строк, которые появляются непосредственно в коде). Если вы хотите, чтобы пароли хранились непосредственно в вашем коде, я бы посоветовал сначала позаботиться об этом, так как их гораздо проще найти в файлах классов, чем в работающей виртуальной машине.

Так что, если вы считаете, что должны хранить свои пароли в char [], вы все равно можете создать объект String из него, прежде чем вызывать getConnection (). Если реализация драйвера не хранит строковый объект внутри, он быстро не будет доступен и, следовательно, будет собираться довольно быстро. Единственный шанс прочитать его тогда - это изучить память JVM непосредственно там, где она еще может существовать. Таким образом, вы правы, что использование char [] было бы немного более безопасным, но не настолько, как в любом случае пароль должен был бы быть в памяти в какой-то момент.

т.е. очень простой способ получить пароль с помощью любого API-интерфейса - ввести поддельный драйвер SQL и получить пароль непосредственно в методе connect. Любой, кто сможет проверить память JVM, чтобы найти в ней еще не перезаписанную строку пароля, также сможет вставить модифицированный драйвер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...