Задача 19: Секурность

    Задача: сделать достаточно защищенный механизм аутентификации на PHP.

    Способ 1.
    В форму передается случайная последовательность, на стороне сервера она запоминается в таблице в связке SESSION_ID && S_KEY. На стороне клиента выполняется преобразование вида
    sha1(sha1(password) + S_KEY). sha1(password) — предпологаемый хэш пароля в базе, S_KEY — переданная последовательность. В результате мы имеем постоянно меняющийся хэш, который безопасно передать на сервер.
    На сервере полученный хэш сравнивают с sha1(password_from_db + S_KEY). Если совпадает, в переменную $_SESSION['user'] заносим подгруженный инстанс класса пользователя.

    Тут все хорошо и правильно, но не совсем секурно.

    Что может сделать злоумышленник?
    1. Украсть кукизы с сессией.
    2. Перехватить трафик и снова украсть сессию.

    Что нам нужно?
    Мы должны быть уверены в том, что сессия жостко привязана к пользвателю на другой стороне.

    IP — не выход, его можно подменить. Да и для людей, сидящих за NAT, IP будет общий.

    Что же делать?
    Использовать удалённый порт. Как правило браузер не меняет порт для сайта, и он долго остается неизменным. NAT тоже не меняет порт, потому что он ему нужен для проброса пакетов.

    Замечание: данный метод применим только к критически важным участкам системы. Для пользователя хватит и Способа 1. Все потому, что никто не гарантирует статичность порта на всю сессию, а это повлечет постоянные ре-логины, что пользователь просто не моймёт.

    Средняя зарплата в IT

    120 000 ₽/мес.
    Средняя зарплата по всем IT-специализациям на основании 9 072 анкет, за 1-ое пол. 2021 года Узнать свою зарплату
    Реклама
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее

    Комментарии 34

      –2
      Давайте угадаю ваш порт… 8080 или 80? :)
        0
        не угадали :)

        <?php echo $_SERVER['REMOTE_PORT']; ?> будет выводить какой системный порт был использован на удалённой машине. Если кто то подменит айпи, наврят ли порт совпадет.

        На сервере же, для каждого клиента открывается отдельный порт. 80й необходим для принятия запроса на конекшен. В процессе установки соединения с клиентом, сервер открывает еще один порт для него.
          +1
          Ну и кто мешает в таком случае перехватить данные о том какой порт, ведь клиент должен узнать свой новый порт, да и вообще говоря затея с портами — гиблая затея. Сразу отсекаются клиенты сидящие за прокси, да и серваку от множества прослушиваемых портов лучше не станет.
            –1
            Да — перехватить можно. И метод не панацея.
            Для людей седящих за прокси — прокси вроде тоже создает на каждый поток отдельный порт?
            Сервер в данном случае ничего прослушивать не будет. Клиентский порт в $_SERVER кладется автоматом.
              0
              На прокси обычно открыто несколько портов и все, остальные данные просто не пройдут.

              «Клиентский порт в $_SERVER кладется автоматом.» — угу но это сервер, а клиент то как порт узнает:)
                0
                Если клиент не за NATом и без проксей, то он знает свой порт ещё до того, как собственно установилось соединение с сервером ;)

                Если же соединение не прямое, то клиент свой порт не знает, так же, как и не знает свой «внешний IP». Точнее, порт и IP он знает, но он не знает, с какого именно порта и IP видит сервер.

                И может узнать только если сервер ему скажет.
                  0
                  Угу мы тут говорим про то что соединение устанаввливается, а потом сервак назначает какой-то другой порт для клиента для последующих транзакций. Я понимаю что порт из своего первого запроса клиент знает:)
                    +1
                    Да никто никакой другой порт не назначает. Сервер всегда использует тот порт, на который соединялся клиент — по умолчанию для http это 80. То есть, во всех пакетах, которые к клиенту (или к прокси) приходят от сервера, стоит порт отправителя 80, и в все пакеты от клиента к серверу направляются на порт 80.

                    Учите матчасть, то есть, tcp, блин.

                    И вообще, такой сложный протокол с назначением другого порта не работал бы (или плохо работал бы) через NAT, при наличии файерволла и т. п. Для таких протоколов приходися сильно извращаться (на уровне анализа пакетов TCP), чтобы заработали. Примеры таких FTP, SANE, Amanda протоколов — например, для FTP для обхода этой проблемы изобрели «пассивный режим» и так далее.
                      –1
                      Блин перечитайте то что написано выше, я то понимаю про то что вы пишите и это правильно, но вы не понимаете про то что пишем мы.
                        0
                        Я тут наверно с неблокирующими сокетами напутал. При их использование принимающий порт остается всегда для приёма, а клиенту алоцируется новый.
              0
              Совершенно неверно. Сервер принимает соединения на 80-й порт, и никаких «других портов» он не открывает. Для примера, ssh:

              tcp 0 0 192.168.1.2:22 192.168.1.34:55692 ESTABLISHED22062/sshd: merlin
              tcp 0 0 192.168.1.2:22 192.168.1.34:37659 ESTABLISHED22176/sshd: merlin
              tcp 0 160 192.168.1.2:22 88.83.201.253:48613 ESTABLISHED3638/sshd: merlin [

              Видно, что на сервере тремя процессами sshd используется порт 22, а различаются они тем, откуда (IP-адрес и порт клиента) приходят и куда уходят пакеты.

              HTTP работает также. На сервере используется один порт — тот, который открыли при создании сокета, и всё, никаких дополнительных портов.
                0
                вот пример с http: процесс apache не связан ни с какими другими портами, кроме 80 и 443:
                lsrv d.c # netstat -alnp | grep apache
                tcp6 0 0 :::80 :::* LISTEN 1020/apache2
                tcp6 0 0 :::443 :::* LISTEN 1020/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47476 ESTABLISHED1020/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47477 ESTABLISHED22542/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47478 ESTABLISHED17684/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47487 ESTABLISHED22510/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47475 ESTABLISHED14516/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47485 ESTABLISHED22527/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47489 ESTABLISHED14520/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47479 ESTABLISHED22486/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47486 ESTABLISHED22060/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47484 ESTABLISHED22622/apache2
                tcp6 0 0 192.168.1.2:80 192.168.1.34:47474 ESTABLISHED22502/apache2
              0
              а что нельзя сделать так, чтобы сервак и клиент обменялись ключами, к примеру по протоколу Диффи-Хеллмана и затем при каждом запросе к серваку, сервак будет просить у клиента зашифровать на этом ключе какое-то случайное число и таким образом проверять подлинность клиента.

              Кстати, аутенТификация
                0
                Можно, но тогда это уже не моя идея :)

                Кстати, спасибо — поправил.
                  +2
                  А вы велосипед что ли хотите изобрести?
                    0
                    Идея появляется только, когда изобретаешь велосипед? ;)
                    Мне пришла в голову идея — я ей поделился с вами, кто её может оценить.
                  +1
                  Это называется «SSL».
                    0
                    не, SSL, это несколько другое — там сертификаты есть, протокол гораздо сложнее.

                    Тут суть просто примерно одна.
                      0
                      Хорошо, это «упрощённый SSL». А протокол там не сложнее, чем вы предложили — такой: обмениваются ключами, проверяют ключи по сертификатам, договариваются об алгоритме симметричного шифрования и выбирают ключ. Причём, это всё происходит прозрачно для приложения на PHP — вообще ни о чём заботиться самому не надо.
                        0
                        Я знаю, как он выглядит, у меня зачет был по нему:) Ну это вы описали, так сказать, его верхний уровень — обмен сообщениями, а вот если вы посмотрите, как вычисляются ключи и параметры, передаваемые в этих сообщениях, то вы увидите, что там все далеко не просто.
                          +1
                          Не знаю, по-моему, сама по себе идея аутентификации со схемой Диффи-Хеллмана перебивает сложностью любые вопросы установления сессионного ключа ssl.

                          Дело даже не в этом. Зачем нужно изобретать велосипед, если есть уже куча работающего софта, который позволяет сделать всё то же самое, не шевельнув ни пальцем? Зачем нужно изобретать «упрощённый SSL», если можно просто воспользоваться полнофункциональным SSL?
                            0
                            За него на хостинге нужно платить отдельно :)
                              0
                              Проекты, которым может потребоваться такая секурность, наверняка способны это оплатить? :)
                                +1
                                Та это еще один пост, сразу в день регистрации, что за народ пошел.
                                  0
                                  Да я видел этот пост в песочнице, заметил. Боюсь обидеть, но не понимаю, за что тут инвайт дали.
                                    0
                                    :) просто видимо мне повезло.
                                    Я уже постарался исправиться и написал другой.
                              0
                              Ну насчет реализации это да — проще воспользоваться готовым решением.
                              Но вот то что Диффи-Хеллман с двумя посылками с вполне очевидными вычислениями проще, чем SSL с 6 посылками и очень неочевидными вычислениями(там вычисляются три KEY_MATERIAL на основании мастер-ключа, который складывается из двух ключей — открытой и закрытой части, зашифрованной на открытой, которая берется из сертификата сервера; потом на основании этих KEY_MATERIAL получаются два ключа клиента), я не согласен.
                    +1
                    Перехватывая пакет, ты автоматически узнаёшь, какой порт используется на стороне клиента. И нет никаких проблем в том, чтобы попросить свой компьютер отправить пакет с такого же порта, просто обычно не просят, дают это на откуп ОС.
                      0
                      Куки нужно привязывать к IP, хуже от этого не будет. Шанс того, что взломают из-под NAT меньше, чем шанс взлома вообще из всего мира.
                        +1
                        Если взломают из-под NAT, можно настучать взломщику непосредственно по голове :)
                        +3
                        люди, вы во ssl слышали?!!
                          –1
                          ну, допустим.
                          А откуда на клиенте узнают «предпологаемый хэш пароля в базе»? Хэширование паролей ведь обычно выполняют с дополнительным ключом ;-)
                            0
                            для пущей безопасности можно пользователю загнать троян и проверять он ли это по другому каналу)
                              0
                              Неее, с портом это как то не надежно! Лучше провести до клиента оптоволокно, поставить аппаратуру и использовать квантовую криптографию.

                              Ну или просто использовать SSL ;)

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое