\"\n# Браузер выполнит скрипт!\n```\n\n**Защита — экранирование HTML:**\n```python\nfrom markupsafe import escape\n\nuser_input = request.args.get(\"comment\")\nhtml = f\"

{escape(user_input)}

\"\n# Вывет:

<script>alert('hacked')</script>

\n\n# В Jinja2 (Flask/Django) экранирование по умолчанию\n# {{ user_input }} # Автоматически экранируется\n```\n\n**Защита в JavaScript:**\n```python\n# Используй innerText вместо innerHTML\n# JavaScript:\n# НЕПРАВИЛЬНО: document.getElementById(comment).innerHTML = userInput;\n# ПРАВИЛЬНО: document.getElementById(comment).innerText = userInput;\n```\n\n#### 4. NoSQL Injection\n\n**Уязвимый код (MongoDB):**\n```python\n# ОПАСНО!\nuser_input = request.args.get(\"name\")\nuser = db.users.find_one({\"name\": user_input})\n\n# Если user_input = {\"$ne\": null}\n# Запрос станет: {\"name\": {\"$ne\": null}}\n# Вернёт первого пользователя (любого!)\n```\n\n**Защита:**\n```python\n# ПРАВИЛЬНО - валидация типов\nuser_input = request.args.get(\"name\")\nif not isinstance(user_input, str):\n raise ValueError(\"Invalid input\")\nuser = db.users.find_one({\"name\": user_input})\n\n# Или используй schema validation\nfrom pydantic import BaseModel\n\nclass SearchQuery(BaseModel):\n name: str # Только строка\n\nquery = SearchQuery(name=user_input)\nuser = db.users.find_one({\"name\": query.name})\n```\n\n#### 5. LDAP Injection\n\n**Уязвимый код:**\n```python\n# ОПАСНО!\nusername = request.form.get(\"username\")\nldap_filter = f\"(uid={username})\"\nresults = ldap_conn.search(ldap_filter)\n\n# Если username = \"*)(uid=*\"\n# Filter = \"(uid=*)(uid=*)\"\n# Вернёт всех пользователей!\n```\n\n**Защита — экранирование LDAP:**\n```python\nfrom ldap.filter import escape_filter_chars\n\nusername = request.form.get(\"username\")\nescaped = escape_filter_chars(username)\nldap_filter = f\"(uid={escaped})\"\nresults = ldap_conn.search(ldap_filter)\n```\n\n#### 6. Template Injection\n\n**Уязвимый код:**\n```python\n# Jinja2 injection\nuser_input = request.args.get(\"name\")\ntemplate = f\"Hello {user_input}!\"\nresult = jinja_env.from_string(template).render()\n\n# Если user_input = \"{{ 7*7 }}\"\n# Вернёт \"Hello 49!\"\n\n# Если user_input = \"{{ __import__(os).system(ls) }}\"\n# Выполнит команду!\n```\n\n**Защита:**\n```python\n# ПРАВИЛЬНО - используй render() с переменными\nresult = jinja_env.get_template(\"template.html\").render(name=user_input)\n\n# В шаблоне:\n#

Hello {{ name }}!

\n# Переменные будут экранированы автоматически\n```\n\n### Общие принципы защиты\n\n#### 1. Input Validation (Валидация входных данных)\n```python\nfrom pydantic import BaseModel, validator\n\nclass UserInput(BaseModel):\n email: str\n age: int\n \n @validator(\"email\")\n def email_valid(cls, v):\n if \"@\" not in v:\n raise ValueError(\"Invalid email\")\n return v\n \n @validator(\"age\")\n def age_valid(cls, v):\n if v < 0 or v > 150:\n raise ValueError(\"Invalid age\")\n return v\n\nuser = UserInput(email=request.json[\"email\"], age=request.json[\"age\"])\n```\n\n#### 2. Output Encoding (Экранирование вывода)\n```python\nfrom markupsafe import escape\n\n# Для HTML\nhtml = f\"

{escape(user_input)}

\"\n\n# Для JSON\nimport json\njson_str = json.dumps({\"message\": user_input}) # Автоматически экранирует\n\n# Для SQL (используй параметризованные запросы)\ndb.execute(\"SELECT * FROM users WHERE name = ?\", (user_input,))\n```\n\n#### 3. Parametrized Queries (Параметризованные запросы)\n```python\n# ВСЕГДА используй параметры, никогда не конкатенируй\n\n# SQLite\ndb.execute(\"SELECT * FROM users WHERE id = ?\", (user_id,))\n\n# MySQL\ndb.execute(\"SELECT * FROM users WHERE id = %s\", (user_id,))\n\n# PostgreSQL\ndb.execute(\"SELECT * FROM users WHERE id = %s\", (user_id,))\n\n# SQLAlchemy\nfrom sqlalchemy import text\ndb.execute(text(\"SELECT * FROM users WHERE id = :id\"), {\"id\": user_id})\n```\n\n#### 4. Use Security Libraries\n```python\n# bleach для очистки HTML\nimport bleach\nclean_html = bleach.clean(user_input, tags=[\"p\", \"br\"])\n\n# python-html2text для очистки от HTML\nfrom html import escape\n\n# cryptography для защиты sensitive данных\nfrom cryptography.fernet import Fernet\ncipher = Fernet(key)\nencrypted = cipher.encrypt(sensitive_data)\n```\n\n#### 5. Least Privilege (Минимум привилегий)\n```python\n# Используй отдельного пользователя БД для web приложения\n# с минимальными правами (только SELECT/INSERT/UPDATE)\n# НЕ используй root или администратора\n\n# SQL:\nCREATE USER app_user@localhost IDENTIFIED BY password;\nGRANT SELECT, INSERT, UPDATE ON database.* TO app_user@localhost;\n# Не даём права на DROP, ALTER, CREATE\n```\n\n#### 6. Web Application Firewall (WAF)\n```\nУ cloudflare или других провайдеров WAF\nфильтрует инъекции автоматически\n```\n\n### Чеклист безопасности\n\n- ✓ Параметризованные запросы для БД\n- ✓ Экранирование для HTML/JavaScript\n- ✓ Валидация входных данных (type, length, format)\n- ✓ Используй ORM вместо raw SQL\n- ✓ Не используй shell=True в subprocess\n- ✓ Защита от XSS (Content-Security-Policy)\n- ✓ CSRF tokens для POST/PUT/DELETE\n- ✓ HTTPS только\n- ✓ Регулярное обновление зависимостей\n- ✓ Логирование и мониторинг\n\nВывод: главное правило — НИКОГДА не доверяй пользовательским данным. Всегда валидируй и экранируй.","dateCreated":"2026-03-22T11:37:35.706583","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как избежать инъекций в приложении?

2.2 Middle🔥 231 комментариев
#Базы данных (SQL)#Безопасность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Инъекции: защита приложения

Инъекция (Injection) — это атака, когда злоумышленник внедряет вредоносный код в приложение. Это одна из OWASP TOP 10 уязвимостей.

Типы инъекций

1. SQL Injection (SQLi)

Уязвимый код:

# ОПАСНО! Никогда так не делай
user_id = request.args.get("id")
query = f"SELECT * FROM users WHERE id = {user_id}"
results = db.execute(query)

# Злоумышленник передаёт: ?id=1 OR 1=1
# Получится: SELECT * FROM users WHERE id = 1 OR 1=1
# Вернёт всех пользователей!

# Или: ?id=1; DROP TABLE users;--
# Удалит таблицу!

Защита — Parameterized Queries:

# ПРАВИЛЬНО - используй placeholders
user_id = request.args.get("id")
query = "SELECT * FROM users WHERE id = ?"
results = db.execute(query, (user_id,))

# Или с ORM (SQLAlchemy)
user = session.query(User).filter(User.id == user_id).first()

SQL Injection с ORM (безопасно):

from sqlalchemy import text

# НЕПРАВИЛЬНО - конкатенация
query = f"SELECT * FROM users WHERE name = {name}"

# ПРАВИЛЬНО - параметры
query = text("SELECT * FROM users WHERE name = :name")
results = db.execute(query, {"name": name})

# ИЛИ ORM напрямую (самый безопасный вариант)
user = session.query(User).filter(User.name == name).first()

2. Command Injection (OS Command Injection)

Уязвимый код:

import os

# ОПАСНО!
filename = request.args.get("file")
os.system(f"cat {filename}")  # Можно внедрить: ; rm -rf /

# Или
subprocess.run(f"ls {directory}", shell=True)  # shell=True опасна!

Защита — используй список аргументов:

import subprocess

# ПРАВИЛЬНО - массив аргументов
filename = request.args.get("file")
result = subprocess.run(["cat", filename], capture_output=True)

# Без shell=True
subprocess.run(["ls", directory])  # Не может быть injection

3. XSS (Cross-Site Scripting)

Уязвимый код:

# ОПАСНО!
user_input = request.args.get("comment")
html = f"<p>{user_input}</p>"
# Если user_input = "<script>alert(hacked)</script>"
# Браузер выполнит скрипт!

Защита — экранирование HTML:

from markupsafe import escape

user_input = request.args.get("comment")
html = f"<p>{escape(user_input)}</p>"
# Вывет: <p>&lt;script&gt;alert(&#39;hacked&#39;)&lt;/script&gt;</p>

# В Jinja2 (Flask/Django) экранирование по умолчанию
# {{ user_input }}  # Автоматически экранируется

Защита в JavaScript:

# Используй innerText вместо innerHTML
# JavaScript:
# НЕПРАВИЛЬНО: document.getElementById(comment).innerHTML = userInput;
# ПРАВИЛЬНО: document.getElementById(comment).innerText = userInput;

4. NoSQL Injection

Уязвимый код (MongoDB):

# ОПАСНО!
user_input = request.args.get("name")
user = db.users.find_one({"name": user_input})

# Если user_input = {"$ne": null}
# Запрос станет: {"name": {"$ne": null}}
# Вернёт первого пользователя (любого!)

Защита:

# ПРАВИЛЬНО - валидация типов
user_input = request.args.get("name")
if not isinstance(user_input, str):
    raise ValueError("Invalid input")
user = db.users.find_one({"name": user_input})

# Или используй schema validation
from pydantic import BaseModel

class SearchQuery(BaseModel):
    name: str  # Только строка

query = SearchQuery(name=user_input)
user = db.users.find_one({"name": query.name})

5. LDAP Injection

Уязвимый код:

# ОПАСНО!
username = request.form.get("username")
ldap_filter = f"(uid={username})"
results = ldap_conn.search(ldap_filter)

# Если username = "*)(uid=*"
# Filter = "(uid=*)(uid=*)"
# Вернёт всех пользователей!

Защита — экранирование LDAP:

from ldap.filter import escape_filter_chars

username = request.form.get("username")
escaped = escape_filter_chars(username)
ldap_filter = f"(uid={escaped})"
results = ldap_conn.search(ldap_filter)

6. Template Injection

Уязвимый код:

# Jinja2 injection
user_input = request.args.get("name")
template = f"Hello {user_input}!"
result = jinja_env.from_string(template).render()

# Если user_input = "{{ 7*7 }}"
# Вернёт "Hello 49!"

# Если user_input = "{{ __import__(os).system(ls) }}"
# Выполнит команду!

Защита:

# ПРАВИЛЬНО - используй render() с переменными
result = jinja_env.get_template("template.html").render(name=user_input)

# В шаблоне:
# <h1>Hello {{ name }}!</h1>
# Переменные будут экранированы автоматически

Общие принципы защиты

1. Input Validation (Валидация входных данных)

from pydantic import BaseModel, validator

class UserInput(BaseModel):
    email: str
    age: int
    
    @validator("email")
    def email_valid(cls, v):
        if "@" not in v:
            raise ValueError("Invalid email")
        return v
    
    @validator("age")
    def age_valid(cls, v):
        if v < 0 or v > 150:
            raise ValueError("Invalid age")
        return v

user = UserInput(email=request.json["email"], age=request.json["age"])

2. Output Encoding (Экранирование вывода)

from markupsafe import escape

# Для HTML
html = f"<p>{escape(user_input)}</p>"

# Для JSON
import json
json_str = json.dumps({"message": user_input})  # Автоматически экранирует

# Для SQL (используй параметризованные запросы)
db.execute("SELECT * FROM users WHERE name = ?", (user_input,))

3. Parametrized Queries (Параметризованные запросы)

# ВСЕГДА используй параметры, никогда не конкатенируй

# SQLite
db.execute("SELECT * FROM users WHERE id = ?", (user_id,))

# MySQL
db.execute("SELECT * FROM users WHERE id = %s", (user_id,))

# PostgreSQL
db.execute("SELECT * FROM users WHERE id = %s", (user_id,))

# SQLAlchemy
from sqlalchemy import text
db.execute(text("SELECT * FROM users WHERE id = :id"), {"id": user_id})

4. Use Security Libraries

# bleach для очистки HTML
import bleach
clean_html = bleach.clean(user_input, tags=["p", "br"])

# python-html2text для очистки от HTML
from html import escape

# cryptography для защиты sensitive данных
from cryptography.fernet import Fernet
cipher = Fernet(key)
encrypted = cipher.encrypt(sensitive_data)

5. Least Privilege (Минимум привилегий)

# Используй отдельного пользователя БД для web приложения
# с минимальными правами (только SELECT/INSERT/UPDATE)
# НЕ используй root или администратора

# SQL:
CREATE USER app_user@localhost IDENTIFIED BY password;
GRANT SELECT, INSERT, UPDATE ON database.* TO app_user@localhost;
# Не даём права на DROP, ALTER, CREATE

6. Web Application Firewall (WAF)

У cloudflare или других провайдеров WAF
фильтрует инъекции автоматически

Чеклист безопасности

  • ✓ Параметризованные запросы для БД
  • ✓ Экранирование для HTML/JavaScript
  • ✓ Валидация входных данных (type, length, format)
  • ✓ Используй ORM вместо raw SQL
  • ✓ Не используй shell=True в subprocess
  • ✓ Защита от XSS (Content-Security-Policy)
  • ✓ CSRF tokens для POST/PUT/DELETE
  • ✓ HTTPS только
  • ✓ Регулярное обновление зависимостей
  • ✓ Логирование и мониторинг

Вывод: главное правило — НИКОГДА не доверяй пользовательским данным. Всегда валидируй и экранируй.

Как избежать инъекций в приложении? | PrepBro