Александр Похабов
В этой статье будут рассмотрены решения проблем аутентификации и хранения
сертификатов и ключей с помощью hardware-ключей. В своей работе я использовал
ОС GNU/Linux, рассматриваемый дистрибутив – Gentoo Linux. Тем, кто работает с
другими дистрибутивами, использующих Pluggable Authentication Modules, не стоит
расстраиваться, разница будет заметна лишь при установке необходимого ПО.
Предполагается, что мы имеем два хоста – рабочая
станция и удаленный сервер под управлением ОС Linux. С сервером (назовем его
«remote») работаем, используя sshd, на обоих хостах имеем привилегии
суперпользователя.
Взглянем на проблемы, рассматриваемые в статье.
Проблема первая
Часто приходится сталкиваться с проблемой запоминания паролей, запрашиваемых
/bin/login. Все знают, что пароли должны иметь минимальную длину в восемь
символов и включать в себя символы верхнего и нижнего регистров, а также
спецсимволы. Когда количество подконтрольных нам серверов и пользовательских учетных
записей на них возрастает, удержать в памяти все пароли зачастую почти
непосильная задача. Все принятые нормативные акты по использованию данных
учетной записи запрещают записывать пароли на бумаге, сохранять их в файлах и
так далее. Как же быть администратору, у которого десятки, а то и сотни
серверов и на каждом время от времени приходится регистрироваться с разными
учетными данными?
Проблема вторая
Например, мы используем GnuPG, публичный ключ доступен многим, secret key
защищен паролем (pass phrase), но он является не более чем файлом на диске.
Если этот файл похищен злоумышленником, он попытается подобрать верный pass
phrase (brute force). Нет гарантии, что правильный пароль не будет найден в
ближайшее время.
Электронные USB-ключи, такие как Aladdin eToken
или Rainbow iKey, а также смарткарты решают эти проблемы. USB-ключ или
смарткарту удобно держать при себе, нельзя просто получить доступ к хранящимся
в них ключам и сертификатам, как в случае их хранения на жестком диске. Подбор
PIN по словарю также обречен на провал, так как после трех (в моем примере)
неудачных попыток PIN будет заблокирован.
Проект OpenSC основал Olaf Kirch. Он хотел
написать библиотеку, предоставляющую структуру для написания драйверов устройств
чтения смарткарт по принципу «все в одном», как для работы с устройствами,
подключаемыми к последовательному порту, так и для USB-ключей.
К моменту написания данной статьи
поддерживаются следующие устройства:
n KOBIL KAAN Professional
n Schlumberger e-gate
n Aladdin eToken PRO
n Eutron CryptoIdentity IT-SEC
n Rainbow iKey 3000
Список поддерживаемого оборудования всегда можно
посмотреть на веб-сайте проекта OpenSC – http://opensc.org.
Установка
Так как в моем примере рассматривается USB-token от Aladdin (Aladdin eToken
PRO 32K), ядро должно быть собрано с поддержкой USB device filesystem.
# USE='usb pam' emerge opensc
Убедимся, что установлено все необходимое для
последующей работы:
# qpkg -I -v |
grep open
net-misc/openssh-3.8.1_p1-r1
*
dev-libs/openssl-0.9.7d-r1
*
dev-libs/opensc-0.8.1-r1
*
dev-libs/openct-0.5.0
*
# qpkg -I -v |
grep hotplug
sys-apps/hotplug-base-20040401
*
sys-apps/hotplug-20040401
*
Копируем пример конфигурационного файла
opensc.conf:
# cp
/usr/share/opensc/opensc.conf.example /etc/opensc.conf
Сделаем openct и hotplug демонами, запускаемыми
по умолчанию:
# rc-update add hotplug
default
# rc-update add openct
default
Запускаем их:
# rc
* Starting
input hotplugging... [ ok ]
* Starting pci
hotplugging... [ ok ]
* Starting usb
hotplugging... [ ok ]
* Starting
OpenCT... [ ok ]
Чтобы не работать постоянно с учетной записью
root, добавим непривилегированного пользователя chiko в группу openct и wheel
(для возможности использования $ su):
# usermod -G openct,wheel
chiko
Далее работаем уже под непривилегированной
учетной записью.
Вставим USB-ключ и убедимся, что он распознан:
# openct-tool
list
0 Aladdin
eToken PRO
Наш ключ имеет идентификатор 0 – запомним его.
Идентификаторы ключа всегда присваиваются по возрастанию начиная с 0. Если ключ
не распознан, проверьте исправность USB-порта и наличие в ядре поддержки USB:
# cat
/путь/к/исходникам_ядра/.config | grep CONFIG_USB_DEVICEFS
CONFIG_USB_DEVICEFS=y
а также вывод mount:
# mount | grep
usbfs
usbfs on
/proc/bus/usb type usbfs (rw)
Все готово для создания RSA-ключей и
X509-сертификата, приступим:
#
/etc/ssl/misc/CA.pl –newca
CA certificate
filename (or enter to create)
Making CA
certificate ...
Generating a
1024 bit RSA private key
........++++++
.................................++++++
writing new
private key to './demoCA/private/cakey.pem'
Enter PEM pass
phrase:
Verifying -
Enter PEM pass phrase:
-----
You are about
to be asked to enter information that will be incorporated into your
certificate request.
What you are
about to enter is what is called a Distinguished Nameor a DN.
There are quite
a few fields but you can leave some blank.
For some fields
there will be a default value,
If you enter
'.', the field will be left blank.
-----
Country Name (2
letter code) [AU]:RU
State or Province
Name (full name) [Some-State]:KRAST
Locality Name
(eg, city) []:Achinsk
Organization
Name (eg, company) [Internet Widgits Pty Ltd]:AGK
Organizational
Unit Name (eg, section) []:SB
Common Name
(eg, YOUR name) []:Pokhabov Aleksandr
Email Address
[]:chiko@example.com
Примечание: все будет временно храниться в
директории ~/demoCA.
Создаем пароль:
# openssl x509
-in demoCA/cacert.pem -days 3650 -out demoCA/cacert.pem -signkey
demoCA/private/cakey.pem
Getting Private
key
Enter pass
phrase for demoCA/private/cakey.pem:
# /etc/ssl/misc/CA.pl
–newreq
Generating a
1024 bit RSA private key
......................++++++
............................................................................................................++++++
writing new
private key to 'newreq.pem'
Enter PEM pass
phrase:
Verifying -
Enter PEM pass phrase:
-----
You are about
to be asked to enter information that will be incorporated into your
certificate request.
What you are
about to enter is what is called a Distinguished Name or a DN.
There are quite
a few fields but you can leave some blank.
For some fields
there will be a default value,
If you enter
'.', the field will be left blank.
-----
Country Name (2
letter code) [AU]:RU
State or
Province Name (full name) [Some-State]:KRAST
Locality Name
(eg, city) []:Achinsk
Organization
Name (eg, company) [Internet Widgits Pty Ltd]:AGK
Organizational
Unit Name (eg, section) []:SB
Common
Name (eg, YOUR name) []:Pokhabov Aleksandr
Email Address
[]:chiko@example.com
Please enter
the following 'extra' attributes to be sent with your certificate request
A challenge
password []:OurChallengePass
An optional
company name []:AGK
Request (and
private key) is in newreq.pem
Подписываем:
#
/etc/ssl/misc/CA.pl –sign
Using
configuration from /etc/ssl/openssl.cnf
2745:error:0E06D06C:configuration
file routines:NCONF_get_string:no value: conf_lib.c:329:group=CA_default
name=unique_subject
Enter pass
phrase for ./demoCA/private/cakey.pem:
Check that the
request matches the signature
Signature ok
Certificate
Details:
Serial
Number: 1 (0x1)
Validity
Not
Before: Nov 4 09:48:50 2004 GMT
Not
After : Nov 4 09:48:50 2005 GMT
Subject:
countryName = RU
stateOrProvinceName = KRAST
localityName = Achinsk
organizationName
= AGK
organizationalUnitName = SB
commonName = Pokhabov
Aleksandr
emailAddress = chiko@example.com
X509v3
extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
D9:F9:DB:F8:59:4C:72:86:15:13:B0:C0:FE:76:5C:93:C0:FD:38:B9
X509v3 Authority Key Identifier:
keyid:6B:2E:C8:03:71:2E:67:62:71:BF:A7:93:56:52:C2:FF:62:30BA:F0
DirName:/C=RU/ST=KRAST/L=Achinsk/O=AGK/OU=SB/
`
CN=Pokhabov Aleksandr/emailAddress=chiko@example.com
serial:00
Certificate is
to be certified until Nov 4 09:48:50 2005 GMT (365 days)
Sign the
certificate? [y/n]:y
1 out of 1
certificate requests certified, commit? [y/n]y
Write out
database with 1 new entries
Data Base
Updated
Signed
certificate is in newcert.pem
Экспортируем наш закрытый ключ:
# openssl rsa
-in newreq.pem -out newkey.pem
Enter pass
phrase for newreq.pem:
writing RSA key
#
/etc/ssl/misc/CA.pl -pkcs12
Enter pass
phrase for newreq.pem:
Enter Export
Password:
Verifying -
Enter Export Password:
Сертификат и ключи готовы, поместим их на наш
USB-token. Смарткарты, как и USB-ключи используют для хранения сертификатов и
ключей файловую систему. Многие производители в своих устройствах используют
собственные проприетарные механизмы хранения ключей и сертификатов, например
различные имена директорий. OpenSC реализует PKCS #15 стандарт и имеет модуль
эмуляции для несовместимых механизмов хранения. Необходимо отформатировать
аппаратный ключ (параметры «-EC» – сокращенные от «--erase-card» и
«--create-pkcs15») перед его первым использованием (внимание! вся информация на
ключе будет уничтожена!):
# pkcs15-init
-EC --label 'Chiko Test Card' --no-so-pin
Connecting to
card in reader Aladdin eToken PRO...
Using card
driver: Siemens CardOS
About to erase
card.
About to create
PKCS #15 meta structure.
Параметр --no-so-pin указывает, что не будет
использоваться Security Officer PIN. Это избавит вас от лишних запросов
Security Officer PIN, но так вы понижаете планку безопасности (владельцу ключа
будут доступны возможности создания новых профилей). Также, в случае утери PIN
и PUK-кодов пользовательского профиля вы не сможете разблокировать пользовательский
PIN. Выбор за вами.
На следующем шаге создается пользовательский
профиль, выбираются PIN- и PUK-коды:
# pkcs15-init
-P --auth-id 01 --label 'CHIKOPIN'
Connecting to
card in reader Aladdin eToken PRO...
Using card
driver: Siemens CardOS
Found Chiko
Test Card
About to store
PIN.
New user PIN
required.
Please enter
PIN:
Please type
again to verify:
Unlock code for
new user PIN required (press return for no PIN).
Please enter
PIN:
Please type
again to verify:
Помещаем в аппаратный ключ только что созданный
секретный ключ. На ошибку в пятой строке не обращаем внимания:
# pkcs15-init
-S newcert.p12 --format pkcs12 -a 01 --split-key
Connecting to
card in reader Aladdin eToken PRO...
Using card
driver: Siemens CardOS
Found Chiko
Test Card
About to store
private key.
error:23076071:PKCS12
routines:PKCS12_parse:mac verify failure
Please enter
passphrase to unlock secret key:
Importing 2
certificates:
0:
/C=RU/ST=KRAST/L=Achinsk/O=AGK/OU=SB/
CN=Pokhabov
Aleksandr/emailAddress=chiko@example.com
1:
/C=RU/ST=KRAST/L=Achinsk/O=AGK/OU=SB/
CN=Pokhabov
Aleksandr/emailAddress=chiko@example.com
User PIN
required.
Please enter
PIN:
Всё! Ключ прошит. Распорядитесь ключами и
сертификатом, находящимися в ~/demoCA, подобающим образом. Не стоит забывать,
что одна из преследуемых нами целей – исключить наличие сертификатов и закрытых
ключей на жестком диске.
Теперь мы готовы настроить PAM-аутентификацию,
используя pam_opensc.so.
# mkdir ~/.eid
# pkcs15-tool
-r 45 -o ~/.eid/authorized_certificates
Connecting to
card in reader Aladdin eToken PRO...
Using card
driver: Siemens CardOS
Trying to find
a PKCS#15 compatible card...
Found Chiko
Test Card!
Reading
certificate with ID '45'
Регистрируемся как root и вносим необходимые
изменения в настройку PAM. Для использования # su без запроса пароля членами
группы wheel, имеющими аппаратный ключ, привожу пример конфигурационного файла:
# more /etc/pam.d/su
auth sufficient /lib/security/pam_opensc.so
auth required /lib/security/pam_wheel.so
use_uid
account required /lib/security/pam_stack.so
service=system-auth
session required /lib/security/pam_stack.so
service=system-auth
Так как мы работали с учетной записью chiko (в
вашем случае может быть другой), проверяем корректную работу следующим образом:
# su chiko
Using card
reader Aladdin eToken PRO
Enter PIN1
[CHIKOPIN]:
$
Работает! Вывод # ps auxf докажет, что нет
никакого обмана. Проверим логи:
# grep -ir
pam_opensc /var/log/messages
Nov 11 16:43:00
workstation su(pam_opensc)[3374]:
Authentication
successful for chiko at pts/0.
Извлечем ключ из USB:
# su chiko
No smart card
present
su: Permission
denied
Sorry.
Теперь не только длина, но и само наличие пароля
не обязательны. Можно удалить хэш пароля для пользователя chiko (и не только
для него) из /etc/shadow, заменив его на восклицательный знак.
При желании сделать аутентификацию только по
hard-ware-ключу, /etc/pam.d/login должен быть соответствующе изменен.
У меня он имеет вид:
# more /etc/pam.d/login
auth required /lib/security/pam_opensc.so
account required /lib/security/pam_stack.so
service=system-auth
session required /lib/security/pam_stack.so
service=system-auth
При попытке зарегистрироваться без наличия
аппаратного ключа в USB получим:
workstation
login: chiko
No smart card
present
Login incorrect
Если предполагается регистрация в системе под
root по # su, файл /root/.eid/authorized_certificates должен быть доступен для
чтения, иначе получим ошибку:
# su
Using card
reader Aladdin eToken PRO
Enter PIN1
[CHIKOPIN]:
No such user,
user has no .eid directory or .eid unreadable.
Будьте осторожны при изменении файлов
конфигурации PAM, если допустить ошибки конфигурирования, то есть риск
появления неприятного события – мы не сможем зарегистрироваться как root, и
придется загружаться с LiveCD, монтировать раздел с /etc и править
конфигурационные файлы PAM. Если в ваши планы ни в коем случае не входит
перезагрузка, предпочтительно сделать резервные копии файлов конфигурации PAM, и
используя crontab, по расписанию в определеное время вернуть их на место. Это
применимо в случае ограничения количества pid и tty для root, если же таких
ограничений нет, предпочтительнее использовать заранее открытую сессию.
Подробнее о работе с PAM можно узнать в страницах руководства по PAM.
Внимание! Во всех домашних каталогах
пользователей, с учетными данными которых мы будем регистрироваться в системе,
должен присутствовать корректный ~/.eid/authorized_certificates.
В моем примере до блокирования PIN дается три
попытки его ввода. Как быть, если после третьей неудачной попытки ввести PIN мы
получили предупреждение о его блокировке?
# su
Using card
reader Aladdin eToken PRO
Enter PIN1
[CHIKOPIN]:
sc_pkcs15_verify_pin:
Authentication method blocked
Ведь даже после ввода корректного PIN мы не
увидим ничего, кроме предупреждения о том, что он заблокирован. При создании
пользовательского профиля на аппаратном ключе, кроме PIN мы также указывали
PUK-код, его необходимо помнить именно для такого случая. Разблокирование:
# pkcs15-tool
-u
Connecting to
card in reader Aladdin eToken PRO...
Using card
driver: Siemens CardOS
Trying to find
a PKCS#15 compatible card...
Found Chiko
Test Card!
Enter PUK
[CHIKOPIN]:
Enter new PIN
[CHIKOPIN]:
Enter new PIN
again [CHIKOPIN]:
PIN
successfully unblocked.
Если и PUK забыт и (в нашем примере) не
использовался Security Officer PIN, не остается ничего кроме форматирования
ключа, поэтому будьте максимально осторожны.
Первоочередная цель достигнута – dual factor
authentication (наличие hardware-ключа и знание PIN) работает на нашей системе.
Невооруженным глазом заметно, что такой способ аутентификации намного
безопасней пары login/password.
С регистрацией в локальной системе разобрались,
рассмотрим регистрацию с помощью нашего аппаратного ключа на удаленных
серверах.
Первое, что следует отметить, – openssh должен
быть собран с поддержкой смарткарт. В Gentoo это делается очень просто:
# USE='X509 pam smartcard'
emerge openssh
Пользователи других дистрибутивов применяют
следующее:
./configure
--with-opensc=/путь/opensc
Как настроить и запустить sshd, думаю, объяснять
нет необходимости. Никаких особенных настроек не требуется, за исключением
вставки на рабочей станции в /etc/pam.d/sshd строки auth required /lib/security/pam_opensc.so.
Вот как он выглядит у меня:
# more /etc/pam.d/sshd
auth required
/lib/security/pam_opensc.so
accoun required
pam_stack.so service=system-auth
session required
pam_stack.so service=system-auth
Итак, у нас имеется готовый ключ и корректно
собранный, настроенный и активный sshd на сервере remote. На нем есть учетная
запись пользователя ajwol и в его домашнем каталоге имеется директория ~/.ssh .
Чтобы зарегистрироваться с его учетной записью, используя наш ключ, в домашней
директории ajwol, должен присутствовать и быть доступным для чтения файл
~/.ssh/authorized_keys, содержащий в себе публичный ключ. Создадим его на
машине, с которой будем регистрироваться:
# ssh-keygen -D 0 >
~/authorized_keys
где «0» – идентификатор ключа.
Скопируем этот файл в
/home/ajwol/.ssh/authorized_keys на сервер remote:
# scp ~/authorized_keys
ajwol@remote:.ssh
Регистрируемся на удаленном сервере, используя
параметр -I 0 (id ключа):
# ssh -I 0 -l
ajwol remote
Enter PIN for
Private Key:
Last login: Fri
Nov 12 08:20:15 2004 from grayhat
ajwol@remote
ajwol $
Задача выполнена. Вы можете регистрироваться
старым проверенным способом без ключа (не указывая параметр -I), используя
login/password, но, по желанию, можете также поиграть с настройками модулей PAM
на сервере remote.
Примечание: ~/.ssh/authorized_keys должен быть
доступен во всех домашних каталогах пользователей, с логинами которых будем
регистрироваться удаленно.
Теперь не имеет значения длина пароля для логина
ajwol на хосте remote, пользователь даже не обязан знать его, хватит и PIN. Эти
шаги можно проделать со многими удаленными хостами, освободив себя от
необходимости запоминания массы длинных паролей к множеству пользовательских
аккаунтов.
Задачи, поставленные в начале статьи, решены. В
следующих статьях об использовании аппаратных ключей будут рассмотрены примеры
их работы с Mozilla и Apache 2, шифрование домашних каталогов.
Ссылки:
n http://opensc.org
n http://www.openssl.org/docs
n http://www.kernel.org/pub/linux/libs/pam
n man
opensc