1) Введение, или "что такое SSL"? SSL или Secure Socket Layer это протокол среднего уровня который разработан для поддержания безопасности и сохранности обычного TCP/IP соединения. Вообще SSL накладывается на обычные прикладные протоколы, такие как HTTP, POP, SMTP, итп. Но его основная черта, это наложение на TCP/IP, более того, именно для последнего создан популярный API(библиотека) OpenSSL. Вот на примере этой библиотеки, а так же, без неё, я покажу как происходит процесс соединения. "Каким боком это будет полезно хаксору?" - скажете вы, ну вы наверное не раз видели эксплоиты для различных cервисов, вроде Apache/mod_ssl, IIS, и им подобным. Так вот, для того чтобы хоть как то добраться до ошибки в уязвимой SSL программе, нужно знать ее работу на самом низком уровне, а именно, представлять себе процесс "рукопожатия", обмена ключами, сертификатами и тд. Данная статья будет введением в этот нелегкий процесс.
2) Что же происходит при вводе "https://" в нашем браузере?
Первый этап SSL соединения - рукопожатие. Вот последовательный список того что происходит при нем:
+----------------------+-----------------+---------------------+
| Клиент | Направление | Сервер |
+----------------------+-----------------+---------------------+
| ClientHello | --------> | ServerHello |
| | | -Certificate |
| | | -ServerKeyExchange |
| | | -CertificateRequest |
| | | ServerHelloDone |
| | <-------- | |
| -Certificate | | |
| ClientKeyExchange | | |
| -CertificateVerify | | |
| [ChangeCipherSpec] | | |
| Finished | --------> | [ChangeCipherSpec] |
| | | Finished |
| | <-------- | Application Data |
| Application Data | <-------> | |
+----------------------+-----------------+---------------------+
Эта таблица была содрана из спецификации SSL*
Поля начинающиеся на символ дефиса являются необязательными. Хотя в большинстве случаев сертификаты являются обязательным условием для удачного SSL соединения. Так что же просходит при том же конекте с https сервером? Ты наверное видел сообщение типа "Принять этот сертификат?" в своем браузере, когда подключался к подозрительному сайту. Так вот, в наших браузерах существует маленькая база сертификатов самых авторитетных контор вроде VeriSign. Если сайт, будь то шоп, будь то багтрак, встречают вас без запроса о принятии сертификата, хоть вы и ввели https, значит им можно довериться (в большинстве случаев), так как их сертификаты подписаны одной из авторитетных контор. Если же запрос все таки поступил, значит сертификат они подписали сами.
Хотелось бы отметить, что в статье я только опишу как послать первый запрос ClientHello, так как все будет делаться на низшем уровне. Соединение же на уровне API делается очень просто. Все примеры приводятся в самом пакете OpenSSL (генерация сертификата, соединение, итд).
3) Уровень 2. Приложение
Чтобы соединиться с любым SSL сервером, достаточно выполнить следующую команду в шелле:
sslground$ openssl s_client -host i.have.ssl-enabled.com -port
CONNECTED(00000714)
...
Certificate chain
...
Server Certificate
...
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES256-SHA
Session-ID:
7CED2EE0CBEBF0919523BACE5BCD0051F367E43F73F7ED32F09AFF20
Session-ID-ctx:
Master-Key:
0EC59F73F2479DACD03D38E1D1068995069891174720B76B33ED1AD3
31E97A0E3498120783F542E9E847A7EF
Key-Arg : None
Start Time: 1105080224
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
Cделаем следующие выводы из того что мы увидели
1) Ключ сессии шифруется 2048 битным RSA ключом
2) Соединение шифруется 256 битным ключом сессии алгоритмом AES
3) Aлгоритм SHA играет роль CRC, а именно проверяет, не изменил ли злой хакс0р данные сессии (например сидит между клиентом/cервером)
4) Версия протокола SSLv3.1 которая теперь имеет название TLSv1
Если вам интересно, можете попытаться соединиться с серваком используя опции -ssl2/-ssl3/tls1, чтобы проверить, какие версии он поддерживает. Так можно проверить поддержку уязвимых версий (ssl2). Для полного списка опций наберите man s_client.
А теперь попробуем запустить сервер сами, при помощи следующей команды:
sslground$ openssl s_server -accept 443 -cert /путь/к/cертификату.pem
-HTTP /путь/к/html_файлу.html
Все, теперь к такому вот минисерваку можно подключиться браузером, и вы увидите html страницу. Все это дело шифруется сильнейшими алгоритмами. Используется порт 443.
4) Уровень 1. API
Не буду тут разглагольствовать (сказанул), сразу перейду к процессу соединения
1) Создаем socket (socket())
2) Коннектимся по обычному TCP/IP (сonnect())
3) Готовим библиотеку (загружаем сертификаты если надо)
4) Будучи соединенными, делаем 2-е соединение (SSL_connect())
5) Обмениваемся инфой (SSL_send(), SSL_recv())
6) Обрываем соединение (SSL_shutdown(), SSL_free())
К статье я приложил пример "pssl.c" всего этого безобразия. Теперь проверим:
sslground$ gcc -o pssl pssl.c -lssl
sslground$ ./pssl
--SSL Connection established
--Getting peer certificate
--Server: Apache/1.3.31 (Unix) mod_ssl/2.8.17 OpenSSL/0.9.7c
--Writing cert to cert.crt
--Shuting down
Прога просто соединяется с сервером и читает название сервиса http.
5) Уровень 0. Следуем спецификации.
Вот мы и добрались до того уровня, где все делается без библиотеки OpenSSL. По сути, если хорошо разберёшься с этим уровнем, спокойно можешь писать свою версию API SSL :).
На будущее, если ты хочешь видеть, какие циферки и данные идут между 2мя SSL приложениями, научись правильно травить на это дело сниффер. Именно так я сооброжал что же там происходит:
sslground$ tethereal -i lo -VR ssl -x | less
Вот пример того как сниффер ethereal выводит данные SSL. Распишу опции более подробно:
'-V' - вывести все данные в виде дерева (запустите, поймете)
'-R ssl' - выводить данные только SSL протокола (остальной мусор не нужен)
'-x' - все печатается в виде hex кодов
Если же твоя прога слушает на отличном от 443-го порту, запускай так:
sslground$ tethereal -i lo -d tcp.port==31337,ssl -VR ssl -x | less
5.1) СlientHello
Вот собственно и первый пакет, который отсылается любым SSL клиентом:
unsigned char client_hello[]=
"\x16" /* type - handshake */
"\x03\x00" /* SSLv3 */
"\x00\x37" /* length */
"\x01\x00" /* client hello */
"\x00\x33" /* length */
"\x03\x00" /* SSLv3 */
"\x01\x01\x01\x01" /* random.gmt.unix_time */
/* start random.bytes*/
"\xaa\xaa\xaa\xaa\xbb\xbb\xbb"
"\xbb\xcc\xcc\xcc\xcc\xdd\xaa"
"\xdd\xdd\xee\xee\xee\xee\xff"
"\xff\xff\xff\xaa\xaa\xaa\xbb"
/* end random.bytes*/
"\x00" /* session id length */
"\x00\x0c" /* cipher suites length */
"\x00\x00" /* NULL_WITH_NULL_NULL */
"\x00\x39" /* DHE_RSA_WITH_AES_256_CBC_SHA */
"\x00\x09" /* RSA_WITH_DES_CBC_SHA */
"\x00\x35" /* RSA_WITH_AES_256_CBC_SHA */
"\x00\x05" /* RSA_WITH_RC4_128_SHA */
"\x00\x04" /* RSA_WITH_RC4_128_MD5 */
"\x01\x00"; /* comp methods length / method */
Опишу подробнее:
"\x16" - Тип содержимого, 0x16 для рукопожатия. Там могут быть 0x15 (ошибки), 0x17(данные) и другие.
"\x03\x00" - Используется SSLv3
"\x00\x37" - размер пакета
"\x01\x00" - Тип пакета, 0x01 для ClientHello. Другие варианты могут быть: Certificate(0x0b), CeritificateVerify(0x0f), СlientKeyExchange(0x10), Finished(0x20).
"\x01\x01\x01\x01" - дата, нам не важно, пишем как хотим
"\xaa\xaa\x....." - 28 случайных байт. Вообще используется для генерации ключа сессии. Но опять же, нам это не важно.
"\х00" - Размер ID сесии (опускаем, поэтому и равно 0). ID сессия в SSL используется для восстановления оборванных соединений.
"\x00\x0c" - размер следующих данных cipher_suites. А именно 12 байт. Если посчитаете кол-во байт ниже этой строки, вы заметите что оно равно 12 (несчитая последней строки).
Далее идут обозначения поддерживаемых клиентом шифров. Их можно посмотреть в исходниках SSL (как я и делал).
"\x01\x00" - 0х01 для размера методов компрессии, 0х00 для того чтобы показать, что никаких методов не применять.
Как видите, ClientHello говорит серверу какие желает использовать шифры, а также даёт данные для генерации ключа сессии (ключ который и шифрует последующие данные).
6) Программа.
К статье приложена еще одна маленькая программа. Она собирает информацию о поддерживаемых шифрах сервера. Это маленький аналог проги THCSSLCheck, написанной мембером команды THC johny cyberpunk. Кстати именно он написал популярный эксплоит для Windows IIS/SSL.
7) Доки
1] SSLv2 specification:
http://www.netscape.com/eng/security/SSL_2.html
2] SSLv3 specification:
http://wp.netscape.com/eng/ssl3/3-SPEC.HTM
3] TLSv1 specification:
ftp://ftp.isi.edu/in-notes/rfc2246.txt
4] OpenSSL API programming intro:
http://www.rtfm.com/openssl-examples
5] Ethereal packet analyzer:
http://www.ethereal.com
(Эксклюзивом для Inattack.ru. 4king)
PS: Для компиляций приложенных прог просто наберите 'make' в папке с ними.
PS2: netris - мой 2й псевдоним (в кодах используется).