В веб-приложении на Flask встречается код: user = request.args.get('user'); query = "SELECT * FROM users WHERE name = '" + user + "'"; results = db.execute(query) — выявите уязвимости (SQL-инъекции, XSS, CSRF и т.п.), предложите конкретные исправления и обсудите подходы к хранению паролей и управлению сессиями

10 Окт 2025 в 13:31
128 +1
0
Ответы
1

Код
user = request.args.get('user')
query = "SELECT * FROM users WHERE name = '" + user + "'"
results = db.execute(query)

содержит несколько серьёзных проблем безопасности. Ниже — что именно уязвимо, почему, и конкретные исправления + рекомендации по хранению паролей и управлению сессиями.

1) Уязвимости в исходном коде

SQL‑инъекция. Формирование SQL через конкатенацию строки с участием пользовательского ввода даёт возможность выполнить произвольный SQL (например: user = "x' OR '1'='1";).XSS (reflected/stored). Если значение user затем выводится в HTML без экранирования — возможна межсайтовая скриптовая атака.CSRF (если этот GET/POST используется для изменения состояния без защиты). Хотя пример показывает только SELECT — общая практика использования небезопасных эндпоинтов и отсутствие CSRF‑защиты рискована.Утечки информации / логирование. Если логируете raw-запросы, можно слить секреты.Неправильное хранение паролей (если пароли вообще хранятся в виде plain text в users) — очень опасно.Неправильная конфигурация сессий (незащищённые cookies, отсутствие HttpOnly/Secure/SameSite).

2) Конкретные исправления (по порядку)
A. Защита от SQL‑инъекций — использовать параметризованные запросы / ORM

Psycopg2 / psycopg2‑binary (Postgres):
cur.execute("SELECT * FROM users WHERE name = %s", (user,))sqlite3:
cur.execute("SELECT * FROM users WHERE name = ?", (user,))SQLAlchemy (рекомендуется в Flask):
ORM

user_obj = User.query.filter_by(name=user).first()

или text + параметры

from sqlalchemy import text
results = db.session.execute(text("SELECT * FROM users WHERE name = :n"), {"n": user})

Важно: никогда не вставляйте user напрямую в строку SQL.

B. Экранирование и защита от XSS

При рендере HTML используйте шаблонизатор с авто‑эскейпингом (Jinja2 в Flask эскейпит по умолчанию). Пример:
return render_template("profile.html", user=user)Если вам нужно вывести HTML, убедитесь, что вы доверяете содержимому (и используйте Markup/escape осознанно).Дополнительно — заголовки CSP (Content‑Security‑Policy) и правильный набор заголовков безопасности (X-Frame-Options, X-Content-Type-Options).

C. CSRF

Для форм/POST/изменяющих запросов используйте CSRF‑токены (Flask-WTF или flask_wtf.csrf.CSRFProtect).
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect(app)Для API обычно используют токены в заголовке авторизации (Bearer) и CORS/SameSite политики вместо cookie‑CSRF.

D. Валидация и нормализация ввода

По возможности применяйте allow‑list: длина, допустимые символы (например, имена пользователей — только латиница/цифры/символы).Для поиска по LIKE используйте параметризованные запросы и экранирование wildcard‑символов.

3) Пример безопасного кода (Flask + SQLAlchemy + CSRF)
Пример минимальной реализации получения пользователя:
from flask import Flask, request, render_template
from flask_wtf.csrf import CSRFProtect
from models import User # SQLAlchemy модель

app = Flask(name)
csrf = CSRFProtect(app)

@app.route('/user')
def user_profile():
name = request.args.get('user', '', type=str)

Валидация: ограничить длину и набор символовif not name or len(name) > 100:
abort(400)
user = User.query.filter_by(name=name).first() # параметризовано
return render_template('profile.html', user=user) # Jinja2 эскейпит автоматически

4) Хранение паролей — лучшие практики

Никогда не храните пароли в открытом виде.

Используйте адаптивные KDF (key derivation function):

Argon2 (рекомендуется), bcrypt, scrypt. PBKDF2 возможно, но Argon2 предпочтительнее на 2024+.

Используйте проверенные библиотеки:

argon2-cffi: from argon2 import PasswordHasherpasslib (оборачивает bcrypt/argon2 и даёт удобство)werkzeug.security.generate_password_hash (использует PBKDF2 по умолчанию; приемлемо, но Argon2/Bcrypt лучше)

Пример (argon2):
from argon2 import PasswordHasher
ph = PasswordHasher(time_cost=2, memory_cost=65536, parallelism=4) # настраивайте под вашу infra
hash = ph.hash(plain_password)

проверка:

try:
ph.verify(hash, provided_password)
except VerifyMismatchError:

неверный пароль

Важные замечания:

Используйте уникальную соль для каждой записи (библиотеки сами генерируют соль).Храните только hash (и параметры, если библиотека не включает их).Используйте constant-time сравнение при проверке (библиотеки делают это).Планируйте миграцию параметров (увеличение cost) — храните метаданные для каждого хеша или используйте passlib, который умеет ре-хешировать при входе.

5) Управление сессиями

Конфигурация cookie:
SESSION_COOKIE_SECURE = True (только HTTPS)SESSION_COOKIE_HTTPONLY = True (не доступно JS)SESSION_COOKIE_SAMESITE = 'Lax' или 'Strict' (предпочтительно Lax для большинства)Flask по умолчанию хранит сессии в client‑signed cookies. Для большей безопасности храните сессии на сервере (Redis/DB) через Flask-Session:
from flask_session import Session
app.config['SESSION_TYPE'] = 'redis'
Session(app)Защита от фиксации сессий:
Генерируйте новый идентификатор сессии при логине (session.clear() и заполнение новой сессии).На логаут обязательно удаляйте сессию на сервере и cookie.Ограничение времени жизни:
app.permanent_session_lifetime = timedelta(hours=1)Используйте короткие тайм‑ауты для чувствительных операций и опцию "запомнить меня" с долгосрочной токенизацией, а не долговременными сессионными куки.Аутентификация:
Используйте Flask-Login для управления логином/логаутом, и храните только идентификатор пользователя в сессии.Для API — используйте JWT аккуратно (реплэй/отзыв проблемны) или токены доступа + refresh токены, хранимые в httpOnly cookie и с проверкой на сервере.

6) Дополнительные рекомендации

HTTPS всегда.Ограничение частоты (rate limiting) и защита от брутфорса (Flask-Limiter, блокировки, задержки).Логирование не содержит секретов (не логируйте пароли, токены, полные запросы с секр. параметрами).Мониторинг, IDS/IPS и тестирование (DAST, SAST, регулярные pentest).Минимизация прав БД: приложение использует пользователя БД с минимальными правами (SELECT/INSERT/UPDATE только по необходимости).Принцип наименьших привилегий для секретов и сервисов.

Кратко — что нужно сделать прямо сейчас

Заменить конкатенацию SQL на параметризованные запросы / ORM.Экранировать/валидировать пользовательский ввод и эскейпить вывод в шаблонах (Jinja2 по умолчанию).Подключить CSRF‑защиту для форм/изменяющих запросов.Перейти на безопасное хранение паролей (Argon2/bcrypt через библиотеки).Пересмотреть конфигурацию сессий (Secure, HttpOnly, SameSite), и при необходимости перейти на серверные сессии + регенерация сессии при логине.

Если хотите, могу:

Привести готовый пример приложения Flask с SQLAlchemy, Argon2 и Flask‑Login, где все эти рекомендации реализованы,Или показать конкретные примеры под вашу СУБД (Postgres/SQLite/MySQL).
10 Окт 2025 в 13:56
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир