АЛЕКСАНДР ПОХАБОВ
Железный login: ломаем зубы грубой силе
В этой статье будут рассмотрены решения проблем аутентификации и хранения сертификатов и ключей с помощью 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-ключей.
К моменту написания данной статьи поддерживаются следующие устройства:
- KOBIL KAAN Professional
- Schlumberger e-gate
- Aladdin eToken PRO
- Eutron CryptoIdentity IT-SEC
- 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 – запомним его. Идентификаторы ключа всегда присваиваются по возрастанию начиная с 0. Если ключ не распознан, проверьте исправность USB-порта и наличие в ядре поддержки USB:
# cat /путь/к/исходникам_ядра/.config | grep CONFIG_USB_DEVICEFS
а также вывод 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, шифрование домашних каталогов.
Ссылки:
- http://opensc.org
- http://www.openssl.org/docs
- http://www.kernel.org/pub/linux/libs/pam
- man opensc