...

воскресенье, 14 августа 2016 г.

[Из песочницы] По следам «спамера» или Oracle DB + UTL_SMTP + SSL/TLS

На написание данной статьи меня сподвигло прочтение публикации «Как я спам слал» от пользователя Nike01. Руководство поставило передо мной похожую задачу по рассылке учетных данных пользователей средствами базы данных Oracle. В качестве SMTP relay должен был выступать сервер исходящих сообщений Яндекса, использующий SSL при авторизации.



Сбор информации


Как и Nike01, я в первую очередь стал смотреть в сторону пакета UTL_MAIL. Данный пакет, по сути, представляет из себя «обертку» над UTL_SMTP и UTL_TCP и предназначен в основном для отправки простых почтовых сообщений, позволяя пользователю особо не вдаваться в тонкости протокола SMTP. К сожалению UTL_MAIL имеет ряд ограничений, в их числе — отсутствие поддержки SMTP аутентификации и следовательно для решения моей задачи он не подходит.

Далее, я обратился к документации по пакету UTL_SMTP, как выяснилось — это довольно мощный и гибкий инструмент, который позволяет задействовать практически все команды протокола SMTP, в том числе имеет поддержку SMTP авторизации, а начиная с версии БД 11.2.0.2 умеет и STARTTLS. То, что надо!

Переходим к почтовому серверу. Из справки по использованию smtp.yandex.ru узнаем, что сервис слушает 465 порт:


Ок. Пробуем установить соединение:
[oracle@ora_db ~]$openssl s_client -connect smtp.yandex.ru:465
CONNECTED(00000003)
depth=2 C = PL, O = Unizeto Technologies S.A., OU = Certum Certification Authority, CN = Certum Trusted Network CA
verify return:1
depth=1 C = RU, O = Yandex LLC, OU = Yandex Certification Authority, CN = Yandex CA
verify return:1
depth=0 C = RU, O = Yandex LLC, OU = ITO, L = Moscow, ST = Russian Federation, CN = smtp.yandex.ru, emailAddress = pki@yandex-team.ru
verify return:1
---
Certificate chain
 0 s:/C=RU/O=Yandex LLC/OU=ITO/L=Moscow/ST=Russian Federation/CN=http://ift.tt/2aRvPoL
   i:/C=RU/O=Yandex LLC/OU=Yandex Certification Authority/CN=Yandex CA
 1 s:/C=RU/O=Yandex LLC/OU=Yandex Certification Authority/CN=Yandex CA
   i:/C=PL/O=Unizeto Technologies S.A./OU=Certum Certification Authority/CN=Certum Trusted Network CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGtzCCBZ+gAwIBAgIQeNdVGMktXbH0GDaX1lgg9TANBgkqhkiG9w0BAQsFADBf
MQswCQYDVQQGEwJSVTETMBEGA1UEChMKWWFuZGV4IExMQzEnMCUGA1UECxMeWWFu
ZGV4IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRIwEAYDVQQDEwlZYW5kZXggQ0Ew
HhcNMTUxMDEyMTI0MTI0WhcNMTcxMDExMTI0MTI0WjCBmjELMAkGA1UEBhMCUlUx
EzARBgNVBAoMCllhbmRleCBMTEMxDDAKBgNVBAsMA0lUTzEPMA0GA1UEBwwGTW9z
Y293MRswGQYDVQQIDBJSdXNzaWFuIEZlZGVyYXRpb24xFzAVBgNVBAMMDnNtdHAu
eWFuZGV4LnJ1MSEwHwYJKoZIhvcNAQkBFhJwa2lAeWFuZGV4LXRlYW0ucnUwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDfdYJIwjSdhSwHdNxNJ+2TH8jc
l2Skm4k6Z9UTDcxCMbe8rvkEg3bu7EUPnftNmBGxB3KXNj73irZ6PLRu3bO7psi3
hbWNRVDzQlcdQZmW/Iucd8IQlvN1gwDZ79eu1fWmRMThmNmiiKK1AjtZNTc+Dq/9
kTl4TkRzdge6KpkOn3lJFwiTozixxKKfawxQSlFpRadzLuYt2Cj88Huo3R5frwwH
8nTMDITtHZVSSYw1cYNIWj+y5G3D1TA1pKcyIPI8WHqJeHIekI3t4uK9JQNEaJI0
clabA3fn1wdJ4jCWajdLcssJ9PJ6eJB+l4HZFt3EDhe8XiQ/69gZjQVIVrcpAgMB
AAGjggMxMIIDLTAMBgNVHRMBAf8EAjAAMGkGA1UdHwRiMGAwL6AtoCuGKWh0dHA6
Ly9jcmxzLnlhbmRleC5uZXQvY2VydHVtL3ljYXNoYTIuY3JsMC2gK6AphidodHRw
Oi8veWFuZGV4LmNybC5jZXJ0dW0ucGwveWNhc2hhMi5jcmwwcQYIKwYBBQUHAQEE
ZTBjMCwGCCsGAQUFBzABhiBodHRwOi8veWFuZGV4Lm9jc3AtcmVzcG9uZGVyLmNv
bTAzBggrBgEFBQcwAoYnaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL3ljYXNo
YTIuY2VyMB8GA1UdIwQYMBaAFDdc4xngso6hqE7Sz6vQ3OMLXDVNMB0GA1UdDgQW
BBQYy748oNmcZPHfTrybOrdqeu/mTDAOBgNVHQ8BAf8EBAMCBaAwggE/BgNVHSAE
ggE2MIIBMjCCAS4GDCqEaAGG9ncCBQEKAjCCARwwJQYIKwYBBQUHAgEWGWh0dHBz
Oi8vd3d3LmNlcnR1bS5wbC9DUFMwgfIGCCsGAQUFBwICMIHlMCAWGVVuaXpldG8g
VGVjaG5vbG9naWVzIFMuQS4wAwIBAhqBwFVzYWdlIG9mIHRoaXMgY2VydGlmaWNh
dGUgaXMgc3RyaWN0bHkgc3ViamVjdGVkIHRvIHRoZSBDRVJUVU0gQ2VydGlmaWNh
dGlvbiBQcmFjdGljZSBTdGF0ZW1lbnQgKENQUykgaW5jb3Jwb3JhdGVkIGJ5IHJl
ZmVyZW5jZSBoZXJlaW4gYW5kIGluIHRoZSByZXBvc2l0b3J5IGF0IGh0dHBzOi8v
d3d3LmNlcnR1bS5wbC9yZXBvc2l0b3J5LjAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
KwYBBQUHAwIwEQYJYIZIAYb4QgEBBAQDAgbAMHoGA1UdEQRzMHGCDnNtdHAueWFu
ZGV4LmJ5gg5zbXRwLnlhbmRleC5reoIPc210cC55YW5kZXguY29tgg5zbXRwLnlh
bmRleC51YYISc210cC55YW5kZXguY29tLnRyggpzbXRwLnlhLnJ1gg5zbXRwLnlh
bmRleC5ydTANBgkqhkiG9w0BAQsFAAOCAQEAoVcDTfHCdx1N6IF0rBtZTxJBu2Tf
WcSYGu/Uif6EqqVsy44kQ8Yxresaqb8bR0FkJxSP1HXDwQuXm18sdZDb4f/ealF4
Hb6ZmF5ilP0SNUccka4wI0DDTuMuBDstGbCvLJPxTjHTWP9HYrYoAJsUnux92blR
Uc11XnKQE9ltWEpKys9RQhTLDqPNrALa423zvN5jLKqMK6vVzuTIOnrOQFZMDxmQ
KVVUtvGS7ZBmL8Z8ripEDBUFywAcxHC9DJpTUwxZUs2ceJbuN6J0qKjP2F/aKJZR
GTgW095M/H1tEGjouYfSj21cy9ZDNiUqN1Yutg0+nGNexiRDghg44yWMeQ==
-----END CERTIFICATE-----
subject=/C=RU/O=Yandex LLC/OU=ITO/L=Moscow/ST=Russian Federation/CN=http://ift.tt/2aRvPoL
issuer=/C=RU/O=Yandex LLC/OU=Yandex Certification Authority/CN=Yandex CA
---
No client certificate CA names sent
Server Temp Key: ECDH, prime256v1, 256 bits
---
SSL handshake has read 3581 bytes and written 373 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: C64B0AE4863B7F1A44ED0981E29F4D1E796F98F7FB0EF950A7A1588232F11ABC
    Session-ID-ctx:
    Master-Key: F704953E4A95AD4A1C06BBDF1425F4E5B1E2B8BE5EE5214484AC0DF9219E7185ABB38573904FA3CFD0B88A8FF3185061
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - b3 08 e7 79 5b 86 ba 5a-7e 71 bf f8 5f ad 66 4a   ...y[..Z~q.._.fJ
    0010 - 5b 4b c6 fe e4 ae 95 21-6e 60 b8 84 bd 09 8e 91   [K.....!n`......
    0020 - ba a4 1e 29 b8 fc 7c 5b-72 16 ae 7e f6 f7 a9 e5   ...)..|[r..~....
    0030 - 69 0a 4e 41 03 cc 79 3a-b4 f7 6d 99 81 a6 a2 ef   i.NA..y:..m.....
    0040 - c8 27 02 50 1d 68 0b 70-1f d1 d4 1a b7 d9 99 b8   .'.P.h.p........
    0050 - b0 6d 47 ee 89 7d 5d 37-bd ab 89 a7 d2 d2 3d 1d   .mG..}]7......=.
    0060 - 2f e1 4b 85 ae eb ab de-3a f7 e2 18 ce 55 48 3b   /.K.....:....UH;
    0070 - 15 14 8f 69 45 bc 8a a4-77 b1 a0 8f 41 96 ea c7   ...iE...w...A...
    0080 - f2 2d be e2 26 26 5a 06-1f f3 c0 fe 6b f7 de ab   .-..&&Z.....k...
    0090 - ab 04 f8 74 e5 b3 c9 25-c6 24 ba 88 44 50 3b 57   ...t...%.$..DP;W

    Start Time: 1470992045
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
220 smtp2h.mail.yandex.net ESMTP (Want to use Yandex.Mail for your domain? Visit http://pdd.yandex.ru)

Отлично, сертификаты из вывода нам понадобятся позже.

Реализация


Для начала создадим Oracle wallet, в нем мы будем хранить доверенные сертификаты почтового сервера. Сертификаты можно взять тут:

Стартуем Oracle Wallet Manager командой ovm, создаем новый wallet/задаем пароль:

Импортируем доверенные сертификаты, Operations > Import Trusted Certificate.:

Сохраняем, по умолчанию wallet хранится тут $ORACLE_HOME/owm/wallets/oracle/. Далее необходимо дать права на исполнение пакета UTL_SMTP:
GRANT EXECUTE on UTL_SMTP to SMTP_USER;

Создаём ACL, даём права на connect:
begin
  DBMS_NETWORK_ACL_ADMIN.CREATE_ACL 
    ( 
      acl    => 'smtp_acl.xml',
      principal  => 'SMTP_USER',
      is_grant   => TRUE, 
      privilege  => 'connect', 
    ); 
end;
/

На доступ к SMTP Яндекса:
begin
  DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL
    (
       acl => 'smtp_acl.xml',
       host => 'smtp.yandex.ru',
       lower_port => 1,
       upper_port => 1024
    );
end;
/

На использование wallet'а:
begin
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE
( 
      acl    => 'smtp_acl.xml',
      principal  => 'SMTP_USER',
      is_grant   => TRUE, 
      privilege  => 'use-client-certificates'  
    );
end;
/

Задаём путь до wallet'а:
begin
DBMS_NETWORK_ACL_ADMIN.ASSIGN_WALLET_ACL
( 
      acl    => 'smtp_acl.xml',
      wallet_path   => 'file:/oracle_home/owm/wallets/oracle/'
    );
end;
/

Так же нам понадобится сконвертировать учетные данные по доступу к почтовому ящику(логин, пароль) в base64:
select UTL_RAW.cast_to_varchar2 (
          UTL_ENCODE.base64_encode (UTL_RAW.cast_to_raw ('user@yandex.ru'))) as username,
       UTL_RAW.cast_to_varchar2 (
          UTL_ENCODE.base64_encode (UTL_RAW.cast_to_raw ('password'))) as password
from dual;

Полученные хеши будем применять при SMTP аутентификации.

Тестируем!


DECLARE
  c utl_smtp.connection;
  l_mailhost    VARCHAR2 (64) := 'smtp.yandex.ru';
  l_from        VARCHAR2 (64) := 'user@yandex.ru';
  l_to          VARCHAR2 (64) := 'user@gmail.com';
  l_subject     VARCHAR2 (64) := 'utl_smtp test';
  crlf varchar2(2) := UTL_TCP.CRLF;
BEGIN
  c := utl_smtp.open_connection(
            host => l_mailhost,
            port => 465,
            wallet_path => 'file:/oracle_home/owm/wallets/oracle/',
            wallet_password => 'password',
            secure_connection_before_smtp => FALSE);

  UTL_SMTP.STARTTLS(c);
  UTL_SMTP.EHLO(c, 'oracle');

  utl_smtp.command( c, 'AUTH LOGIN');
  utl_smtp.command( c, 'хеш на логин');
  utl_smtp.command( c, 'хеш на пароль');  
 
  UTL_SMTP.mail (c, l_from);
  UTL_SMTP.rcpt (c, l_to);
  UTL_SMTP.open_data (c);
  UTL_SMTP.write_data (c, 'Date: ' || TO_CHAR (SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || crlf);
  UTL_SMTP.write_data (c, 'From: ' || l_from || crlf);
  UTL_SMTP.write_data (c, 'Subject: ' || l_subject || crlf);
  UTL_SMTP.write_data (c, 'To: ' || l_to || crlf);
  UTL_SMTP.write_data (c, 'message test' || crlf);
  UTL_SMTP.close_data (c);
  UTL_SMTP.quit (c); 
END;
/

PL/SQL procedure successfully completed.

Сообщение было успешно доставлено на gmail.com. Пункт 4.с реализован.

Спасибо за внимание!

Комментарии (0)

    Let's block ads! (Why?)

    Комментариев нет:

    Отправить комментарий