← Все новости

Три пакета вместо двухсот пяти: честный разбор Django

У Django лучший процесс безопасности из всего, что мы разбирали: оплачиваемая команда, обязательства по срокам и одновременные заплатки во всех ветках. Уязвимости находят регулярно, но случаев массовой эксплуатации ни один каталог за ним не числит. Подвох есть, и он в трёх других местах — один из которых специфически российский.

Три пакета в чистой установке Django против 205 у Laravel и 194 у Astro

Это шестой разбор в серии: до него были WordPress, Битрикс, Tilda, Astro, OpenCart и Laravel. Предупредим сразу: хвалить здесь придётся много. По качеству работы с безопасностью Django — лучшее, что мы видели за всю серию, и нечестно было бы это замолчать.

Но подвох есть, и он в неожиданном месте.

Три пакета

Мы поставили чистый Django сегодня, 9 октября 2026 года. Результат:

Что считаем Сколько
Пакетов после установки Django 3
Пакетов в типовом боевом наборе 9
Файлов создаёт команда создания проекта 6 (28 КБ)

Три пакета — это сам Django, библиотека asgiref и разборщик SQL sqlparse. Всё. Типовой боевой набор — это Django плюс сервер приложений, драйвер базы, работа с картинками, раздача статики и чтение настроек из файла. Девять пакетов на полноценный сайт.

Для сравнения, нашими же замерами: чистый Laravel — 205 пакетов, чистый Astro — 194. Разница не в полтора раза, а в двадцать с лишним.

Причина в философии. Django называют «фреймворком с батарейками в комплекте»: аутентификация, работа с базой, админка, формы, защита от подделки запросов, миграции — всё это части самого Django, а не отдельные пакеты от отдельных авторов. Вы получаете много кода, но у него один владелец и один процесс выпуска версий.

Процесс, которого нет больше нигде

Вот то, за что мы готовы Django хвалить без оговорок. В разборе OpenCart мы писали, что в проекте нет даже файла с правилами сообщения об уязвимостях, а исследователи регулярно не получают ответа. Здесь всё устроено противоположным образом.

  • Есть адрес, куда сообщать, и опубликованный ключ для шифрования письма. Обсуждать уязвимости в публичном баг-трекере прямо запрещено.
  • Есть обязательства по срокам, записанные в документе: подтверждение получения в течение трёх рабочих дней, решение в рамках отраслевого стандарта в 90 дней.
  • Есть команда безопасности — сегодня в ней тринадцать человек, все названы по именам.
  • Есть деньги. Фонд Django содержит трёх оплачиваемых разработчиков, и все трое входят в команду безопасности. Бюджет фонда публичный: в 2026 году цель сбора поднята с 300 до 500 тысяч долларов, и программа этих ставок — самая крупная статья расходов.
  • Есть предупреждение заранее. Примерно за неделю до публикации рассылаются два уведомления: публичное — о дате, времени и серьёзности предстоящего выпуска, и закрытое — с полным описанием проблемы и готовыми заплатками, для поставщиков операционных систем. Сервисы, торгующие сканированием уязвимостей, в закрытый список не берут принципиально.
  • Заплатки выходят одновременно для всех поддерживаемых веток. Это не декларация — это видно по датам. Выпуск от 6 октября 2026 года закрыл четыре уязвимости сразу в версиях 6.1.2, 6.0.9 и 5.2.18, и все три вышли в один день.
  • Есть публичный архив всех уязвимостей с 2007 года, где по каждой указаны дата, класс проблемы, исправленные версии и ссылка на конкретную правку в каждой ветке.

И ещё одна деталь, которую мы считаем признаком зрелости. В том же выпуске от 6 октября прямо написано, что одна из уязвимостей «была упущена при исправлении» предыдущей. Проект публично признаёт, что предыдущая заплатка оказалась неполной. Так ведут себя те, кому важнее починить, чем выглядеть.

Сроки поддержки: три года вместо двух

У Django есть то, чего нет у Laravel, — долгоживущие версии. Раз в два года выходит версия LTS, которая получает исправления безопасности три года. Обычные версии выходят примерно раз в восемь месяцев.

Версия Исправления безопасности до
Django 6.1 декабрь 2027
Django 6.0 апрель 2027
Django 5.2 LTS апрель 2028
Django 6.2 LTS (выйдет в апреле 2027) апрель 2030

Сайт, сделанный на Django 5.2 LTS весной 2025 года, может получать исправления безопасности, не трогая код приложения, до апреля 2028-го. Тот же бизнес на Laravel 12 обязан пройти переход на новую основную версию к февралю 2027-го. И Django объявил, что с версии 2028 года трёхлетний срок получит каждый выпуск, а не только LTS.

Отдельно отметим правило, которого мы больше нигде не встречали: требуемая версия Python выводится из графика поддержки самого Python. Формулировка проекта означает простую вещь — версия Django LTS не оставит вас на Python, который уже перестали чинить. Запомните это, через два раздела оно сыграет.

Как читать 165 уязвимостей

За девятнадцать лет у Django накопилось около 165 записей об уязвимостях. Делить это на девятнадцать и говорить «примерно девять в год» было бы лукавством: в одном только 2026 году их 32. Темп вырос, и это надо показать честно — вот все выпуски безопасности текущего года:

Дата выпуска Закрыто
3 февраля6
3 марта2
7 апреля5
5 мая3
3 июня5
7 июля3
4 августа4
6 октября4

Выпуск почти каждый месяц, по три-шесть уязвимостей за раз. Выглядит тревожно — пока не посмотришь, что именно закрывают. Возьмём июньский выпуск целиком: пять записей, все пять сам Django оценил низшим уровнем опасности. Коллизия соли у подписанных кук; возможность отправить письмо незашифрованным, если рукопожатие TLS не удалось, а ошибки подавлены; и три штуки про кэширование — заголовок Cache-Control с заглавной буквы не распознавался, ответ на запрос с заголовком авторизации мог попасть в кэш, пробел в заголовке Vary ломал проверку. Это вычистка углов, а не дыры, через которые уносят базу.

Так что правильное прочтение этих 32 записей — не «Django стал хуже», а «Django стали пристальнее смотреть, и всё найденное публикуют». Обратная ситуация настораживает сильнее:

Проект с нулём уязвимостей не безопаснее. Он просто не исследован.

Для сравнения: у OpenCart, который мы разбирали неделю назад, за всю историю 65 записей, при этом в проекте нет даже адреса для сообщений об уязвимостях, а исследователи жалуются, что им не отвечают. Меньшее число там означает не меньше проблем, а меньше внимания.

Гораздо важнее количества — состав. Мы разобрали записи за последние пять лет по классам:

Класс проблемы Доля
Отказ в обслуживании (сайт тормозит или падает) 46%
Внедрение SQL 16%
Утечка данных через кэш 8%
Выход за пределы каталога, доступ в админке, перечисление пользователей, прочее 30%

Почти половина — это не взлом, а «кто-то прислал хитрую строку, и сервер потратил на неё слишком много времени». Сам Django относит такие проблемы к низкому уровню опасности, и обычно они отсекаются обратным прокси раньше, чем доходят до приложения. Случаи с реальной утечкой данных — около трети от общего числа: по пятилетнему среднему это пять-шесть в год, в более плотном 2026-м — около десятка. И каждый из них закрыт в день публикации сразу во всех поддерживаемых ветках.

Про внедрение SQL стоит сказать отдельно, потому что строка «16%» выглядит пугающе. Почти все эти случаи требуют необычного способа вызова — когда в запрос подставляются имена полей, пришедшие от пользователя. При обычной работе с базой через Django такое не воспроизводится.

Теперь о том, доходит ли дело до реальных атак. Здесь нужно различать два разных вида списков, которые легко перепутать.

Первый вид — базы уязвимостей. Это американская NVD и российский БДУ ФСТЭК. Они регистрируют всё найденное, независимо от того, пользовался этим кто-нибудь или нет. Записи по Django в БДУ есть, и их регулярно пополняют. Например, запись BDU:2026-03467 от марта 2026 года — высокий уровень опасности, оценка 7,5. По сути это отказ в обслуживании: обрезка HTML на хитрой строке с кучей незакрытых тегов заставляет сервер считать слишком долго. Производитель признал и исправил, а в поле «Наличие эксплойта» у неё стоит «Данные уточняются» — то есть подтверждённого эксплойта регулятор не фиксирует.

Для российского читателя в записях БДУ есть деталь поважнее: среди затронутого ПО там перечислены Astra Linux Special Edition и РЕД ОС. Django входит в состав сертифицированных отечественных дистрибутивов, и уязвимости в нём автоматически становятся уязвимостями этих систем. Если вы работаете с аттестованной инфраструктурой, следить за записями БДУ придётся независимо от того, что показывают зарубежные каталоги.

Второй вид — каталоги подтверждённой эксплуатации. Самый известный — KEV американского агентства CISA: туда попадают только те уязвимости, по которым есть свидетельства реальных атак. В версии каталога от 8 октября 2026 года 1 739 записей: семь по WordPress, пять по Drupal, три по Laravel, а также Exchange, Fortinet и прочее. Записей по Django нет ни одной. Мы проверили весь каталог выгрузкой.

И сразу оговорка, без которой этот факт можно неверно прочитать. Отсутствие в каталоге — слабое доказательство. Оно означает, что массовой эксплуатации никто публично не задокументировал, а не что её не бывает и не может быть. KEV — список американского регулятора, составленный для своих ведомств, и он заведомо неполон. Правильный вывод скромнее: уязвимости у Django находят регулярно, но ни один каталог подтверждённых атак — ни американский, ни российский — на сегодня не числит за Django ни одного случая массовой эксплуатации. Для системы, которая работает девятнадцать лет, это хороший результат, но это не гарантия.

Так где же подвох

В трёх местах, и ни одно из них не находится внутри Django.

1. Установка пакета исполняет чужой код

Это главный структурный недостаток Python, и он серьёзнее, чем кажется. Когда вы ставите пакет из исходников, менеджер пакетов запускает сценарий установки от имени вашего пользователя — до того, как кто-либо посмотрел на содержимое. Хуже того: это происходит даже при команде «просто скачать, не устанавливая», потому что прочитать описание пакета иначе нельзя.

Сравните с Composer в мире PHP, где исполнять код при установке могут только явно перечисленные в списке разрешённых плагины, а по умолчанию список пуст. Это тот редкий случай, когда PHP устроен безопаснее.

Частично спасают готовые сборки: при их установке код не исполняется. Но он исполнится при первом обращении к пакету — то есть при запуске сайта. Именно так работал вредоносный пакет django-auth-middleware-plus, найденный в июне 2026 года: при загрузке он поднимал фоновый поток и отправлял на сторону имя машины и имя пользователя. Номер версии у него был 99.99.99 — чтобы сборка выбрала именно его.

Насколько это опасно на практике, показал апрель 2026 года. Злоумышленники получили ключ публикации — через зависимость сканера безопасности, по иронии — и выпустили вредоносные версии двух популярных настоящих пакетов. Не подделок с похожими именами, а именно настоящих. Площадка отреагировала быстро: от загрузки до блокировки прошло два с половиной часа. За это время вредоносные версии скачали больше 119 тысяч раз. По оценке площадки, у 40–50% пострадавших версии не были зафиксированы — то есть сборка просто взяла самое свежее.

Теперь цифры по площадкам, и к ним нужна оговорка. Записей о вредоносных пакетах в открытой базе OSV: у npm — 222 385, у PyPI — 11 814, у Packagist — одна. Но это кривые обнаружения, а не кривые происходящего. У npm 195 929 записей внесены одним-единственным сканером. У PyPI больше 6 тысяч записей 2023 года приходятся на один февраль — это раскрытие одной кампании. А единица у Packagist означает, что там до марта 2026 года просто никто автоматически не искал.

Пакеты с именами из мира Django среди вредоносных есть, хотя и немного — мы нашли десяток. Самый показательный: django-storage вместо настоящего django-storages. Разница в одну букву.

Справедливости ради, площадка Python делает многое и делает открыто: двухфакторная аутентификация обязательна для всех с 1 января 2024 года, есть карантин для подозрительных пакетов, с июля 2026 года запрещено дописывать файлы в релизы старше двух недель, отчёты об инцидентах публикуются с точностью до минут. Это заметно больше, чем делают остальные.

2. Админка по известному адресу без защиты от перебора

Django приносит с собой готовую админку, и по умолчанию она находится по адресу /admin/. Это удобно и это же — самая заметная мишень на сайте.

Главное здесь — прямая цитата из документации самого Django:

«Django не ограничивает частоту запросов на аутентификацию пользователей».

То есть из коробки форма входа принимает неограниченное число попыток подбора пароля. Нет блокировки, нет задержки, нет капчи. Позиция проекта в том, что это задача обратного прокси или отдельного пакета, и позиция защитимая — но владельцу сайта от этого не легче, и в документации по админке об этом не сказано ни слова.

Честно о том, чего мы не знаем: сколько сайтов на Django держат админку открытой, никто не измерял. Мы искали и не нашли ни одного публичного замера. Косвенный признак есть — существует целая россыпь пакетов, которые подсовывают сканерам фальшивую админку-ловушку. Раз их пишут, значит сканеры видят. Но это не измерение, и выдавать его за измерение мы не будем.

3. Три ошибки развёртывания — и команда, которая их ловит

Классических ошибок три, и они те же, что у Laravel: включённый режим отладки, слабый или утёкший секретный ключ и неверно заданный список разрешённых доменов.

Режим отладки выдаёт при ошибке страницу с кусками исходного кода, значениями переменных и блоком настроек, где может оказаться и пароль от базы. Документация формулирует без обиняков: «Вы никогда не должны включать отладку в рабочем режиме». Единственный известный нам замер масштаба — 2018 год, когда исследователь нашёл 28 165 сайтов на Django с включённой отладкой. Цифре восемь с половиной лет, более свежей мы не нашли, и приводим её только как указание на порядок. Автор того исследования, кстати, сказал справедливую вещь: «Это не вина Django».

А вот то, чего нет ни у одной другой системы в нашей серии. В Django встроена команда проверки готовности к бою, и она ловит все три ошибки:

  • предупреждение W018 — включён режим отладки;
  • предупреждение W009 — секретный ключ короче 50 символов, содержит меньше 5 разных символов или начинается с django-insecure-, то есть это тот самый ключ-заглушка, который генерируется при создании проекта;
  • предупреждение W020 — не заполнен список разрешённых доменов.

Плюс полтора десятка проверок заголовков безопасности, флагов куки и переадресации на HTTPS. Одна команда, встроенная, бесплатная, выполняется за секунду. Если вы заказываете сайт на Django — попросите показать вам её вывод перед запуском. Это самый дешёвый пункт приёмки из всех, что мы можем посоветовать.

Российская специфика: тикают сразу трое часов

Здесь мы нашли то, чего не ожидали, и это самая практическая часть разбора.

Распространено мнение, что на российском виртуальном хостинге Django не запустить. Это неверно: Timeweb, REG.RU и SpaceWeb предлагают Django на обычном хостинге и документируют установку. Проблема в другом.

Самый свежий Python на виртуальном хостинге Timeweb — 3.10. А Django 6.0 и 6.1 требуют Python не ниже 3.12. Мы проверили: менеджер пакетов на версии 3.10 отказывается ставить Django 6 вообще, предлагая максимум 5.2.

Дальше складывается цепочка из трёх сроков, и все три уже идут:

  • Python 3.10 перестал поддерживаться 1 октября 2026 года — восемь дней назад на момент написания. Исправлений безопасности для него больше не выходит.
  • Django 5.2 LTS, в который вы упёрлись из-за этого Python, получает исправления безопасности до апреля 2028 года.
  • Ubuntu 22.04, на которой обычно стоит тот самый Python 3.10, теряет обычную поддержку в июне 2027 года.

К середине 2028 года все три слоя оказываются без поддержки одновременно. И выход из этого — не обновление, а переезд: другая операционная система, другой Python, другая версия Django, заново разрешённые зависимости. На виртуальном хостинге это вообще невозможно — там меняют не версию Python, а хостинг.

Вспомните правило из третьего раздела: Django обещает, что версия LTS не оставит вас на мёртвом Python. Обещание проект держит — но только если вы можете обновить Python. На российском виртуальном хостинге вы не можете.

Поэтому практический ответ для Django — виртуальный сервер, а не хостинг. Это от 950 ₽ в месяц у Selectel или около 180–400 ₽ за недорогой VDS, но вместе с ним вы получаете в собственность nginx, автозапуск, обновление сертификатов, резервные копии и обновления системы. Для сравнения: PHP-сайт на том же виртуальном хостинге работает за 119–450 ₽ в месяц и не требует ничего из перечисленного.

И честно о том, как выглядит установка на виртуальном хостинге, если всё-таки идти этим путём. Инструкция провайдера просит создать окружение вручную, перенести файл запуска, написать .htaccess с включением исполнения сценариев, вручную отредактировать файл запуска, чтобы он подхватил окружение, и только потом выполнить миграции и сборку статики. Это не то, что делает владелец сайта.

Сколько стоит и кем обслуживать

Неожиданный результат: российские студии берут за Django ровно столько же, сколько за PHP. Мы нашли одну и ту же студию с двумя прайсами — на поддержку Laravel и на поддержку Django. Цифры совпадают до рубля: 27 000 ₽ в месяц за 10 часов, 40 000 ₽ за 16 часов, разовые работы 2 300–3 500 ₽ в час.

То есть ставка не зависит от языка. Разница не в ставке, а в количестве часов: развёртывание, окружение и обновления съедают больше.

Разработчики стоят дороже, но не драматически. По самооценкам на Хабр Карьере за первое полугодие 2026 года средний разработчик Python уровня middle — 225 000 ₽ против 196 666 ₽ у PHP, то есть примерно на 14% больше. На senior разница около 11%. По вакансиям цифры ниже у обоих: медиана около 150 000 ₽. Разные способы считать — самооценка сотрудников против объявлений работодателей — дают расхождение почти в два раза, и это стоит держать в голове, когда вам показывают любую из этих цифр.

Но есть вещь важнее денег. Разработчиков Python в России много, и их больше, чем на PHP. Только рынок Python устроен иначе: он повёрнут в сторону продуктовых компаний, бэкенда и анализа данных. Нет привычного слоя недорогих исполнителей, которые чинят корпоративные сайты за пару тысяч рублей. Дефицит не в разработчиках Python, а в разработчиках Python, готовых взять такую работу.

Что будет, если сайт бросить

Мы проверили это, а не просто описали. Результат двойственный.

Хорошая новость: сам Django удивительно живуч. Мы поставили Django 2.2.28 — версию 2019 года, поддержка которой кончилась в апреле 2022-го, — на современный Python, и встроенная проверка отчиталась: «проблем не обнаружено». Работающий сайт сам по себе не ломается. И площадка пакетов не удаляет старые версии: любой выпуск Django доступен и сегодня.

Плохая новость: он ломается при переустановке. Мы попробовали поставить драйвер базы данных версии 2020 года — обычный, самый распространённый — и получили ошибку сборки: для старых версий готовых сборок нет, их надо компилировать, а для этого нужны системные библиотеки, которых на современной машине уже другие.

Отсюда настоящий сценарий аварии. Сайт прекрасно работает годами. А потом сервер переносят, или восстанавливают из резервной копии, или просто перезапускают после сбоя — и набор зависимостей, который работал в 2021 году, отказывается ставиться. Предупреждения об этом не будет, а текст ошибки ничего не скажет владельцу бизнеса.

Справедливости ради: у PHP та же болезнь, но в более мягкой форме. Версии PHP тоже кончаются, но на хостинге они переключаются кнопкой в панели, а у сайта без фреймворка переустанавливать просто нечего.

Практический вывод: сайту на Django надо закладывать оплачиваемый переезд раз в три-четыре года. Если вам считают смету без этой строки — смета неполная.

Где проходит граница с нашим подходом

Скажем прямо: Django — хороший выбор, и во многих случаях правильный. Если задача — не сайт-визитка, а приложение с данными, ролями, сложной логикой и внутренней админкой, то Django даёт готовое решение всего этого, написанное людьми, которым за это платят, и проверенное девятнадцатью годами.

Наша разница с Django проходит не по безопасности — там мы с ними не конкуренты — а по трём вещам.

  • Нет цепочки часов. У нас нет версии фреймворка, у которой кончается срок, нет связки «Python тянет Django, Django тянет систему» и нет переезда раз в три года.
  • Работает на обычном хостинге. Не нужен виртуальный сервер, не нужны служба автозапуска, сборка статики и миграции при каждой выкладке.
  • Найти исполнителя проще и дешевле. Код на PHP без фреймворка читает любой разработчик PHP, а их в России много и они недороги. Для сценария «подрядчик пропал» это решающее обстоятельство.

И чем мы за это платим: пишем руками то, что в Django есть из коробки, не получаем бесплатно улучшений новых версий, и за нашим кодом не стоит ни фонда, ни тринадцати человек в команде безопасности, ни девятнадцати лет публичного архива.

Поэтому рекомендация та же, что и в разборе Laravel. Если у вас работает приложение на Django и есть человек, который его ведёт, — не переписывайте. Разумный разговор о замене начинается там, где сайт должен жить годами без обслуживания, где движущихся частей должно быть минимум, или где вы не готовы держать при сайте разработчика на Python постоянно.

Что сделать с существующим сайтом на Django

  1. Попросите показать вывод встроенной проверки развёртывания. Она ловит отладку, слабый ключ и пустой список доменов за одну секунду. Если в выводе есть W018 — отладка включена, и это надо чинить сегодня.
  2. Проверьте, открыта ли админка. Откройте адрес сайта с /admin/ на конце с чужого устройства. Если форма входа открывается всем — ограничьте доступ по адресу IP или поставьте защиту от перебора: своей у Django нет.
  3. Узнайте версию Django и версию Python. Если Python 3.10 или ниже — он уже не поддерживается, и вы заперты на Django 5.2 с горизонтом до апреля 2028 года. Это не срочно, но это надо планировать.
  4. Попросите зафиксировать версии зависимостей. В апрельском инциденте пострадали именно те, у кого версии не были зафиксированы.
  5. Убедитесь, что секретный ключ не лежит в репозитории и не начинается с django-insecure-. Удаление из истории коммитов ключ не меняет — его надо менять.
  6. Проверьте, что у вас есть всё для передачи другому разработчику: репозиторий, список зависимостей с версиями, инструкция по выкладке, доступы к серверу и домену.

Коротко

  • Чистый Django — три пакета, типовой боевой сайт — девять. У Laravel 205, у Astro 194.
  • У Django лучший процесс безопасности из всего, что мы разбирали: оплачиваемая команда, обязательства по срокам, предупреждение поставщиков за неделю, одновременные заплатки во всех ветках, публичный архив с 2007 года.
  • Версии LTS поддерживаются три года против двух у Laravel.
  • Уязвимости находят часто: 32 записи за один 2026 год, выпуск почти каждый месяц. Но смотреть надо на состав — в июньском выпуске все пять записей сам Django оценил низшим уровнем опасности.
  • Уязвимости у Django находят регулярно, и в БДУ ФСТЭК они есть — в том числе как уязвимости Astra Linux и РЕД ОС, куда Django входит. Но ни один каталог подтверждённых атак не числит за Django случаев массовой эксплуатации: в каталоге CISA из 1 739 записей по Django нет ни одной. Это хороший признак, но не гарантия.
  • Подвох не внутри Django. Он в том, что установка пакета Python исполняет чужой код; в админке по известному адресу без защиты от перебора; и в том, что на российском хостинге вы упираетесь в Python 3.10, который уже умер.
  • Сайту на Django нужен постоянный разработчик и оплачиваемый переезд раз в три-четыре года.

Посмотреть со стороны, что ваш сайт рассказывает о себе каждому посетителю, можно нашей бесплатной проверкой. Никаких проб на прочность — только то, что сайт сам сообщает о себе любому, кто его открывает.

А если нужен честный разбор конкретного проекта и ответ на вопрос, стоит ли вообще что-то менять, — напишите на info@g3a.ru. Вполне возможно, что достаточно выключить отладку и закрыть админку, и мы об этом скажем прямо.

Источники

← Все новости