• Как обезопасить загрузку изображений на сайт?

    Vamp
    @Vamp
    Суть уязвимости в том, что в метаданные картинки вставляется произвольный php код. Далее, используя уязвимости сайта, злоумышленник заставляет сервер исполнить эту картинку как php скрипт.

    Чтобы избавиться от внедрённых таким образом шеллов, применяют ресайз, в ходе которого все метаданные теряются. Дополнительным бонусом идёт проверка валидности - imagecreatefromstring() и прочие аналогичные функции вернут ошибку, если пользователь залил битый/неподдерживаемый формат или вообще не картинку.

    В принципе - это годный способ, если вам не нужен оригинал загруженного изображения. Используйте его без опасений.

    Если оригинал всё же нужен, то следует удалить метаданные во время загрузки. Здесь уже будет посложнее, так как у каждого формата свои особенности в этом плане. Например, у jpeg это секции COM и APP1 (EXIF). У png - tEXt, iTXt и zTXt. У других форматов ещё какие-то свои особенности. То есть нужно разбираться в форматах изображений и использовать библиотеки, позволяющие работать с форматом на таком низком уровне. Причём надо удалять все метаданные, не относящиеся непосредственно к изображению, так как php код могут засунуть и в нестандартный чанк - браузер его проигнорирует и покажет картинку корректно, но php код там всё-таки присутствовать будет.

    Можно ещё попробовать сделать поиск подстроки <? в сыром контенте файла. Если подстрока найдена, то, возможно, там есть какой-то php код. Способ так себе и не рекомендуется к применению - будет много ложноположительных срабатываний.

    И ещё никогда не сохраняйте изображение в файловой системе под тем именем, с которым пользователь его загрузил. Генерируйте свои имена файлам. Если пользовательское имя файла нужно - сохраните его отдельно в базе.
    Ответ написан
    Комментировать
  • Каким сайтам нужен APCu?

    Vamp
    @Vamp
    В статье рассматривается производительность какой-то абстрактной "обычной CMS" на дешманском VPS хостинге и влияние трех разных видов кеша на общую производительность сайта.

    В разделе "SERVER CACHE TYPES EXPLAINED", в принципе, довольно точно и доходчиво расписано про рассматриваемые типы кеширования.

    OpCache кеширует результат парсинга php скриптов интерпретатором. Возможно вы не знали, но php скрипты не исполняются интерпретатором напрямую - они сначала проходят через этап парсинга исходного скрипта и его преобразования в так называемые опкоды, которые уже исполняются php интерпретатором. Полученные на этапе прасинга опкоды можно закешировать, так как они не меняются от вызова к вызову (разумеется, если сам скрипт не меняется). Эта операция одинаковая для всех скриптов, поэтому OpCache должен быть включен всегда и везде.

    APCu позволяет закешировать произвольную информацию. Например, результат SQL запроса, чтобы в следующий раз не делать запрос к базе и достать результат сразу из кеша. Необходимость APCu для сайта очень сильно зависит от самого сайта. Обычно об этом написано в документации к движку, на котором написан сайт. Так же возможна ситуация, когда сайт затачивался под другой кеширующий модуль, например, memcache, xcache или даже кеширует свои данные в простые файлы - в этом случае наличие/отсутствие APCu ни на что влиять не будет.

    There is one peculiarity regarding APCu caching, when it is used alone without OpCache enabled. APCu will internally reduce number of MySQL queries between PHP and MySQL, however, to really shine and show it’s full potential, OpCache must be enabled.

    Вот этот замечательный абзац вообще полный бред. APCu не сможет магическим образом уменьшить количество запросов к mysql. Об этом должен позаботиться программист явно - положить результат запроса в кеш и проверить в кеше его наличие перед отправкой запроса. И APCu не станет сиять, если включить OpCache. Эти два модуля никак друг на друга не влияют. Вообще. Совсем.

    Static HTML - кеширование всей страницы целиком. То есть весь сгенерированный HTML код страницы будет сохранён где-то. Может быть даже в APCu, хотя из статьи не очень ясно где именно сохраняется результат. Скорее всего в файловой системе. Последующие запросы к этой странице будут обслужены полностью из этого кеша. Непонятно зачем это было выделено в отдельный тип кеширования.

    На таблицу результатов можно не смотреть. Эти цифры не имеют никакого смысла, если не представлен сайт, который был протестирован, так как влияние APCu и static HTML cache очень сильно от этого зависит. Результаты могут быть диаметрально противоположны для тех же самых условий, но для другого сайта.

    В общем и целом, статья по вашей ссылке не рекомендуется к прочтению.

    Отвечая на ваш вопрос - ставить APCu нужно только для сайтов, которые явно его поддерживают. OpCache нужно ставить всегда.
    Ответ написан
    Комментировать
  • Какой подход для валидатора правильней?

    Vamp
    @Vamp
    Архитектурно правильнее возвращать как в примере с Yii2. Использование исключений для управления потоком выполнения программы считается серьёзным антипаттерном.

    Например:
    1. Исключения в данном случае - просто более хитрая замена оператору GOTO. Надеюсь, не нужно объяснять почему GOTO тоже считается антипаттерном?
    2. Программы, написанные в таком стиле, становится сложно читать и понимать.
    3. Меньшая эффективность в рантайме, так как большинство современных компиляторов не оптимизированы для случаев использования исключений в качестве управляющей логики.

    Более подробно по ссылке.
    Ответ написан
    5 комментариев
  • Как реализовать "защиту" авторизации по номеру телефона?

    Vamp
    @Vamp
    1. Проверьте синтаксическую корректность номера телефона. Все мобильные номера в РФ начинаются на +79 и имеют длину ровно 11 цифр. Проверку можно даже добавить в веб форму на уровне js. Это нельзя назвать защитой от хулиганов, но она отсеет реальные ошибки и опечатки, облегчив жизнь обычным пользователям.

    2. Пробейте номер по базе россвязи (файл DEF-9xx). Так вы определите номера, на которые 100% не будет доставки. В отличии от проверки синтаксиса, не выдавайте пользователю ответ о некорректном номере. На все номера отвечайте "Одноразовый код отправлен, введите его сюда", но на невалидные номера не отправляйте сообщение.

    3. Добавьте ограничение на количество отправляемых форм в минуту с одного IP и количество отправляемых сообщений на один и тот же номер (независимо от IP).

    4. Оцените сколько может быть отправок форм в день и поставьте общий лимит на все отправки смс за день. Это единственный реальный способ контролировать атаку на сливание бюджета. Да, реальные пользователи пострадают при достижении лимита, но вы не должны доводить до него - настройте мониторинг количества отправляемых смс и алертинг при достижении порога в 90% от лимита, чтобы у вас было время среагировать на атаку и отбить её до полного исчерпания лимита. Либо если это всплеск реальных пользователей (например, неожиданно удачная реакция на рекламу), то у вас будет время скорректировать лимит. Можно рассчитывать лимит как 2 * среднее количество отправок смс за последние Х дней, чтобы не приходилось править его вручную по мере естественного роста посещаемости. Формулу и процент для алертинга, разумеется, подберёте под свои требования. Но можете взять и мои за основу.

    Отдельно хочу рассказать про так называемые прямые мобильные номера. Они выглядят как городские (например, +7495), но в реальности являются мобильными и могут принимать смски. Проверка в пункте 1 не пропускает такие номера и нет никакого способа проверить без отправки смс является ли отдельно взятый городской номер прямым мобильным. Прямых номеров мало по сравнению с настоящими мобильными или настоящими городскими. К тому же у каждого прямого номера есть мобильный аналог, начинающийся на +79, которым пользователь может воспользоваться для регистрации. Поэтому предлагаю просто забить на прямые номера, а в случае жалоб на невозможность регистрации с прямым номером, рассказывать про существование мобильного аналога, который может быть прописан где-то в договоре с оператором на оказание услуг связи или узнать в техподдержке оператора и с которым можно спокойно зарегистрироваться.

    Обязательное требование email'а не усилит схему защиты, так как не проблема наштамповать реальных адресов со скриптом, автоматически прокликивающим подтверждающие ссылки во входящих письмах.

    Альтернативным вариантом является аренда входящего номера. В этом случае не вы отправляете сообщения пользователям, а они вам. Обычно за входящий номер берут фиксированную плату в месяц независимо от количества смс, так что не придётся в принципе волноваться за бюджет. Но тогда у вас будут в пролёте пользователи с отключенной услугой отправки смс. А таких немало, могу сказать. Благодаря интернет-мессенджерам.
    Ответ написан
    2 комментария
  • Как получить доступ к объекту js который выполняется в iframe?

    Vamp
    @Vamp
    document.getElementById('frameId').contentWindow.yourObject

    В данном примере получается доступ к объекту yourObject внутри iframe с id=frameId.

    Но это сработает только если сама страница и iframe в ней были загружены с одного домена.

    В остальных случаях доступ будет запрещен из-за same origin policy.
    Ответ написан
    1 комментарий
  • Что означает синтаксис dockerfile (php-fpm)?

    Vamp
    @Vamp
    что такое dev суфикс (freetype и freetype-dev) и как понять какую версию ставить (я ставил методом тыка, когда получал ошибки и гуглил)

    Dev суффикс означает, что в данном пакете присутствуют файлы, необходимые для компиляции кода, использующего устанавливаемую библиотеку. Устанавливать нужно обе версии. Обычная версия "freetype" содержит саму библиотеку в so файле, которую gd будет подключать в рантайме. Dev версия "freetype-dev" нужна для сборки самого gd, так как модуль собирается из исходников.

    почему, например, для mycrypt мне сперва нужно загрузить именно libmcrypt-dev, потом через pecl скачать mcrypt, а потом через алиас docker-php-ext-enable включить (экспериментировал и не работает с другими сценариями), а если смотреть на opcache, тот тут сразу docker-php-ext-install и все, а xdebug еще один сценарий: pecl -> docker-php-ext-enable - почему все по разному, как это понять?

    Для разных модулей требуются разные сторонние библиотеки. Для gd это freetype (для работы со шрифтами), libpng (для поддержки формата png), libjpeg-turbo (для поддержки jpeg). У opcache таких зависимостей нет, поэтому ничего дополнительно устанавливать не требуется.

    в чем отличие этих сценариев установки расширений (что делает каждая команда, простыми словами)?

    У php есть модули, которые поставляются с самим php. Например: zip, opcache, pdo_mysql, intl. Такие модули устанавливаются специально предусмотренным для этого скриптом docker-php-ext-install. Этот скрипт распаковывает исходники php, собирает запрошенные вами модули, копирует их в /usr/local/lib/php/extensions/no-debug-non-zts-20190902 (в других образах php путь может отличаться), прописывает загрузку модуля в ini и удаляет распакованные ранее исходники. То есть под капотом скрипт docker-php-ext-install вызывает скрипты docker-php-source, docker-php-ext-configure, docker-php-ext-enable.

    А есть модули, которые хостятся отдельно на сайте pecl.php.net. Это официальный репозиторий, где хостятся всякие разные сторонние модули типа mcrypt, imagick, xdebug. Для их установки нужно использовать утилиту pecl. Так как pecl автоматически не включает модули в ini, из-за этого необходимо самому включать их при помощи скрипта docker-php-ext-enable.

    нагуглил что
    docker-php-source - создает /usr/src/php

    Ещё распаковывает туда исходники самого php и поставляемых с ним модулей.

    docker-php-ext-install - скачивает (ОТКУДА?)

    Из архива /usr/src/php.tar.xz

    docker-php-ext-configure- конфигурирует перед установкой (что это значит?)

    Этот скрипт настраивает настройки, с которыми будет скомпилирован модуль. Например, тот же gd можно собрать без поддержки jpeg если сконфигурировать без опции --with-jpeg. Нужно ли запускать docker-php-ext-configure так же зависит от того, что написано в документации. Очень мало модулей требует предварительной конфигурации перед установкой. Мне на ум приходит только gd.

    В целом, официальная документация php вам поможет понять каким способом нужно устанавливать модули. Смотрим раздел requirements. Если написано "This extension is bundled with PHP", значит нужно устанавливать при помощи скрипта docker-php-ext-install. Если написано что-то вроде "This PECL extension is not bundled with PHP", значит нужно устанавливать через pecl.

    Независимо от способа установки, нужно всегда устанавливать библиотеки, от которых зависят конкретные нужные вам модули. Например, в том же imagick написано "ImageMagick >= 6.2.4 is required". Это значит, что нужно установить библиотеку imagemagick. В вашем базовом образе на основе alpine 3.16 в репозиториях ОС присутствует версия 7.1.0, которая подходит под условие >= 6.2.4:

    /var/www/html # apk info imagemagick
    imagemagick-7.1.0.35-r0 description:
    Collection of tools and libraries for many image formats
    
    imagemagick-7.1.0.35-r0 webpage:
    https://imagemagick.org/
    
    imagemagick-7.1.0.35-r0 installed size:
    4664 KiB


    Для intl нужна "ICU library, version 4.0.0 or newer". Такая библиотека тоже присутствует в репозиториях альпины:

    /var/www/html # apk info icu
    icu-71.1-r2 description:
    International Components for Unicode library
    
    icu-71.1-r2 webpage:
    https://icu.unicode.org/
    
    icu-71.1-r2 installed size:
    796 KiB


    Dev версии библиотек нужны только в момент установки модулей. Дальше их желательно удалить, чтобы уменьшить размер вашего образа.
    Ответ написан
    6 комментариев
  • Каковы шансы сгенерировать одинаковые onion домены?

    Vamp
    @Vamp
    И по какому принципу они вообще генерируются(v3)?

    Генерируется ключевая пара размером 256 бит по алгоритму ed25519. Публичный ключ затем кодируется в base32 вместе с некоторыми служебными данными - номером версии (3) и контрольной суммой. Получившаяся строка и является доменом в зоне onion.

    Если делать полный перебор (а других вариантов я не вижу), то нужно сгенерировать до 2256 ключевых пар. Если взять миллиард компьютеров, которые будут одновременно и без пересечений друг с другом генерировать ключевую пару каждую наносекунду, то все пары можно перебрать примерно за 36*1041 млрд лет, что кажется мне достаточно малым шансом, учитывая, что возраст вселенной всего чуть менее 14 млрд лет.

    Надо отметить, что не все варианты из 256-битового пространства удовлетворяют ed25519. Но даже если отбросить 99% вариантов как невалидные и не тратить время на их генерацию, то перебор оставшихся 1% все равно будет невообразимо дольше возраста вселенной.
    Ответ написан
    Комментировать
  • Как соединить репозиторий GitHub и редактор кода Atom?

    @IvanKalinin
    Например для этого графика можно использовать этот плагин
    Для других вещей этот

    А вообще по поиску "git" существует множество плагинов.

    Уточните так же что именно Вы имеете ввиду под "соединить".

    Есть еще удобная утилита для работы с git SourceTree
    Ответ написан
    Комментировать
  • Зачем нужны события в yii2?

    @LAV45
    Эта и многие другие темы по yii2 на пальцах, и на русском языке ))
    https://www.youtube.com/user/ElisDN/videos
    Ответ написан
    Комментировать
  • Как в Yii2 basic убрать web/ из url при помощи .htaccess и правил urlManager'а?

    IvanCher
    @IvanCher
    Мысли шире
    Если коротко, то вам нужно WebRoot указать не корневую папку с проектом (***/project), а папку web(***/project/web).
    Ответ написан
    Комментировать
  • Лучшие практики организации больших моделей в Yii2?

    SamDark
    @SamDark
    Yii2 core team
    1. Нет. Зачем?
    2. Хороши тем, что не надо экземпляра. Плохи, скорее всего, потому как по-хорошему к модели они не совсем относятся.
    3. Если задача сложная, не пытайтесь всё запихать в модели AR, создавайте свой доменный слой. То есть, надо вам посчитать отчёты за квартал, считайте отдельным классом. Не моделью.
    Ответ написан
    2 комментария