Страницы

Поиск по вопросам

Показаны сообщения с ярлыком ssl. Показать все сообщения
Показаны сообщения с ярлыком ssl. Показать все сообщения

воскресенье, 9 февраля 2020 г.

Где происходит шифрование данных, и где находится ключ tls/ssl?

#безопасность #ssl #https #криптография #tls


Интересует вопрос безопасности https соединения.


Не могу понять, где именно происходит шифрование данных, когда запрашивается какой-нибудь
сайт по https? - В браузере, в операционной системе клиента или вообще на сервере? 
Каким образом передается ключ браузеру, чтобы расшифровать сообщение?  Просто в ответном
сообщении или как-то еще, его же могут перехватить? 
Знает ли браузер алгоритм шифрования? - это открытая информация? Если так, то почему
не используются закрытые алгоритмы (о которых никто не знает), или постоянно меняющиеся,
чтобы злоумышленнику было сложнее разгадать? 

    


Ответы

Ответ 1



Шифрование происходит с обеих сторон. Ведь если шифровать будет только одна сторона (например только сервер), значит трафик от другой стороны (от клиента) будет не зашифрован. Его можно будет подслушать или даже изменить. Формально никто не передает никому ключ. В протоколе TLS клиент и сервер должны сгенерировать общий секрет (shared secret), набор из 48 байт. Потом клиент и сервер на основании общего секрета вычисляют ключи: ключ шифрования клиента и ключ шифрования сервера. Процедура вычисления ключей из общего секрета стандартная, и задана в описании протокола TLS. Сервер и клиент знают 2 ключа шифрования, одним шифруют, вторым дешифруют. А теперь самое интересное - как клиент и сервер вычисляют общий секрет. Это зависит от выбранного набора шифров: TLS_RSA_WITH_: В данном случае клиент сам создает общий секрет генерируя 48 случайных байт. Затем он шифрует их при помощи публичного RSA ключа, который находится в сертификате сервера. Сервер получает зашифрованные данные, и расшифровывает их при помощи приватного RSA ключа. Данная схема используется редко. TLS_DHE_RSA_/TLS_ECDHE_RSA_/TLS_ECDHE_ECDSA_: Здесь используется криптографическая схема Диффи-Хеллмана (DHE) или ее версия на эллиптических кривих (ECDHE). Суть схемы такая: сервер и клиент генерируют случайные большие числа (приватные ключи), вычисляют на их основе другие числа (публичные ключи), и пересылают друг другу. Имея свой приватный ключ и публичный ключ другой стороны, они вычисляют общий секрет. Третья сторона, которая прослушивает канал, видит только 2 публичных ключа, и она не может вычислить общий секрет. После этого все данные, которыми обменивались клиент и сервер для получение этого ключа подписываются сертификатом сервера (RSA или ECDSA подписи). Если клиент доверяет сертификату сервера, он проверяет эту подпись, и если она правильная, начинается уже обмен данными. Это наиболее часто используемая схема. Есть еще несколько схем, но они используются очень редко или не используются вообще. Про перехват. Как я выше описал, перехватывать сообщения здесь бесполезно, так как в первом случае его может расшифровать только сервер, а во втором используется хитрая криптографическая схема. Алгоритмы шифрования знает и сервер, и клиент. Ведь если клиент не знает, какой алгоритм шифрования, как он будет шифровать данные для отправки? В современной криптографии никто не использует закрытые алгоритмы. Открытые алгоритмы постоянно изучаются лучшими криптографами мира, ищутся уязвимости, и предлагаются решения для их обхода. В TLS мы условно можем сказать, что алгоритмы меняются, так как каждый раз генерируются другие ключи шифрования. А потом, если вы хотите использовать закрытый алгоритм, например для просмотра веб-страницы, каким образом этот алгоритм может быть закрытый, если ваш компьютер/устройство производит шифрование/дешифрование? Я упустил/упростил некоторые детали, что бы описать только основные идеи.

Ответ 2



Работает это так: У сервера и у клиента имеются т.н. сертификаты. Грубо говоря - сертификаты это набор: публичный ключ (PubKey)+секретный ключ (PrivKey) В момент установления соединения происходит т.н. handshake-рукопожатие, опять же грубо говоря в этот момент клиент и сервер обмениваются информацией какие у них сертификаты и какие алгоритмы шифрования они поддерживают и могут ли они доверять сертификатам противной стороны. Handshake проходит успешно, если клиент и сервер имеют корневые сертификаты, которые доверяют сертификатам респондентов. Если handshake проходит успешно они обмениваются публичными ключами и на их основе вычисляют сессионный ключ, который вычисляется как sessionKey=sharedKey(PubKeyClient, PrivKeyServer)==sharedKey(PubKeyServer, PrivKeyClient) - здесь фигурирует функция sharedKey() - это некий мат.алгоритм, который вычисляет сессионный ключ на основе публичного ключа респондента и секретного ключа получателя, причем он тождественно равен сессионному ключу полученному в результате вычисления на основе публичного ключа получателя и приватного ключа респондента - собственно на этом вся эта математика и строится - иначе ничего не взлетит После этапа 3. обе партии имеют одинаковый ключ, который используется для симметричного шифрования выбранным алгоритмом, который устанавливается во время handshake Далее каждая сторона шифрует свои запросы сессионным ключом, принимающая сторона дешифрует его и вуаля. В реале все намного сложнее - можете почитать хотя бы Википедии Update его же могут перехватить Посколько сервер и клиент обмениваются только публичными ключами, то атакующий может перехватить только публичные ключи, знание публичного ключа без знания секретного ключа бесполезно. Знает ли браузер алгоритм шифрования? - это открытая информация? Да, это открытая информация. В криптографии защита на основе незнания алгоритма шифрования не считается надежной защитой. Скорее даже наоборот, знание алгоритма - это наоборот способ защиты - как некая гарантия надежности алгоритма. Существует определенная процедура как бы сертификации алгоритмов, которая и подтверждает его надежность - то есть устойчивость к разнообразным атакам. В случае SSL/TLS для обмена ключами используются RSA и DH, а для обмена в пределах сессии используются симметричные алгоритмы IDEA и AES.

пятница, 24 января 2020 г.

Нужно ли настраивать Apache для работы с SSL, если я использую Nginx (proxy) + Apache?

#apache #nginx #ssl


У меня есть сервер с Ubuntu Server 16.04, схема работы веб-сервера стандартная (Apache
+ mod_php + Nginx как прокси)
Настроил Nginx для работы с установленным SSL сертификатом, надо ли тоже самое проделывать
с Apache(имею ввиду настройку Apache для работы с SSL)?
    


Ответы

Ответ 1



Нет не нужно, если запросы идут только на nginx, а так же nginx и apache находятся на одном сервере. Если nginx и apache находятся на разных серверах, то настоятельно рекомендуется использовать безопасное соединение.

воскресенье, 12 января 2020 г.

SSL авторизация на сайте по сертификату в связке с логином и паролем

#ssl #java


Подскажите что я делаю не так? 

Необходима авторизация на сайте https://test.local, для авторизации используется
сертификат cert.pfx и связка логин:пароль. 
cert.pfx - я экспортировал из браузера firefox, что бы действительно убедиться что
сертификат верный я его импортировал(в веб браузер) на другие машины. авторизация проходила
успешно.

Из полученного сертифката я создал keystore.jks 

openssl pkcs12 -in custom_cert.p12 -out custom_cert.pem -nodes -nokeys
openssl pkcs12 -in custom_cert.p12 -out custom_key.pem -nodes -nocerts

openssl pkcs8 -topk8 -nocrypt -in custom_key.pem -inform PEM -out custom_key.der
-outform DER
openssl x509 -in custom_cert.pem -inform PEM -out custom_cert.der -outform DER


Вот так вот выглядит мое подключение

String URL = "test.local";

 try {

            KeyStore kS = KeyStore.getInstance( KeyStore.getDefaultType() );
            FileInputStream fIS = new FileInputStream("keystore.jks"); 
            kS.load(fIS, "123456".toCharArray());

            KeyManagerFactory kMF = KeyManagerFactory.getInstance("SunX509");
            kMF.init(kS, "123456".toCharArray());
            KeyManager[] kMs = kMF.getKeyManagers();

            TrustManagerFactory tMF = TrustManagerFactory.getInstance("SunX509");
            tMF.init(kS);
            TrustManager[] tM = tMF.getTrustManagers();


            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(kMs, tM, new SecureRandom());
            SSLContext.setDefault(sslContext);
            javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            SSLSocket sslClientSocket = (SSLSocket) sslSocketFactory.createSocket(URL,443);
            sslClientSocket.startHandshake();


            HttpHost targetHost = new HttpHost(URL, 443, "https");
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);



            CredentialsProvider credsProvider = new BasicCredentialsProvider();
            credsProvider.setCredentials(
                    new AuthScope(targetHost.getHostName(),443),
                    new UsernamePasswordCredentials("Fedya.Ivakin", "191919"));

            HttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .setDefaultCredentialsProvider(credsProvider)
                    .setSslcontext(sslContext)
                    .build();

            AuthCache authCache = new BasicAuthCache();           
            BasicScheme basicAuth = new BasicScheme();
            authCache.put(targetHost, basicAuth);

            HttpClientContext context = HttpClientContext.create();
            context.setCredentialsProvider(credsProvider);

            HttpGet httpget = new HttpGet("/");

            HttpResponse response = httpclient.execute(targetHost, httpget, context);
            System.out.println(response.getStatusLine());


В результате получаю HTTP/1.1 403 Forbidden.

Хотя ошибок ни каких нет, куда копать? подскажите пожалуйста.
    


Ответы

Ответ 1



Кучу сайтов перерыл. Встречал такие утверждения, что pkcs12 сертификаты java не понимает и надо их конвертировать и кучу еще чего. Но вот так у меня проходит авторизация по сертификату + логин пароль. String URL = "https://test.local:443"; URL url = new URL(URL); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); con.setSSLSocketFactory(getFactory1(new File("key/User.pfx"), "123456")); Authenticator.setDefault(new MyAuthenticator()); con.setAllowUserInteraction(true); con.setRequestMethod("GET"); con.connect(); domain необходимо указывать именно через два слеша, плюс не нужно указывать зону(ru и тп). Например логин и пароль у нас такой Ivan.Petrov@domain.ru - это логин, 123456 - это пароль class MyAuthenticator extends Authenticator { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("domain\\Ivan.Petrov", "123456".toCharArray()); } } == private SSLSocketFactory getFactory1(File pKeyFile, String pKeyPassword) throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException { KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); KeyStore keyStore = KeyStore.getInstance("PKCS12"); InputStream keyInput = new FileInputStream(pKeyFile); keyStore.load(keyInput, pKeyPassword.toCharArray()); keyInput.close(); keyManagerFactory.init(keyStore, pKeyPassword.toCharArray()); TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { //To change body of implemented methods use File | Settings | File Templates. } public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; SSLContext context = SSLContext.getInstance("TLS"); context.init(keyManagerFactory.getKeyManagers(), trustAllCerts, new SecureRandom()); return context.getSocketFactory(); } Ничего ни пришлось конвертировать и тп. Необходимо экспортировать сертификат пользователя из браузера и закинуть его в приложение.

Ответ 2



Здравствуйте, попробуйте как описано здесь

суббота, 11 января 2020 г.

Как работает SSL в мобильных приложениях?

#алгоритм #ssl #шифрование #сертификат


В браузере все понятно, у него заранее есть список вшитых сертификатов CA, которыми
он проверяет сертификат сервера... Но как происходит проверка в мобильных приложениях?
Или, допустим, когда я отправляю запрос, допустим, через BurpSuite?
    


Ответы

Ответ 1



Общие принципы SSL (а точнее, инфраструктуры ключей) продолжают работать и в контексте мобильных приложений. Набор CA (или, по-русски, ЦС – центров сертификации): может быть размещен в ОС (чаще всего, т. к. он используется по умолчанию [обычно]). может поставляться с приложением (что не такая уж редкость, см. Firefox). может отсутствовать вовсе, если клиент заранее знает публичный ключ сервера сам, или может попросить пользователя проверить отпечаток ключа в интерфейсе (привет, SSH!), или просто плевать хотел на безопасность (и такое бывает! ¯\_(ツ)_/¯). Может использоваться несколько вариантов сразу. Например, Яндекс.Браузер использует гибрид: он рассчитывает на системное хранилище, но отпечатки (хэши) сертификатов ЦСов оттуда сравнивает с известными ему (за уточнение механизма спасибо Abyx). Их немного, поэтому зашить в бинарник не проблема. Таким образом ЯБ пытается предупреждать ситуации, в которых соединение пользователя компрометируется через сторонний ЦС, установленный в систему без его ведома. Так что, как видите, SSL довольно хорошо гнётся под разные ситуации. Но реально этим богатством редко пользуются. В подавляющем большинстве случаев сервер имеет ключ, заверенный известным ЦС, а клиент имеет только пачку известных ЦС в ОС. Сервер предоставляет доказательства, указывающие через известные ЦС на подлинность своего ключа. Так клиент понимает, что это тот самый сервер.

Ответ 2



Если говорить про Android (он построен на ядре Linux), там есть папка с сертификатами /etc/ssl, в которой хранится список всех установленных сертификатов в системе. Мобильные приложения при установке защищенного соединения обращаются к этому списку.

Сайт на apache 2 при доступе по ip через https предупреждает о небезопасном соединении

#linux #apache #http #ssl #apache2


Дано:

debian, apache2 на vps, ssl-сертификат и домен. 

Сертификат вот так подключен в настройках apache:

файл /etc/apache2/apache2.conf:


    DocumentRoot "/var/www/html"
    ServerName mydomain.ru
    ServerAlias www.mydomain.ru

    # Other directives here
        SSLEngine on
        SSLCertificateFile /path/to/domain_name.crt
        SSLCertificateKeyFile /path/to/private.key
        SSLCertificateChainFile /path/to/chain.crt



    DocumentRoot "/var/www/html"
    ServerName mydomain.ru
    ServerAlias www.mydomain.ru

    # Other directives here



Сам домен ещё не до конца, видимо, прописался на dns серверах и я пробую к сайту
через IP ходить.

Проблема:

В итоге я могу по адресам http://x.x.x.x и https://x.x.x.x попасть на сайт, но в
случае https браузер жутко ругается на небезопасность соединения. При этом в информации
о сертификате браузер говорит что всё ОК и сертификат этот связан с моим доменом.

Вопрос:

Так и должно быть и проблема исчезнет когда я буду на сайт ходить по имени домена
вместо IP? Можно ли это починить чтобы я мог ходить по IP-адресу без ругани на безопасность?
    


Ответы

Ответ 1



ответ частично основан на этом ответе. сертификат, соответствующий стандарту x.509, удостоверят «имя субъекта» (subject). наиболее интересно нам «общепринятое имя» (common name), являющееся частью «имени субъекта». как правило, оно содержит fqdn. пример для сертификата, которым подтверждается аутентичность http-сервера, доступного по доменному имени ya.ru: $ : | openssl s_client -connect ya.ru:443 2>/dev/null | openssl x509 -noout -subject -nameopt RFC2253 subject=CN=ya.ru,ST=Russian Federation,L=Moscow,OU=ITO,O=Yandex LLC,C=RU CN=ya.ru — вот это и есть подтверждаемое сертификатом «общепринятое имя» (common name, сокращённо cn) — ya.ru. с точки зерния стандарта «общепринятое имя», в общем, произвольно. и в применении к сертификатам, подтверждающим аутентичность http-сервера может, теоретически, содержать не доменное имя, а, например, ip-адрес: ведь он ничем не «хуже», чем любая другая произвольная строка символов. но на практике такое не встречается (хотя на сайте у какого-то из регистраторов я даже встечал упоминание возможности подтвердить сертификатом ip-адрес). стоит упомянуть, что нынче одним сертификатом может подтверждаться целый набор доменных имён. пример с тем же сертификатом: $ : | openssl s_client -connect ya.ru:443 2>/dev/null | openssl x509 -noout -text | grep DNS DNS:ya.ru, DNS:www.ya.ru, DNS:m.ya.ru выданный же вам сертификат с вероятностью, равной единице, удоствоверяет именно доменное имя. убедитесь сами: $ cat файл.с.сертификатом | openssl x509 -noout -subject -nameopt RFC2253 поэтому вполне естественным является предупреждение от вашего http-клиента о небезопасности соединения — ведь строка какое-то.доменное.имя (которую он «видит» внутри сертификата) абсолютно не совпадает со строкой какой-то.ip-адрес (которую вы ввели в адресной строке клиента). по поводу того, как же проверить сертификат (средствами http-клиента), если доменное имя пока не резолвится в нужный ip-адрес, посмотрите, например, этот ответ.

четверг, 9 января 2020 г.

Почему браузер считает валидным сертификат от другого домена?

#ssl #браузер


Сейчас только обратил внимание, что на сайте ru.stackoverflow.com установлен сертификат
*.stackexchange.com -- и вообще-то браузеры должны предупреждать при заходе на сайт
о невалидном сертификате.



Тем не менее -- в строке браузера стоит зелёный замок, соединение защищено. Почему
так происходит?

Насколько я понимаю -- должно выдаваться сообщение "SSL_ERROR_BAD_CERT_DOMAIN", типа
такого:


    


Ответы

Ответ 1



А вы загляните в раздел X509v3 Subject Alternative Name, в нем как раз перечисляются прочие домены, для которых данный сертификат будет действителен: DNS:.stackexchange.com, DNS:stackoverflow.com, DNS:.stackoverflow.com, DNS:stackauth.com, DNS:sstatic.net, DNS:.sstatic.net, DNS:serverfault.com, DNS:.serverfault.com, DNS:superuser.com, DNS:.superuser.com, DNS:stackapps.com, DNS:openid.stackauth.com, DNS:stackexchange.com, DNS:.meta.stackexchange.com, DNS:meta.stackexchange.com, DNS:mathoverflow.net, DNS:.mathoverflow.net, DNS:askubuntu.com, DNS:.askubuntu.com, DNS:stacksnippets.net, DNS:.blogoverflow.com, DNS:blogoverflow.com, DNS:.meta.stackoverflow.com, DNS:*.stackoverflow.email, DNS:stackoverflow.email

понедельник, 6 января 2020 г.

Настроить ssl на nginx

#linux #nginx #ssl #dns


Здравствуйте!

Есть некий сервер, на котором nginx слушает один адрес (допустим, 1.1.1.1). Адрес
резолвится в большую кучу dns-имён, при чём, самых разных. Допустим, у меня для каждого
имени есть свой SSL-сертификат. Как мне настроить nginx, чтоб они для каждого имени
ассоциировал свой сертификат?
    


Ответы

Ответ 1



Насколько я понимаю, у вас сервер имеет ip 1.1.1.1, на нем nginx и много dns указывают в A-записи на 1.1.1.1 Тогда так server { listen 80; server_name site1.com www.site1.com; rewrite ^(.*) https://$host$1 permanent; } server { listen 443; ssl on; ssl_certificate /etc/nginx/ssl/site1.pem; ssl_certificate_key /etc/nginx/ssl/site1.key; server_name site1.com www.site1.com; root /var/www/site1; ... } server { listen 80; server_name site2.com www.site2.com; rewrite ^(.*) https://$host$1 permanent; } server { listen 443; ssl on; ssl_certificate /etc/nginx/ssl/site2.pem; ssl_certificate_key /etc/nginx/ssl/site2.key; server_name site2.com www.site2.com; root /var/www/site2; ... } Для каждого сайта сначала слушаем порт 80, делаем rewrite с http на https, потом слушаем 443. Это выдержка из рабочего конфига nginx.

Ответ 2



насколько я помню можно конфиги для разных сайтов вынести из основного. ссылка

пятница, 27 декабря 2019 г.

Перехват SSL траффика

#ssl #firefox #cpp


Требуется перехватить траффик flash приложения запущенном в firefox. Как это сделать?
Вижу варианты:

Через прокси. Но по большому счету тут уже зашифрованный траффик и ничего с ним не
сделаешь.
Через сам firefox, через расширения или перехват функции перед шифрованием.
    


Ответы

Ответ 1



Можно добавить в Firefox свой сертификат и использовать sslsplit. Если флеш использует свою базу сертификатов, то тогда нужно и туда. Также обычный FireBug (или встроенный в Firefox аналог) часто показывает запросы от флеша.

Ответ 2



Попробуйте использовать Charles, он выступает в роли локального прокси. При его установке Charles автоматически предложит установить плагин для firefox. Далее нужно установить корневой сертификат: меню Tools(Инструменты?) > Charles > "Install Charles Root Certificate". Так же в самой программе нужно будет добавить адрес сайта, трафик которого вы хотите перехватывать: Proxy Settings, вкладка SSL. Сам давно не пользовался, так что больше подсказать не могу, читайте документацию на официальном сайте.

среда, 25 декабря 2019 г.

Функция fsockopen перестала работать с ssl

#php #centos #ssl #openssl


На vps (CentOS 7) перестала работать функция fsockopen с протоколом ssl:

fsockopen('ssl://smtp.yandex.ru', 465, $errnum, $errstr, 5);


Результат возвращает false, $errnum = 0, $errstr = ''. С другими протоколами проблем
нет. Месяц назад работало, за месяц много что настраивал на vps, теперь не могу определить
проблему. В лог ошибок попадает следующее:

FastCGI sent in stderr: "PHP message: PHP Warning:  fsockopen():
SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
in /site/fsockopen.php on line 3
PHP message: PHP Warning:  fsockopen(): Failed to enable crypto in /site/fsockopen.php
on line 3
PHP message: PHP Warning:  fsockopen(): unable to connect to ssl://smtp.yandex.ru:465
(Unknown error) in /site/fsockopen.php on line 3"

    


Ответы

Ответ 1



Всем спасибо, кто помогал, проблему решил следующим образом: Скачал сертификат от сюда: http://curl.haxx.se/ca/cacert.pem и положил его в каталог /etc/ssl/certs/ В php.ini прописал: openssl.cafile=/etc/ssl/certs/cacert.pem Выставил стандартные права на каталог /etc/pki/, так как в данной системе /pki/tls/certs/ смонтировано на /etc/ssl/certs/ (не хватало прав чтобы прочитать сертификат, это видимо одна из основных проблем которую я не замечал, по ошибке неправильные права выставил на /etc/pki/ когда что то делал на сервере)

среда, 11 декабря 2019 г.

Взломали сайт, помогите найти дыру в защите

#администрирование #ssl #хостинг #защита #взлом


Доброго времени суток!

Я администрирую сайты у нас в компании.
Недавно нам взломали сайт, и не один. Атакам ежедневно подвергаются все сайты, находящиеся
на хостинге. Выглядит это как добавление php файлов, архивов и целых папок в корни
сайтов и в директории типа images.
Результатами взлома сначала являлась подмена главной страницы для роботов гугл, затем
2 рассылки с нашего почтового сервера и рассылка со ссылкой на нехороший файл на одном
из наших сайтов.

Что было сделано:


Почистили все от вредоносного кода, обновили cms основного нашего сайта, так как
сначала думали, что только он был взломан, запретили доступ к системным папкам по другим ip.
Поменяли все пароли (к ftp, cms, бд). 
Дальнейшие действия не очевидны. Наш хостер не дает изолировать друг от друга папки
на хостинге, как и не может ограничить доступ к ftp по другим ip( 


Какой следующий шаг?

UPD 4.12.17


Установили на всех сайтах логи доступа.
Прогнали сайты через ai-bolit, появилась почва для размышления и поле для деятельности.
После вычистки и настройки сайтов будем их разносить по разным хостингам и наблюдать.


UPD 18.12.17


На прошлой неделе выложил на хостинг чистые копии сайтов. Ограничил доступы к системным
папкам и отключил register_globals через .htaccess.
С тех пор проблемы со взломом не возникали. Скоро будем переезжать на новый хостинг. 


Спасибо всем за помощь. С наступающим вас!
    


Ответы

Ответ 1



Можно попробовать перекрыть вот этот вектор атаки: Выглядит это как добавление php файлов, архивов и целых папок в корни сайтов и в директории типа images. Но для этого необходима возможность создавать на сервере новых пользователей и настраивать веб-сервер, т.е. эта инструкция - не для шаред-хостинга. 1. Разделяем пользователя-владельца сайта и пользователя от которого работает веб-сервер. Второму пользователю запрещается доступ на запись во все директории кроме тех куда пользователи могут загружать файлы. В UNIX-подобных ОС без использования ACL такого поведения можно достигнуть включив обоих пользователей в одну группу, далее первый пользователь делается владельцем файлов и директорий, и права на файлы устанавливаются 640 (740 на директории или 750 если важен листинг директории). 2. В тех директориях, куда разрешается загрузка пользовательских файлов - запрещаем запуск любых скриптов на уровне веб-сервера. В Apache для этого надо прописать примерно следующее (только изучите свой конфиг чтобы увидеть реальные типы возможных скриптов - ну или выключите все что не используете): RemoveHandler .php .phtml .php3 RemoveType .php .phtml .php3 AllowOverride None Также конфиг выше отключает поддержку .htaccess в этих директориях, потому что в противном случае при наличии дыр злоумышленник может загрузить этот файл и разрешить самому себе запускать скрипты. При использовании Nginx надо закрыть директории со статикой от поиска в них скриптов через использование ^~: location ^~ /uploads/ { try_files $uri =404; } Также в случае использования сайтом паттерна Front Controller можно отказаться от популярного location ~* \.php(/|$) в пользу непосредственного направления нужных маршрутов на фронт-контроллер (да, для этого придется внимательно изучать используемую CMS): location / { fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME /path/to/index.php; fastcgi_param PATH_INFO $uri; } Если у вас внезапно Windows и IIS - надо убрать все обработчики кроме статических файлов и заблокировать конфигурацию от изменений: Важно сделать это именно через location в файле более высокого уровня, чтобы злоумышленник не мог обойти ограничение через замену файла web.config в доступной для записи папке. 3. После закрытия папок куда пользователи могут загружать файлы от загрузки туда серверных скриптов надо закрыть их от загрузки html-страниц. Это уже атака не на ваш сервер, а на ваших пользователей - но это же не означает что от нее не надо защищаться? В Apache это делается через RemoveType .html (полный список типов уточните в своем конфиге), в nginx надо будет явно перечислить разрешенные к загрузке типы файлов (types { ... }), а в IIS это делается настройкой system.webServer/staticContent по аналогии со списком обработчиков (там можно как удалить несколько типов так и полностью составить список с нуля). Если веб-сервер настроен правильно - то злоумышленнику будет намного труднее пользоваться имеющимися дырами. А дыр связанных с загрузкой пользовательских файлов можно будет и вовсе не бояться.

воскресенье, 8 декабря 2019 г.

Почему при шифровании TLS используются именно простые числа?

#алгоритм #безопасность #ssl #шифрование #криптография


Почему при шифровании TLS, да и вообще в криптографии используются именно простые
числа? Почему бы не использовать любые? 
    


Ответы

Ответ 1



Одна причина в том, что легко умножить 2 большие простые числа, например 393050634124102232869567034555427371542904833 * 170141183460469231731687303715884105727 дает сразу 66874100049762646240147492397977579549553083399872470020691839934725993584071278591 (Python, < 0.2 секунд), no обратное сделать (разложить большое число на простые числа) практически не возможно - нет общего достаточно быстрого алгоритма (см. Алгоритмы факторизации.) Вообще это работа на несколько лет даже для супер компьютеров.

Ответ 2



TLS допускает использование различных протоколов шифрования и обмена ключей. Разные протоколы используют простые числа по совершенно различным причинам: RSA Один из самых популярных протоколов шифрования, RSA, основывается на том, что задача факторизации числа - разложение составного числа на простые множители (скорее всего), не разрешима с полиномиальной сложностью на обычных компьютерах (но разрешима за полиномиальное время на квантовых, криптоапокалипсис грядет). Т.е. если у вас есть два огромных простых числа p и q, то тот, кто знает только n = p * q, проведет достаточно много времени, пытаясь разложить n обратно на p и q. Естественно, есть оговорки, позволяющие отсечь известные субэкспоненциальные алгоритмы, например, p и q должны отличатся порядком хотя бы на пару разрядов, но в общем случае можно считать что большие p и q сделают решение задачи факторизации n дико долгим. При этом, найти два больших простых числа - достаточно легко. Так что использование больших простых чисел - это способ получить огромное и тяжело факторизируемое составное число. RSA описывает подбор/генерацию чисел e, d, n, таких, что для любого значения m будет справедливо: Способ генерации предполагает выбор n = p * q, e = 65,537 (или любому другому небольшому числу). Т.е. они находятся быстро. Пара (n, e) - это публичный ключ. Доказано, что если взять в качесте d результат решения уравнения ed = 1(mod ϕ(n)), то тройка (e, d, n) будет отвечать требованию выше. ϕ(n) - это функция Эйлера - равная количеству натуральных чисел, меньших n и взаимно простых с ним. Для ее нахождения нужно факторизовать n. Т.е. если вы знаете только (n, e), то поиск d решением этого уравнения займет вечность. Но при этом φ(p) = p − 1, φ(q) = q − 1. И для простых p и q: φ(n) = φ(pq) = (p − 1) * (q − 1). Так что вы берете два больших простых числа, быстро вычисляете φ(n) и n, получаете d из уравнения выше. Простые числа и φ(n) выбрасываете и никому не показываете. (n, d) - это ваш приватный ключ, и узнать его, зная только (n, e), ни у кого не получится за разумное время. После этого любой, у кого есть ваш публичный ключ может зашифровать для вас сообщение: А вот расшифровать его можете только вы: Из взаимозаменяемости e и d и одинаковости для шагов для шифрации/дешифрации следует второй способ применения RSA - только вы можете зашифровать известный текст так, что расшифровать его можно будет только с помощью публичного ключа. Если вы допишете к концу сообщения его чексумму, зашифрованную приватным ключом (получив при этом "электронную подпись"), то любой может посчитать ту же чексумму, "расшифровать" подпись, и сравнить два значения. Если они совпадут - значит сообщение дошло без изменений, и отправили его именно вы. Diffie-Hellman Протокол обмена ключами DH полагается не на сложность факторизации, а на сложность решения задачи дискретного логарифмирования. Он основан на том, что нельзя быстро вычислить ключ зная только ga, gb, g и p. Но при этом он легко позволяет сторонам вычислить этот общий ключ, переслав по открытому каналу ga, gb, если одна сторона придумает свое секретное a, а вторая - свое секретное b. Elliptic Curve Diffie-Hellman Даже основы эллиптической криптографии в один пост SO не влезут, так что стоит только упомянуть, что ECDHE так же полагается не на сложность факторизации, а на сложность решения задачи дискретного логарифмирования. Для задачи дискретного логарифмирования есть субэкспоненциальный алгоритм Полига-Хеллмана, позволяющий свести решение проблемы для n точек к подзадачам для множителей n - p1, p2, p3, p4. Соответственно, количество точек кривой выбирают таким, чтобы оно делилось на какое-то большое простое число p, сравнимое по длине с n. Т.е. простые числа в ECDHE используются только косвенно, в качестве "ограничителя простоты". Из этих же соображений значения p, g в DH накладываются соответствующие ограничения.

Ответ 3



На самом деле ничего суперсложного здесь нет. 1) TLS базируется на асимметричной криптографии, в каковой есть понятие приватного и публичного ключей 2) Если не вдаваться в математические тонкости асимметричной криптографии, навроде теоремы Эйлера, Ферма, Галуа и проч. мастодонтов то эти ключи (например, в алгоритме RSA) вычисляется на основе целых числе p, q (необязательно кстати и простых): PublicKey={e(p,q), p*q} //e(p,q) - некая целочисленная функция (публичная экспонента) PrivateKey={d(p,q), p*q) //d(p,q) - также некая целочисленная функция (приватная экспонента) грубо говоря, если знать эти 2 числа p, q то можно вычислить ключи. Теперь внимание, атакующему всегда известно их произведение p*q - из публичного ключа, который как явствует из его названия известен всем. 3) То есть чтобы дешифровать надо просто разложить некое число n на 2 множителя p, q. Задача называется факторизацией - алгоритмов масса, но в целом все очень печально (с точки зрения скорости). 4) Подходим к самому главному - ради чего весь цирк с конями и затевался: зачем требуется, чтобы p, q были простыми? Здесь есть 2 ответа: Функции e(p, q) и d(p, q) - работают не со всеми числами, то есть если подать им на вход непростое число, то функции могут не дать ничего. Зато если p, q простые то функции работают безупречно. Для усложнения факторизации n: разложение большого числа на простые сомножители усложняется с ростом длины числа как n*log(n), то есть вы раскладываете 1024 битовое число, то сложность грубо говоря будет 1024*2^1024, но если число вдруг окажется четным то его сложность составит уже 512*2^1023 - то есть вычислительная сложность упадет в 4 раза - соответственно простота гарантирует увеличение вычислительной сложности.

Ответ 4



Кажется разобрался с этой темой. На примере Диффи-Хеллмана. Чтобы найти ключ K, нужно решить уравнение K=g^a*b mod p, где "g", "p" - известно. Произведение простых чисел (очень больших) действительно сложно подобрать. И нужно использовать именно простые числа потому что нет базы данных среди больших простых чисел (а базы данных нет потому что нереально перебрать такие большие цифры), иначе бы это сильно ускорило решение задачи, как и со всеми числами. Но это в теории, а на практике серьезные взломщики вряд ли будут перебирать произведение 2-ух простых чисел. Т.к. чтобы найти секретный ключ K, можно решить и другое уравнение, которое тоже равно секретному ключу. K=B^a mod p, где "p" известно, а "B" можно перехватить (т.к. эта информация в незащищенном видео передается по сети). И тогда уже останется подобрать только "a". А если учесть, что "a" - как минимум нечетное и огромное (порядка 10^100) - отбросить на конце четные и диапазон слишком маленьких чисел. Хотя даже при всем при этом "a" замучаешься подбирать)

Ответ 5



В TLS для генерации ключей чаще всего используется криптоалгоритм RSA. В его основе лежит предположение, что факторизация произведения простых чисел является вычислительно сложной операцией. Легко умножить два простых числа, но очень сложно имея только произведение получить исходные числа. На сегоднешний день не существует эффективного алгоритма, который позволяет это сделать быстро.

Что именно разработчики .NET 4.6.2 изменили в SslStream помимо SSL3?

#c_sharp #net #ssl #tls


Описание проблемы: пользователи поголовно начали жаловаться на странное поведение
программы (которая была написана на .NET 4.5) после автоматического обновления Windows.
Начал разбираться, тестировать. Воспроизвел проблему у себя на .NET 4.6.2. Оказывается
транспорт SslStream начиная с .NET 4.6 поменял свое поведение. Причем непонятно в каком
месте. 

Взял сторонний транспорт (Chilkat), сравнил - везде получается одинаковые параметры,
TLS 1.0, Cipher - Aes128, Hash - Sha1, одинаковые байты идущие через соединение...

Но! - Chilkat отрабатывает нормально, а SslStream рвет соединение на ReadAsync с
исключением: IOException, сбой операции дешифрования. Журналы ошибок Windows пустые.

Вопрос: что конкретно изменилось в реализации?

p.s. Switch.System.Net.DontEnableSchUseStrongCrypto=true в appconfig не помогает,
поведение не меняется. 



Update: 

Посмотрел локальные исключения, вот что всплыло: System.ComponentModel.Win32Exception
(0x80004005): Не удается установить связь с локальной системой безопасности. Погуглил,
нашел что это связано с лицензией на Windows. Хоть убейте не понимаю чем связана неактивированная
тестовая Windows с работоспособностью SslStream. Клиентов ведь не заставишь поголовно
покупать лицензии...

Часть синхронного стека вызовов:

System.dll!System.Net.Security._SslStream.ProcessReadErrorCode(System.Net.SecurityStatus
errorCode = {неизвестно}, byte[] buffer = {неизвестно}, int offset = {неизвестно},
int count = {неизвестно}, System.Net.AsyncProtocolRequest asyncRequest = {неизвестно},
byte[] extraBuffer = {неизвестно})
    System.dll!System.Net.Security._SslStream.ProcessFrameBody(int readBytes = {неизвестно},
byte[] buffer = {неизвестно}, int offset = {неизвестно}, int count = {неизвестно},
System.Net.AsyncProtocolRequest asyncRequest = {неизвестно})
    System.dll!System.Net.Security._SslStream.StartFrameHeader(byte[] buffer = {неизвестно},
int offset = {неизвестно}, int count = {неизвестно}, System.Net.AsyncProtocolRequest
asyncRequest = {неизвестно})
    System.dll!System.Net.Security._SslStream.StartReading(byte[] buffer = {неизвестно},
int offset = {неизвестно}, int count = {неизвестно}, System.Net.AsyncProtocolRequest
asyncRequest = {неизвестно})
    System.dll!System.Net.Security._SslStream.ProcessRead(byte[] buffer = {неизвестно},
int offset = {неизвестно}, int count = {неизвестно}, System.Net.AsyncProtocolRequest
asyncRequest = {неизвестно})
    System.dll!System.Net.Security._SslStream.Read(byte[] buffer = {неизвестно},
int offset = {неизвестно}, int count = {неизвестно})
>   Application.exe!d__a.MoveNext()




Update2: 

Провел ряд тестов в процессе воспроизведения проблемы для публичного обозрения -
по предварительным данным виноват Cipher = Aes128, тот же Aes256 - работает нормально.
    


Ответы

Ответ 1



Для .NET 4.+ и x64 разрядных ОС, глобальный вариант: Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319] "SchSendAuxRecord"=dword:00000000 Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319] "SchSendAuxRecord"=dword:00000000 Для .NET 2.+ и x64 разрядных ОС, глобальный вариант: Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v2.0.50727] "SchSendAuxRecord"=dword:00000000 Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727] "SchSendAuxRecord"=dword:00000000 Действует сразу, перезапуск ОС не требуется. Использовать только в крайнем случае!!! Выключение этой структуры связано с большими рисками по отношению к старым версиям SSL\TLS транспорта ОС.

понедельник, 15 июля 2019 г.

Как реализовать схему nginx-nginx ssl?

На фронтенде nginx, на бакэнде nginx с сертификатами.
Как мне пробросить запросы на бакэнд? или надо пробросить сертификаты на фронтенд?
Сейчас напрямую форвардятся все запросы к 443 на бакэнд через iptables, но реальный ip адрес не передается, а надо.
Через iptables этого не сделать, надо как-то через nginx.


Ответ

Через iptables этого не сделать (ссылка)
по ссылке описана несколько иная сетевая схема: два сервера, подключенные к интернету независимо друг от друга.
в вашем же случае (когда у второй машины шлюзом по умолчанию указана первая) это вполне реализуемо: Проброс реального ip-адреса в виртуальную машину за nat но более гибким решением, по-моему, будет обработка ssl на первой из машин («шлюзе»). тогда из поступающих https-запросов можно будет узнать целевое доменное имя и проксировать уже http- (не https-) пакеты на нужные http-серверы внутри вашей сети. а на этих серверах уже можно принимать и обрабатывать http- (не https-) трафик.
для того же, чтобы дать понять этим серверам, что https таки используется, можно устанавливать де-факто стандартный заголовок x-forwarder-proto, и эти серверы затем смогут сообщить сайтам об этом факте (например, некоторые cms имеют привычку делать редирект на https, если «обнаруживают», что используется http, например, для авторизации пользователей).
как этот заголовок обработать в apache, написано, например, здесь
ServerName ... ... SetEnvIf X-Forwarded-Proto https HTTPS=on ...
как этот заголовок обработать в nginx, написано, например, здесь
server { ... set_scheme_from ip-адрес-шлюза; real_scheme_header X-Forwarded-Proto; ... }

суббота, 22 июня 2019 г.

как воспользоваться сертификатами от проекта let's encrypt?

с 3 декабря 2015 года проект let's encrypt перешёл в режим "public beta".
как воспользоваться сертификатами, выдаваемыми этим проектом?


Ответ

можно воспользоваться любой из реализаций клиентов, работающих с системой let's encrypt
например, есть пошаговая инструкция для официального клиента.

но мне понравился минималистичный shell-скрипт из репозитория lukas2511, который не требует ни повышенных привилегий для своей работы, ни установки дополнительных программ/пакетов (всё необходимое обычно уже имеется в любой «серверной» установке: bash, openssl, curl и утилиты из coreutils).
как я настроил этот клиент
для пущей безопасности я создал пользователя letsencrypt (без пароля):
$ sudo adduser --disabled-password letsencrypt открыл сеанс оболочки от имени этого пользователя:
$ sudo -u letsencrypt -i letsencrypt@host:~$ склонировал репозиторий со скриптом и «перешёл» в созданный каталог:
$ git clone https://github.com/lukas2511/letsencrypt.sh.git $ cd letsencrypt.sh
если git не установлен, можно скачать архив с файлами и распаковать. скопировал образцовый конфиг:
$ cp config.sh.example config.sh создал файл domains.txt для домена (мне требуется, чтобы в сертификате были имена и с www и без):
domain.tld www.domain.tld
если требуются на этой же машине и сертификаты для других доменов, то можно добавить ещё строк в этот файл, по строке для каждого сертификата. создал каталог для аутентификации
$ mkdir .acme-challenges теперь на время надо вернуться к настройкам http-сервера. можно завершить сеанс пользователя letsencrypt, а лучше открыть другое окно с оболочкой более привилегированного пользователя.
в настройках http-сервера надо прописать alias для /.well-known/acme-challenge, чтобы он указывал на созданный в предыдущем пункте каталог. ориентировочно это будет /home/letsencrypt/letsencrypt.sh/.acme-challenges
для nginx в секцию server надо добавить location
location /.well-known/acme-challenge { alias /home/letsencrypt/letsencrypt.sh/.acme-challenges; } для apache в секцию virtualhost надо добавить строку:
alias /.well-known/acme-challenge /home/letsencrypt/letsencrypt.sh/.acme-challenges
это надо проделать для всех доменов (точнее, отдельных строк в созданном вами файле domains.txt).
http-сервер после этого надо перезапустить. теперь можно запускать скрипт для генерации сертификата(-ов). вернитесь к окну, где открыта оболочка, запущенная от имени пользователя letsencrypt (или запустите новую и перейдите в каталог со скриптом):
$ ./letsencrypt.sh -c
если всё пойдёт нормально, последней строкой выдачи будет:
+ Done! сертификат и ключ для домена сгенерированы и лежат в каталоге /home/letsencrypt/letsencrypt.sh/certs/domain.tld
cert.pem privkey.pem
в принципе, это symlink-и на актуальные версии этих файлов, которые лежат в том же каталоге и в названии которых присутствует метка времени. типа cert-1453143084.pem теперь можно прописывать эти файлы в настройках http-сервера:
файл с сертификатом: /home/letsencrypt/letsencrypt.sh/certs/domain.tld/cert.pem файл с ключом: /home/letsencrypt/letsencrypt.sh/certs/domain.tld/privkey.pem обновление сертификатов производится точно так же, как и генерация: от имени пользователя letsencrypt перейдите в каталог со скриптом и запустите скрипт с тем же самым параметром — ./letsencrypt.sh -c
можно создать соответствующую cron-задачу, которая через пару месяцев (сертификаты генерируются на 90 дней) выполнит скрипт (от имени этого пользователя и в нужном каталоге) и перезапустит http-сервер

среда, 12 июня 2019 г.

Время действия сертификата

Пользуюсь сертификатом от LetsEncrypt, подключил скрипт на автопродление, но вот боюсь, что он не продлится автоматически и на всех сайтах однажды появится ошибка безопасности.
В анализе с помощью sslanalyzer.comodoca.com поле Valid From должно каждый день обновляться (становиться текущей датой) или дата изменится на текущую только когда закончится срок действия сертификата и сработает автопродление?


Ответ

боюсь, что он не продлится автоматически
проконтролируйте. если до даты окончания действия сертификата осталось меньше месяца (только в таком случае letsencrypt согласится перевыпустить сертификат), а то (не знаю что), что вы запускаете для запроса нового сертификата, отработало, но сертификат остался прежним — пора разбираться с этим самым тем (не знаю чем).

ремарка: не имею ни малейшего представления, что это за сайт sslanalyzer.comodoca.com, и какую информацию он предоставляет.
но если речь про две даты: когда сертификат стал/станет действующим (notbefore), и когда сертификат прекратил/прекратит быть действующим (notafter), то они записаны непосредственно в сертификате и, конечно, не меняются.
получаете новый сертификат — у него будут новые даты начала и конца действия.
посмотреть их можно с помощью программы openssl примерно так:
$ openssl x509 -noout -startdate -enddate -in файл.с.сертификатом notBefore=Jun 7 15:26:28 2017 GMT notAfter=Aug 30 15:11:00 2017 GMT
или, скачав сертификат с действующего сервера:
http-сервер, порт 443 (https):
$ : | openssl s_client -connect google.com:443 2>/dev/null | openssl x509 -noout -startdate -enddate notBefore=Jun 7 15:26:28 2017 GMT notAfter=Aug 30 15:11:00 2017 GMT smtp-сервер, порт 25 (smtp, starttls):
$ : | openssl s_client -connect smtp.gmail.com:25 -starttls smtp 2>/dev/null | openssl x509 -noout -startdate -enddate notBefore=Jun 7 15:35:24 2017 GMT notAfter=Aug 30 15:11:00 2017 GMT imap-сервер, порт 143 (imap, starttls):
$ : | openssl s_client -connect imap.yandex.ru:143 -starttls imap 2>/dev/null | openssl x509 -noout -startdate -enddate notBefore=Apr 28 17:54:16 2016 GMT notAfter=Apr 28 17:54:16 2018 GMT imap-сервер, порт 993 (imaps)
$ : | openssl s_client -connect imap.gmail.com:993 2>/dev/null | openssl x509 -noout -startdate -enddate notBefore=Jun 7 15:28:03 2017 GMT notAfter=Aug 30 15:11:00 2017 GMT

четверг, 18 апреля 2019 г.

Где происходит шифрование данных, и где находится ключ tls/ssl?

Интересует вопрос безопасности https соединения.
Не могу понять, где именно происходит шифрование данных, когда запрашивается какой-нибудь сайт по https? - В браузере, в операционной системе клиента или вообще на сервере? Каким образом передается ключ браузеру, чтобы расшифровать сообщение? Просто в ответном сообщении или как-то еще, его же могут перехватить? Знает ли браузер алгоритм шифрования? - это открытая информация? Если так, то почему не используются закрытые алгоритмы (о которых никто не знает), или постоянно меняющиеся, чтобы злоумышленнику было сложнее разгадать?


Ответ

Шифрование происходит с обеих сторон. Ведь если шифровать будет только одна сторона (например только сервер), значит трафик от другой стороны (от клиента) будет не зашифрован. Его можно будет подслушать или даже изменить. Формально никто не передает никому ключ. В протоколе TLS клиент и сервер должны сгенерировать общий секрет (shared secret), набор из 48 байт. Потом клиент и сервер на основании общего секрета вычисляют ключи: ключ шифрования клиента и ключ шифрования сервера. Процедура вычисления ключей из общего секрета стандартная, и задана в описании протокола TLS. Сервер и клиент знают 2 ключа шифрования, одним шифруют, вторым дешифруют. А теперь самое интересное - как клиент и сервер вычисляют общий секрет. Это зависит от выбранного набора шифров:
TLS_RSA_WITH_: В данном случае клиент сам создает общий секрет генерируя 48 случайных байт. Затем он шифрует их при помощи публичного RSA ключа, который находится в сертификате сервера. Сервер получает зашифрованные данные, и расшифровывает их при помощи приватного RSA ключа. Данная схема используется редко. TLS_DHE_RSA_/TLS_ECDHE_RSA_/TLS_ECDHE_ECDSA_: Здесь используется криптографическая схема Диффи-Хеллмана (DHE) или ее версия на эллиптических кривих (ECDHE). Суть схемы такая: сервер и клиент генерируют случайные большие числа (приватные ключи), вычисляют на их основе другие числа (публичные ключи), и пересылают друг другу. Имея свой приватный ключ и публичный ключ другой стороны, они вычисляют общий секрет. Третья сторона, которая прослушивает канал, видит только 2 публичных ключа, и она не может вычислить общий секрет. После этого все данные, которыми обменивались клиент и сервер для получение этого ключа подписываются сертификатом сервера (RSA или ECDSA подписи). Если клиент доверяет сертификату сервера, он проверяет эту подпись, и если она правильная, начинается уже обмен данными. Это наиболее часто используемая схема. Есть еще несколько схем, но они используются очень редко или не используются вообще.
Про перехват. Как я выше описал, перехватывать сообщения здесь бесполезно, так как в первом случае его может расшифровать только сервер, а во втором используется хитрая криптографическая схема. Алгоритмы шифрования знает и сервер, и клиент. Ведь если клиент не знает, какой алгоритм шифрования, как он будет шифровать данные для отправки? В современной криптографии никто не использует закрытые алгоритмы. Открытые алгоритмы постоянно изучаются лучшими криптографами мира, ищутся уязвимости, и предлагаются решения для их обхода.
В TLS мы условно можем сказать, что алгоритмы меняются, так как каждый раз генерируются другие ключи шифрования. А потом, если вы хотите использовать закрытый алгоритм, например для просмотра веб-страницы, каким образом этот алгоритм может быть закрытый, если ваш компьютер/устройство производит шифрование/дешифрование?
Я упустил/упростил некоторые детали, что бы описать только основные идеи.

понедельник, 4 марта 2019 г.

Как работает SSL в мобильных приложениях?

В браузере все понятно, у него заранее есть список вшитых сертификатов CA, которыми он проверяет сертификат сервера... Но как происходит проверка в мобильных приложениях? Или, допустим, когда я отправляю запрос, допустим, через BurpSuite?


Ответ

Общие принципы SSL (а точнее, инфраструктуры ключей) продолжают работать и в контексте мобильных приложений. Набор CA (или, по-русски, ЦС – центров сертификации):
может быть размещен в ОС (чаще всего, т. к. он используется по умолчанию [обычно]). может поставляться с приложением (что не такая уж редкость, см. Firefox). может отсутствовать вовсе, если клиент заранее знает публичный ключ сервера сам, или может попросить пользователя проверить отпечаток ключа в интерфейсе (привет, SSH!), или просто плевать хотел на безопасность (и такое бывает! ¯\_(ツ)_/¯).
Может использоваться несколько вариантов сразу. Например, Яндекс.Браузер использует гибрид: он рассчитывает на системное хранилище, но отпечатки (хэши) сертификатов ЦСов оттуда сравнивает с известными ему (за уточнение механизма спасибо Abyx). Их немного, поэтому зашить в бинарник не проблема. Таким образом ЯБ пытается предупреждать ситуации, в которых соединение пользователя компрометируется через сторонний ЦС, установленный в систему без его ведома.

Так что, как видите, SSL довольно хорошо гнётся под разные ситуации. Но реально этим богатством редко пользуются.
В подавляющем большинстве случаев сервер имеет ключ, заверенный известным ЦС, а клиент имеет только пачку известных ЦС в ОС. Сервер предоставляет доказательства, указывающие через известные ЦС на подлинность своего ключа. Так клиент понимает, что это тот самый сервер.

пятница, 1 марта 2019 г.

Сайт на apache 2 при доступе по ip через https предупреждает о небезопасном соединении

Дано:
debian, apache2 на vps, ssl-сертификат и домен.
Сертификат вот так подключен в настройках apache
файл /etc/apache2/apache2.conf
DocumentRoot "/var/www/html" ServerName mydomain.ru ServerAlias www.mydomain.ru
# Other directives here SSLEngine on SSLCertificateFile /path/to/domain_name.crt SSLCertificateKeyFile /path/to/private.key SSLCertificateChainFile /path/to/chain.crt

DocumentRoot "/var/www/html" ServerName mydomain.ru ServerAlias www.mydomain.ru
# Other directives here

Сам домен ещё не до конца, видимо, прописался на dns серверах и я пробую к сайту через IP ходить.
Проблема:
В итоге я могу по адресам http://x.x.x.x и https://x.x.x.x попасть на сайт, но в случае https браузер жутко ругается на небезопасность соединения. При этом в информации о сертификате браузер говорит что всё ОК и сертификат этот связан с моим доменом.
Вопрос:
Так и должно быть и проблема исчезнет когда я буду на сайт ходить по имени домена вместо IP? Можно ли это починить чтобы я мог ходить по IP-адресу без ругани на безопасность?


Ответ

ответ частично основан на этом ответе

сертификат, соответствующий стандарту x.509, удостоверят «имя субъекта» (subject). наиболее интересно нам «общепринятое имя» (common name), являющееся частью «имени субъекта».
как правило, оно содержит fqdn. пример для сертификата, которым подтверждается аутентичность http-сервера, доступного по доменному имени ya.ru
$ : | openssl s_client -connect ya.ru:443 2>/dev/null | openssl x509 -noout -subject -nameopt RFC2253 subject=CN=ya.ru,ST=Russian Federation,L=Moscow,OU=ITO,O=Yandex LLC,C=RU
CN=ya.ru — вот это и есть подтверждаемое сертификатом «общепринятое имя» (common name, сокращённо cn) — ya.ru
с точки зерния стандарта «общепринятое имя», в общем, произвольно. и в применении к сертификатам, подтверждающим аутентичность http-сервера может, теоретически, содержать не доменное имя, а, например, ip-адрес: ведь он ничем не «хуже», чем любая другая произвольная строка символов. но на практике такое не встречается (хотя на сайте у какого-то из регистраторов я даже встечал упоминание возможности подтвердить сертификатом ip-адрес).
стоит упомянуть, что нынче одним сертификатом может подтверждаться целый набор доменных имён. пример с тем же сертификатом:
$ : | openssl s_client -connect ya.ru:443 2>/dev/null | openssl x509 -noout -text | grep DNS DNS:ya.ru, DNS:www.ya.ru, DNS:m.ya.ru

выданный же вам сертификат с вероятностью, равной единице, удоствоверяет именно доменное имя.
убедитесь сами:
$ cat файл.с.сертификатом | openssl x509 -noout -subject -nameopt RFC2253
поэтому вполне естественным является предупреждение от вашего http-клиента о небезопасности соединения — ведь строка какое-то.доменное.имя (которую он «видит» внутри сертификата) абсолютно не совпадает со строкой какой-то.ip-адрес (которую вы ввели в адресной строке клиента).

по поводу того, как же проверить сертификат (средствами http-клиента), если доменное имя пока не резолвится в нужный ip-адрес, посмотрите, например, этот ответ

среда, 20 февраля 2019 г.

Настроить ssl на nginx

Здравствуйте!
Есть некий сервер, на котором nginx слушает один адрес (допустим, 1.1.1.1). Адрес резолвится в большую кучу dns-имён, при чём, самых разных. Допустим, у меня для каждого имени есть свой SSL-сертификат. Как мне настроить nginx, чтоб они для каждого имени ассоциировал свой сертификат?


Ответ

Насколько я понимаю, у вас сервер имеет ip 1.1.1.1, на нем nginx и много dns указывают в A-записи на 1.1.1.1
Тогда так
server { listen 80; server_name site1.com www.site1.com; rewrite ^(.*) https://$host$1 permanent; } server { listen 443; ssl on; ssl_certificate /etc/nginx/ssl/site1.pem; ssl_certificate_key /etc/nginx/ssl/site1.key;
server_name site1.com www.site1.com; root /var/www/site1;
...
}
server { listen 80; server_name site2.com www.site2.com; rewrite ^(.*) https://$host$1 permanent; } server { listen 443; ssl on; ssl_certificate /etc/nginx/ssl/site2.pem; ssl_certificate_key /etc/nginx/ssl/site2.key;
server_name site2.com www.site2.com; root /var/www/site2;
...
}
Для каждого сайта сначала слушаем порт 80, делаем rewrite с http на https, потом слушаем 443.
Это выдержка из рабочего конфига nginx.

понедельник, 18 февраля 2019 г.

Почему браузер считает валидным сертификат от другого домена?

Сейчас только обратил внимание, что на сайте ru.stackoverflow.com установлен сертификат *.stackexchange.com -- и вообще-то браузеры должны предупреждать при заходе на сайт о невалидном сертификате.

Тем не менее -- в строке браузера стоит зелёный замок, соединение защищено. Почему так происходит?
Насколько я понимаю -- должно выдаваться сообщение "SSL_ERROR_BAD_CERT_DOMAIN", типа такого:


Ответ

А вы загляните в раздел X509v3 Subject Alternative Name, в нем как раз перечисляются прочие домены, для которых данный сертификат будет действителен:
DNS:.stackexchange.com, DNS:stackoverflow.com, DNS:.stackoverflow.com, DNS:stackauth.com, DNS:sstatic.net, DNS:.sstatic.net, DNS:serverfault.com, DNS:.serverfault.com, DNS:superuser.com, DNS:.superuser.com, DNS:stackapps.com, DNS:openid.stackauth.com, DNS:stackexchange.com, DNS:.meta.stackexchange.com, DNS:meta.stackexchange.com, DNS:mathoverflow.net, DNS:.mathoverflow.net, DNS:askubuntu.com, DNS:.askubuntu.com, DNS:stacksnippets.net, DNS:.blogoverflow.com, DNS:blogoverflow.com, DNS:.meta.stackoverflow.com, DNS:*.stackoverflow.email, DNS:stackoverflow.email