"Скажи пароль" или как работать со свойством СохраняемоеЗначениеПароля объекта типа ПользовательИнформационнойБазы

Ряд статей уже затрагивали тему проверки текущего пароля пользователя и работу со свойством "СохраняемоеЗначениеПароля", но конкретики по данному вопросу мало. Данная короткая статья призвана исправить этот пробел.

Америку открывать никому не собираюсь, но как это ни странно, после получаса блуждания по просторам интернета я так и не нашёл конкретного описания, как можно сравнить введённый пароль с паролем текущего пользователя без его модификации (как это, например, реализовано в публикации 102655).

На деле всё оказалось довольно просто. В справке к свойству СохраняемоеЗначениеПароля объекта типа ПользовательИнформационнойБазы написано:

Содержит хранимые значения пароля (хеш-функции) и хранимые значения пароля в верхнем регистре (хеш-функции) разделенные запятой.

Только не указано, какие конкретно для этого используются хэш-функции. Для значения пароля «Привет» свойство содержит строку «KAWujn4S8YITX5L7kIQ7sQgNO+g=,c9a04UjoS/W0iLeU7GUa9/Ltd1E=».

Немного покопавшись в «сети», можно найти такую формулировку «sha-1, обёрнутый в base64». Складывая всё вместе, выводим следующий алгоритм:

Функция ПолучитьХешПароля(Пароль) Экспорт

Хеш = Новый ХешированиеДанных(ХешФункция.SHA1);
Хеш.Добавить(Пароль);
Возврат Base64Строка(Хеш.ХешСумма);

КонецФункции

Проверяем на нашем пароле «Привет» и убеждаемся, что получившееся значение действительно совпадает с левой частью из сохраненного хеша.

Дальше с помощью функции получаем текущее значение свойства СохраняемоеЗначениеПароля, не забывая установить привилегированный режим (т.к. «доступно только пользователю с административными правами»), декомпозируем его на регистрозависимую (слева от запятой) и регистронезависимую (справа) части и сравниваем полученные значения.

Функция ПроверитьТекущийПарольПользователя(Пароль, РегистроНезависимый=Истина) Экспорт

УстановитьПривилегированныйРежим(Истина);
ХешТекущегоПароля = ПользователиИнформационнойБазы.ТекущийПользователь().СохраняемоеЗначениеПароля;
УстановитьПривилегированныйРежим(Ложь);

Если ХешТекущегоПароля = Пароль Тогда Возврат Истина КонецЕсли; // Пароль совпадает с СохраняемоеЗначениеПароля только в случае пустого значения

ПозицияРазделителя = Найти(ХешТекущегоПароля, ",");
Результат = Ложь;
Если РегистроНезависимый Тогда
Результат = ПолучитьХешПароля(ВРег(Пароль)) = Прав(ХешТекущегоПароля, СтрДлина(ХешТекущегоПароля) - ПозицияРазделителя);
Иначе
Результат = ПолучитьХешПароля(Пароль) = Лев(ХешТекущегоПароля, ПозицияРазделителя - 1);
КонецЕсли;

Возврат Результат;

КонецФункции

Вуаля! Ну, и на последок приведу еще функцию, формирующую значение свойства СохраняемоеЗначениеПароля из введенного пароля.

Функция ПолучитьСохраняемоеЗначение(Пароль) Экспорт

Возврат ?(ЗначениеЗаполнено(Пароль),ПолучитьХешПароля(Пароль) + "," + ПолучитьХешПароля(ВРег(Пароль),"");

КонецФункции

15 Comments

  1. Olga_Analyst programmer

    Благодарю за статью, пригодилась.

    Reply
  2. bonv

    Как-то у вас получилось одевание штанов через голову. Не проще ли программно получать сохраняемое значение пароля и сравнивать его с хранимым в базе?

    Не учитывается незаполненный пароль, для него сохраняемое значение пароля равно «».

    Для себя когда-то сделал обработку (см. вложение).

    Также в БП что-то похожее есть в модуле

    ЭлектроннаяПодписьВМоделиСервисаСлужебный

    Reply
  3. rtnm

    Меня смущает что 1С не использует при хэшировании «соль»(разную для каждого пользователя или хотя бы единую на всю базу). В этом случае восстановить(подобрать) пароли пользователей становится гораздо проще.

    Reply
  4. mbreaker

    (2) bonv, за конструктивную критику о проверке на пустое значение благодарствую, в код добавил коррективы.

    А вот про «одевание штанов через голову» давайте разберём, у кого же оно получилось «через голову».

    Во-первых, откуда брать значение текущего пароля (из БД или из сеанса) — это исключительно зависит от подхода разработчика. Например, в НФ при смене пароля (меню Сервис — Параметры пользователя) разработчики платформы проверяют введённый пароль сеанса, т.е. из ПользователиИнформационнойБазы.ТекущийПользователь() (проверено эмпирически), разработчики БСП в приведённом Вами примере проверяют значение из БД, т.к. в функцию пользователь передается параметром.

    Во-вторых, я совершенно не понял фразы «не проще ли программно получать сохраняемое значение пароля». А я его аппаратно что-ли получаю?

    В-третьих, небольшой совет на будущее: прежде чем добавлять в свои сообщения едкий сарказм стоит получше вникнуть в комментируемый текст, дабы потом не было стыдно за сказанное. В статье приведён пример функции, которая в зависимости от передаваемого 2-го параметра сравнивает пароль в зависимой от регистра форме и в независимой. В какой форме проверять — остается на выбор использующего. В Вашей же обработке (как впрочем и в функции БСП) сравнение идёт только в регистрозависимом режиме, т.к. проверяются одновременно оба хранимых хэша.

    Ну, и в-четвёртых, почему я не стал оборачивать этот код в обработку, а написал в статье? Потому что если внимательно почитать справку, а потом ещё внимательно почитать мою статью, для получения значения СохраняемоеЗначениеПароля необходимы административные права, а соответственно большинство пользователей использовать эту функцию через обработку не смогут, а установка привилегированного режима во внешней обработке бессмысленна. Соответственно делать это нужно во внутренних механизмах конфигурации, идеально для этого подходят общие формы. Поэтому публикация оформлена в виде статьи, а не обработки (как в Вашем случае).

    Reply
  5. mbreaker

    (3) rtnm, меня много чего смущает в продуктах 1С… но преимущества пока перевешивают… ))

    Reply
  6. bonv

    (4)

    1. В моем комментарии не было замечания по этому пункту

    2.

    я совершенно не понял фразы

    действительно не поняли

    3. Да, действительно, погорячился. Я был не прав, т.к. в моем случае всегда установлена проверка сложности паролей и соответственно используется регистрозависимая проверка. И для моих целей этого достаточно.

    4. О какой публикации речь? Я приложил обработку (ее я сделал задолго до Вашей публикации с целью отладки своей функции), чтобы проиллюстрировать свой комментарий.

    Reply
  7. mbreaker

    (6) bonv,

    1. В моем комментарии не было замечания по этому пункту

    было

    сравнивать его с хранимым в базе

    хоть, похоже, и не умышленно…

    действительно не поняли

    т.е. пояснений не будет?

    в моем случае всегда установлена проверка сложности паролей и соответственно используется регистрозависимая проверка

    к слову сказать, по умолчанию при штатной аутентификации 1С на входе проверка пароля производится без учета регистра (для этого-то в СохраняемоеЗначениеПароля и присутствует хэш пароля в верхнем регистре), но при установке в настройках ИБ (меню Администрирование Параметры информационной базы…) галочки Проверка сложности паролей пользователей она будет производиться уже по регистрозависимой форме. Поэтому при вызове моего варианта это довольно легко реализовать при передаче в функцию вторым параметром выражения НЕ ПолучитьПроверкуСложностиПаролейПользователей(), а в Вашем случае пользователь может в систему войти, а при проверке получить ошибку и долго удивляться.

    О какой публикации речь?

    о моей, которую Вы и комментируете…

    Reply
  8. Bad_Developer

    А кто нибуть разбирался как формируется запись пароля подключения к СУБД в файле srvribrg.lst

    По идеи механизм формирования должен быть похож.

    Пример из файла:

    {6fe8ec41-e16b-422b-9073-cb214248591a,»Torg»,»»,»PostgreSQL»,»dell2900″,»torgovlya»,»postgres»,»X4zp8HCS6WwSInfaP1n6vX+DnyVU0Hj6RwkD8poAcCE=»,»CrSQLDB=Y;DB=torg;DBMS=PostgreSQL;DBSrvr=dell2900;DBUID=postgres;Locale=ru_RU;Ref=torg;SLev=0;Srvr=dell2900;SUsr=»,0,

    {0,00010101000000,00010101000000,»»,»»,»»},0},

    Reply
  9. mbreaker

    (8) Bad_Developer,

    По идеи механизм формирования должен быть похож

    нет, не должен. Потому что здесь пароль шифруется, а не хэшируется. Разница между между этими понятиями проста: в первом случае исходный пароль можно восстановить (дешифровать) обратным алгоритмом, в то время как получение хэша во втором случае — это односторонний процесс и единственный способ выхода на исходный пароль — это «брутфорс» со сравнением результата шифрования.

    Reply
  10. baton_pk

    Это ж до меня тут дошло неожиданно, что если первый и второй хеши совпадают, то это с высоченной долей вероятности говорит о том, что пароль цифровой. Вот дырень-то…

    Reply
  11. mbreaker

    (10) baton_pk, ну допустим «дырень» не в платформе 1С, а в голове администратора системы, т.к. в параметрах информационной базы есть настройка «Проверка сложности паролей пользователей», при установке которой система не допустит использования «цифрового пароля».

    Reply
  12. baton_pk

    (11)

    позволю себе не согласиться 🙂 мы админим магазины через DameWare и чтобы избежать головной боли с разницей раскладок на локальном компе и на удалённом компе, используем длинный цифровой пароль для админа.

    Reply
  13. mbreaker

    (12) baton_pk, я не совсем понял, с чем же высказано несогласие?

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

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

    Только вопрос «дырени», как я его понял, относился к проверке установки паролей пользователями, а не админами. Какой смысл админу в системе самому себе заводить ограничения?

    Reply
  14. baton_pk

    (13)

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

    Хотя это из разряда фантастики всё-таки…

    Reply
  15. donyab

    (10) baton_pk,

    ИЛИ ВСЕ КАПСОМ НАБРАНО)

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *