Python
October 21

πŸ›‘οΈ Как Π·Π°ΠΊΠ°Π»ΠΈΡ‚ΡŒ FastAPI ΠΎΡ‚ уязвимостСй (ΠΈ Π½Π΅ Π΄Π°Ρ‚ΡŒ Ρ…Π°ΠΊΠ΅Ρ€Π°ΠΌ ΠΈΡΠΏΠΎΡ€Ρ‚ΠΈΡ‚ΡŒ Тизнь Π²Π°ΡˆΠ΅ΠΌΡƒ ΠΊΠΎΡ‚ΠΈΠΊΡƒ)

FastAPI β€” ΠΊΠ°ΠΊ ΠΏΡƒΡˆΠΈΡΡ‚Ρ‹ΠΉ ΠΊΠΎΡ‚: Π»Ρ‘Π³ΠΊΠΈΠΉ, быстрый, ΠΎΡ‚Π·Ρ‹Π²Ρ‡ΠΈΠ²Ρ‹ΠΉ ΠΈ Π²ΠΎΠΎΠ±Ρ‰Π΅ Ρ‡ΡƒΠ΄ΠΎ-Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ. Но, ΠΊΠ°ΠΊ ΠΈ ΠΊΠΎΡ‚, ΠΎΠ½ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ ΡƒΡ…ΠΎΠ΄Π° ΠΈ Π·Π°Ρ‰ΠΈΡ‚Ρ‹. Π”Π°ΠΆΠ΅ самоС элСгантноС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚Π°Ρ‚ΡŒ Π»Π°ΠΊΠΎΠΌΡ‹ΠΌ кусочком для Π°Ρ‚Π°ΠΊ, Ссли Π΅Π³ΠΎ Π½Π΅ ΡƒΠΊΡ€Π΅ΠΏΠΈΡ‚ΡŒ.

БСгодня ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΠΌ, ΠΊΠ°ΠΊ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ вашС FastAPI-ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ максимально устойчивым ΠΊ уязвимостям β€” Π±Π΅Π· Ρ„Π°Π½Π°Ρ‚ΠΈΠ·ΠΌΠ°, Π½ΠΎ с любовью ΠΊ бСзопасности ❀️.


🧩 1. ОбновлСния ΠΈ зависимости: мСньшС ΡΡ‚Π°Ρ€ΡŒΡ β€” мСньшС Π΄Ρ‹Ρ€

Бамая частая ΡƒΡΠ·Π²ΠΈΠΌΠΎΡΡ‚ΡŒ β€” ΡƒΡΡ‚Π°Ρ€Π΅Π²ΡˆΠΈΠ΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹.
Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ инструмСнты Π²Ρ€ΠΎΠ΄Π΅:

pip install safety
safety check

ΠΈΠ»ΠΈ Π² CI/CD β€” pip-audit, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ зависимости Π½Π° извСстныС уязвимости.
А Π΅Ρ‰Ρ‘ Π»ΡƒΡ‡ΡˆΠ΅ β€” фиксируйтС вСрсии Π² requirements.txt ΠΈ обновляйтС ΠΈΡ… Ρ€Π°Π· Π² мСсяц (ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ cron-Π·Π°Π΄Π°Ρ‡Ρƒ ΠΈΠ»ΠΈ GitLab pipeline).

πŸ’‘ Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½Ρ‹ΠΉ Ρ„Π°ΠΊΡ‚: Π² 2023 Π³ΠΎΠ΄Ρƒ Π±ΠΎΠ»Π΅Π΅ 60% Python-уязвимостСй ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΠ»ΠΈΡΡŒ ΠΈΠΌΠ΅Π½Π½ΠΎ Π½Π° сторонниС Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ. ΠšΠΎΡ‚ΠΈΠΊ-дСвопс Π±Ρ‹ Π·Π°ΠΏΠ»Π°ΠΊΠ°Π», Ссли Π±Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Π» нСзафиксированныС зависимости.

πŸ” 2. НастройтС ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹Π΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ бСзопасности

FastAPI Π»Π΅Π³ΠΊΠΎ интСгрируСтся с Starlette Middleware.
Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄Π΅Π»Π°ΡŽΡ‚ Тизнь Π·Π»ΠΎΡƒΠΌΡ‹ΡˆΠ»Π΅Π½Π½ΠΈΠΊΠΎΠ² слоТнСС:

from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from starlette.middleware.trustedhost import TrustedHostMiddleware

app = FastAPI()

app.add_middleware(
    TrustedHostMiddleware, allowed_hosts=["example.com", "*.example.com"]
)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://example.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST"],
    allow_headers=["*"],
)

Π’Π°ΠΊΠΆΠ΅ стоит ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ HTTP Security Headers Ρ‡Π΅Ρ€Π΅Π· reverse proxy (Nginx, Traefik):

add_header X-Frame-Options "DENY";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin";
add_header Content-Security-Policy "default-src 'self'";

πŸ§‘β€πŸ’» 3. Валидация Π²Ρ…ΠΎΠ΄Π½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…

FastAPI β€” Ρ‡Π΅ΠΌΠΏΠΈΠΎΠ½ ΠΏΠΎ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ благодаря Pydantic, Π½ΠΎ Π½Π΅ Π·Π°Π±Ρ‹Π²Π°ΠΉΡ‚Π΅ ΠΏΡ€ΠΎ:

  • строгиС Ρ‚ΠΈΠΏΡ‹ (constr, conint, EmailStr),
  • рСгулярки (regex=),
  • собствСнныС Π²Π°Π»ΠΈΠ΄Π°Ρ‚ΠΎΡ€Ρ‹ (@validator).

ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

from pydantic import BaseModel, EmailStr, constr

class User(BaseModel):
    username: constr(min_length=3, max_length=32, regex=r"^[a-zA-Z0-9_]+quot;)
    email: EmailStr

Π’Π°ΠΊ Π²Ρ‹ Π·Π°Ρ‰ΠΈΡ‚ΠΈΡ‚Π΅ΡΡŒ ΠΎΡ‚ SQL-ΠΈΠ½ΡŠΠ΅ΠΊΡ†ΠΈΠΉ, XSS ΠΈ ΠΏΡ€ΠΎΡ‡Π΅ΠΉ гадости Π΅Ρ‰Ρ‘ Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ Π΄Π°Π½Π½Ρ‹Ρ….

😸 ΠšΠΎΡˆΠ°Ρ‡ΠΈΠΉ Π»Π°ΠΉΡ„Ρ…Π°ΠΊ: валидация β€” ΠΊΠ°ΠΊ чистка ΡˆΠ΅Ρ€ΡΡ‚ΠΈ. Π”Π΅Π»Π°ΠΉΡ‚Π΅ Π΅Ρ‘ рСгулярно, ΠΈ Π±ΡƒΠ΄Π΅Ρ‚ мСньшС нСприятных ΡΡŽΡ€ΠΏΡ€ΠΈΠ·ΠΎΠ².

🧱 4. ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ запросов (Rate Limiting)

Π‘Π΅Π· Π»ΠΈΠΌΠΈΡ‚ΠΎΠ² ваш сСрвСр ΠΌΠΎΠΆΠ΅Ρ‚ Π»Π΅Π³ΠΊΠΎ Β«ΡƒΠ»Π΅Ρ‚Π΅Ρ‚ΡŒ Π² космос» ΠΎΡ‚ DDoS ΠΈΠ»ΠΈ случайного скрипта. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ middleware, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ slowapi

from slowapi import Limiter
from slowapi.util import get_remote_address
from fastapi import FastAPI

limiter = Limiter(key_func=get_remote_address)
app = FastAPI()
app.state.limiter = limiter

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π΄Π°ΠΆΠ΅ Ссли ΠΊΡ‚ΠΎ-Ρ‚ΠΎ Π·Π°Ρ…ΠΎΡ‡Π΅Ρ‚ Π·Π°ΡΠΏΠ°ΠΌΠΈΡ‚ΡŒ ваш эндпоинт, ΠΎΠ½ упрётся Π² мягкий, Π½ΠΎ Π½Π°Π΄Ρ‘ΠΆΠ½Ρ‹ΠΉ firewall.


🧰 5. Π₯Ρ€Π°Π½Π΅Π½ΠΈΠ΅ сСкрСтов ΠΈ Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ²

Никогда Π½Π΅ Ρ…Ρ€Π°Π½ΠΈΡ‚Π΅ ΠΏΠ°Ρ€ΠΎΠ»ΠΈ ΠΈ API-ΠΊΠ»ΡŽΡ‡ΠΈ Π² .env рядом с ΠΊΠΎΠ΄ΠΎΠΌ Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ.
Π›ΡƒΡ‡ΡˆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Vault, Doppler, AWS Secrets Manager ΠΈΠ»ΠΈ хотя Π±Ρ‹ Kubernetes secrets.

А Ссли всё-Ρ‚Π°ΠΊΠΈ .env, Ρ‚ΠΎ:

  • Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ .env Π² .gitignore;
  • ΡˆΠΈΡ„Ρ€ΡƒΠΉΡ‚Π΅ содСрТимоС с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ fernet ΠΈΠ»ΠΈ dotenv-vault.

🐾 Π€Π°ΠΊΡ‚: Π² 2024 Π³ΠΎΠ΄Ρƒ исслСдоватСли GitGuardian нашли 10 ΠΌΠΈΠ»Π»ΠΈΠΎΠ½ΠΎΠ² ΡƒΡ‚Π΅ΠΊΡˆΠΈΡ… Ρ‚ΠΎΠΊΠ΅Π½ΠΎΠ² Π² ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Ρ… рСпозиториях GitHub. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΊΠΎΡ‚-Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ сказал Ρ‚ΠΎΠ³Π΄Π°: «мяу...Β»

🧠 6. HTTPS и HSTS

ΠžΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ HTTPS.
Π’ Nginx это просто:

listen 443 ssl;
ssl_certificate /etc/ssl/certs/fullchain.pem;
ssl_certificate_key /etc/ssl/private/privkey.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

🧨 7. Π˜Π·ΠΎΠ»ΡΡ†ΠΈΡ ΠΈ ΠΏΠΎΠ»ΠΈΡ‚ΠΈΠΊΠ° ΠΏΡ€Π°Π²

Если Π²Ρ‹ Π΄Π΅ΠΏΠ»ΠΎΠΈΡ‚Π΅ FastAPI Π² Docker:

  • ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Π½Π΅ root ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ;
  • Π²ΠΊΠ»ΡŽΡ‡Π°ΠΉΡ‚Π΅ read-only Ρ„Π°ΠΉΠ»ΠΎΠ²ΡƒΡŽ систСму, Ссли Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ;
  • ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΡŒΡ‚Π΅ доступ ΠΏΠΎ сСти;
  • ΠΈ Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ seccomp, no-new-privileges.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Dockerfile:

FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN useradd -m appuser
USER appuser
CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]

🐾 Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

FastAPI β€” это ΠΌΠΎΡ‰Π½Ρ‹ΠΉ, Π½ΠΎ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Π·Π²Π΅Ρ€Ρ‘ΠΊ.
Если ΡƒΠ΄Π΅Π»ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ бСзопасности β€” обновлСниям, Ρ‚ΠΎΠΊΠ΅Π½Π°ΠΌ, Ρ‚ΠΈΠΏΠ°ΠΌ, изоляции ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°ΠΌ β€” вашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ станСт ΠΊΡ€Π΅ΠΏΡ‡Π΅, Ρ‡Π΅ΠΌ ΠΊΠΎΠ³Ρ‚ΠΈ ΠΊΠΎΡ‚Π° Π½Π° занавСскС πŸˆβ€β¬›.

НС Π·Π°Π±Ρ‹Π²Π°ΠΉΡ‚Π΅: уязвимости Π½Π΅ спят. А Π·Π½Π°Ρ‡ΠΈΡ‚, ΠΏΡƒΡΡ‚ΡŒ ваш CI/CD ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ дСнь Π±ΡƒΠ΄Π΅Ρ‚ ΠΊΠ°ΠΊ Π΄Π΅ΠΆΡƒΡ€Π½Ρ‹ΠΉ ΠΊΠΎΡ‚, ΠΏΠ°Ρ‚Ρ€ΡƒΠ»ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ ΡΠ΅Ρ€Π²Π΅Ρ€Π½ΡƒΡŽ ΠΊΠΎΠΌΠ½Π°Ρ‚Ρƒ.