Веб-безопасность API
Безопасность - раздел, где заученные названия не спасают: собес проверяет, понимаешь ли ты МЕХАНИЗМ каждой дыры и её лечение. Инъекции, XSS, CSRF, хранение паролей, секреты - джентльменский набор, незнание которого на бэкенде это красный флаг.
Типовые формулировки: «как защититься от SQL-инъекции?», «CORS это защита?», «как хранить пароли».
Инъекции и XSS: отделить код от данных
SQL-инъекция рождается из склейки пользовательского ввода в текст запроса - ввод становится частью SQL-кода. Лечит параметризованный запрос или ORM: значения передаются ОТДЕЛЬНО от кода SQL, драйвер их не интерпретирует как команды. Конкатенация ввода в запрос - прямой путь к дыре.
XSS (cross-site scripting) - из непроэкранированного вывода: чужой скрипт попадает на страницу и исполняется в браузере жертвы. Лечит экранирование вывода плюс CSP (Content-Security-Policy), ограничивающий, откуда грузятся скрипты. Общий принцип обеих дыр один: отделяй код от данных.
// Mass assignment сюда же по духу: биндить надо белый список полей, а не сущность целиком, иначе клиент проставит is_admin.
# дыра:
db.execute(f"SELECT * FROM u WHERE name='{name}'")
# безопасно — значение отдельно от SQL:
db.execute("SELECT * FROM u WHERE name=:n", {'n': name})- SQL-инъекция
- подстановка ввода в SQL; лечится параметризацией
- XSS
- внедрение скрипта через непроэкранированный вывод
CSRF, CORS и хранение секретов
CSRF (cross-site request forgery) - чужой сайт шлёт запрос под сессией жертвы (браузер сам приложит куки). Лечат CSRF-токеном и SameSite-cookie; API на bearer-токене менее уязвим, так как токен не отправляется автоматически. А вот CORS (cross-origin resource sharing) это НЕ серверная защита: это механизм браузера, он лишь ослабляет same-origin для разрешённых origin. curl его игнорирует - считать CORS защитой опасное заблуждение.
Пароли хранят необратимым медленным соль-хешем - bcrypt или argon2, не открыто и не быстрым MD5 (быстрый хеш перебирается на GPU). Секреты держат в env или секрет-менеджере, не в git и не в образе; токены и пароли гоняют только по https.
// Ещё гигиена: не логировать секреты и ПДн (персональные данные), не отдавать стектрейс наружу, патчить уязвимые зависимости (CVE - common vulnerabilities and exposures), валидировать URL против SSRF (server-side request forgery).
- CSRF
- запрос с чужого сайта под сессией жертвы
- CORS
- браузерное ослабление same-origin для разрешённых origin
Как отвечать: «CORS защищает мой API?»
Нет, это частое заблуждение. CORS - механизм самого браузера: он решает, можно ли фронту с одного origin читать ответ API с другого, то есть контролируемо ослабляет same-origin-политику. Но это ограничение исполняется на стороне браузера, поэтому любой клиент, которому браузер не указ - curl, Postman, серверный скрипт - просто игнорирует CORS и дёргает мой API напрямую. Реальная защита это аутентификация, авторизация, параметризованные запросы и валидация входа на сервере. CORS я настраиваю ради легитимного фронта, а не как барьер от злоумышленника.
Развеяно ядро заблуждения (CORS исполняет браузер, curl игнорирует), объяснено назначение CORS и названа настоящая защита - точное понимание модели угроз.
На чём валят
- −Строить SQL конкатенацией ввода вместо параметризованного запроса - прямая инъекция.
- −Считать CORS серверной защитой: он исполняется браузером, curl его игнорирует.
- −Хранить пароли открыто или быстрым хешем (MD5); класть секреты в git или образ.
- −Отдавать стектрейс и детали ошибки наружу - подсказка атакующему про стек и структуру.
Проверьте себя
Пять вопросов из банка по этой подтеме. Всего их 12, остальные разбираются в тренажёре.
- Откуда берётся SQL-инъекция и что её надёжно закрывает?A)Из отсутствия шифрования соединения; закрывается переводом базы данных на TLSB)Из медленных запросов к базе; закрывается добавлением подходящих индексов на таблицыC)Из склейки SQL со строкой ввода; лечит параметризованный запросD)Из слабых паролей к базе; закрывается их регулярной принудительной сменой
показать ответ и разбор
+C)Из склейки SQL со строкой ввода; лечит параметризованный запрос// разбор: SQL-инъекция возникает, когда пользовательский ввод склеивают в текст запроса: злоумышленник дописывает своё условие (' OR 1=1--). Надёжное лечение — параметризованные запросы (плейсхолдеры), где драйвер передаёт значения отдельно от кода SQL, или ORM, делающий это за вас. Экранирование вручную ненадёжно. Никогда не строить SQL конкатенацией ввода.
- Пользовательский текст выводится на страницу как есть, и в нём есть <script>. Что за уязвимость и лечение?A)CSRF: лечится добавлением скрытого токена в каждую форму на сайте приложенияB)SQL-инъекция: лечится параметризацией всех запросов к базе данных приложенияC)Утечка памяти: лечится ограничением длины пользовательского ввода на сервереD)XSS: лечится экранированием вывода, а не доверием к вводу
показать ответ и разбор
+D)XSS: лечится экранированием вывода, а не доверием к вводу// разбор: XSS (cross-site scripting): непроэкранированный пользовательский ввод, попав в HTML, исполняется как скрипт в браузере жертвы (кража cookie/токенов, действия от имени пользователя). Лечение — экранирование/кодирование при ВЫВОДЕ по контексту (HTML, атрибут, JS), а также CSP. Современные шаблонизаторы экранируют по умолчанию; опасно ручное вставление сырого HTML.
- Что такое CSRF и чем его типично закрывают?A)Внедрение скрипта в страницу жертвы; закрывается экранированием пользовательского выводаB)Подбор пароля перебором; закрывается ограничением числа попыток входа в системуC)Чужой сайт шлёт запрос от имени залогиненного юзера; лечит CSRF-токен или SameSite-cookieD)Перехват трафика в открытой сети; закрывается обязательным переводом сайта на HTTPS
показать ответ и разбор
+C)Чужой сайт шлёт запрос от имени залогиненного юзера; лечит CSRF-токен или SameSite-cookie// разбор: CSRF (cross-site request forgery): вредоносная страница заставляет браузер жертвы отправить запрос на ваш сайт, где та залогинена — cookie прикрепится автоматически, и действие выполнится от её имени. Защита: CSRF-токен, который знает только ваша страница, и cookie с атрибутом SameSite, не отправляемая при межсайтовых запросах. Токен-в-заголовке API (не cookie) к CSRF менее уязвим.
- Что на самом деле делает CORS?A)Ограничивает частоту запросов с одного домена для защиты от перегрузкиB)Разрешает браузеру межсайтовые запросы к API с указанных originC)Шифрует межсайтовые запросы, чтобы данные не перехватили при передаче по сетиD)Защищает сервер от несанкционированных запросов, блокируя их ещё до обработки
показать ответ и разбор
+B)Разрешает браузеру межсайтовые запросы к API с указанных origin// разбор: Браузер по умолчанию запрещает JS читать ответы кросс-доменных запросов (same-origin policy). CORS — способ серверу ОСЛАБИТЬ это: заголовками Access-Control-Allow-Origin он говорит браузеру, каким origin можно. Важно: CORS — механизм БРАУЗЕРА, не серверная защита. Запрос из curl/бэкенда CORS не остановит — авторизацию по-прежнему проверяет сервер.
- Как правильно хранить пароли пользователей в базе?A)Хешем медленной соль-функции (bcrypt/argon2), а не в открытом видеB)В открытом виде, но в отдельной таблице с ограниченным доступом для админовC)В зашифрованном виде симметричным ключом, чтобы при необходимости расшифровать обратноD)Хешем быстрой функции вроде MD5 или SHA-1, этого для паролей вполне достаточно
показать ответ и разбор
+A)Хешем медленной соль-функции (bcrypt/argon2), а не в открытом виде// разбор: Пароли хранят как необратимый хеш специальной МЕДЛЕННОЙ функции с солью: bcrypt, scrypt, argon2. Медленность и соль делают массовый перебор и радужные таблицы невыгодными. Обратимое шифрование плохо (утечка ключа = утечка всех паролей), быстрые MD5/SHA — тем более. При входе сравнивают хеши, оригинал не восстанавливают.
дальше
Теорию прочитали. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.