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

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

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

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

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

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

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

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

user_obj = User.query.filter_byname=username=username=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эскейпитпоумолчаниюJinja2 в Flask эскейпит по умолчаниюJinja2вFlaskэскейпитпоумолчанию. Пример:
return render_template("profile.html", user=user)Если вам нужно вывести HTML, убедитесь, что вы доверяете содержимому ииспользуйтеMarkup/escapeосознаннои используйте Markup/escape осознанноииспользуйтеMarkup/escapeосознанно.Дополнительно — заголовки CSP Content‑Security‑PolicyContent‑Security‑PolicyContentSecurityPolicy и правильный набор заголовков безопасности X−Frame−Options,X−Content−Type−OptionsX-Frame-Options, X-Content-Type-OptionsXFrameOptions,XContentTypeOptions.

C. CSRF

Для форм/POST/изменяющих запросов используйте CSRF‑токены Flask−WTFилиflaskwtf.csrf.CSRFProtectFlask-WTF или flask_wtf.csrf.CSRFProtectFlaskWTFилиflaskw tf.csrf.CSRFProtect.
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtectappappappДля API обычно используют токены в заголовке авторизации BearerBearerBearer и CORS/SameSite политики вместо cookie‑CSRF.

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

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

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

app = Flask<strong>name</strong><strong>name</strong><strong>name</strong> csrf = CSRFProtectappappapp

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

Валидация: ограничить длину и набор символовif not name or lennamenamename > 100:
abort400400400 user = User.query.filter_byname=namename=namename=name.first # параметризовано
return render_template′profile.html′,user=user'profile.html', user=userprofile.html,user=user # Jinja2 эскейпит автоматически

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

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

Используйте адаптивные KDF keyderivationfunctionkey derivation functionkeyderivationfunction:

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

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

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

Пример argon2argon2argon2:
from argon2 import PasswordHasher
ph = PasswordHashertimecost=2,memorycost=65536,parallelism=4time_cost=2, memory_cost=65536, parallelism=4timec ost=2,memoryc ost=65536,parallelism=4 # настраивайте под вашу infra
hash = ph.hashplainpasswordplain_passwordplainp assword

проверка:

try:
ph.verifyhash,providedpasswordhash, provided_passwordhash,providedp assword except VerifyMismatchError:

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

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

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

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

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

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

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

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

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

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

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