0Pricing
Security+ Academy · Урок

Проверка входных данных и кодирование выходных данных

Внедряйте проверку входных данных на сервере и контекстно-зависимое кодирование выходных данных, чтобы нейтрализовать уязвимости, связанные с внедрением кода и XSS, до их эксплуатации.

«Проверка входных данных и кодирование выходных данных» — бесплатный урок Security+ Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Security+ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Security+ Academy содержит 4 уроков всего.

Почему входные данные опасны

Каждый фрагмент данных, который application получает извне, — данные пользовательских форм, параметры URL, HTTP-заголовки, тела запросов API и загружаемые файлы — потенциально контролируется злоумышленником. Без проверки злоумышленники внедряют команды SQL, сценарии HTML, команды оболочки и директивы XML/LDAP в потоки данных application. Проверка входных данных и кодирование выходных данных — два основных средства защиты, нейтрализующих уязвимости, связанные с внедрением, ещё до того, как они смогут причинить вред.

Что такое проверка входных данных

Проверка входных данных подтверждает, что полученные данные соответствуют ожидаемым типу, формату, длине и диапазону значений, прежде чем application начнёт их обрабатывать. Проверка должна выполняться на стороне Server — проверку на стороне Client в JavaScript легко обойти, перехватив запросы с помощью таких инструментов, как Burp Suite. Поле имени пользователя должно принимать только буквенно-цифровые символы; поле даты — только допустимые форматы даты; поле электронной почты — соответствовать синтаксису RFC 5322.

# Server-side input validation examples:

# Validate username: allow only alphanumeric and underscore
# Pattern: ^[a-zA-Z0-9_]{3,20}$
# Reject: 'admin--', "' OR 1=1--", '<script>alert(1)</script>'

# Validate age: must be integer between 0 and 120
# Reject: -1, 999, 'abc', '18; DROP TABLE users'

# Validate email: match RFC 5322 pattern, max 254 chars
# Reject: 'a@b' (too short), attacker@evil.com<script>...

Проверка по Allowlist и Denylist

Проверка по Allowlist (белому списку) точно определяет, что IS разрешено, и отклоняет всё остальное. Проверка по Denylist (чёрному списку) определяет, что NOT разрешено, и допускает всё остальное. Проверка по Allowlist всегда предпочтительнее, поскольку злоумышленники постоянно находят новые способы обхода Denylist. Например, Denylist для защиты от SQL-инъекций пытается блокировать SELECT, UNION и символы --, но необычные варианты кодирования часто позволяют обойти такие фильтры. Allowlist, разрешающий для числового поля только цифры, обойти невозможно.

# Allowlist (GOOD): only allow expected characters
# username_pattern = '^[a-zA-Z0-9_]{3,20}$'
# If input does not match -> reject with 400 Bad Request

# Denylist (WEAK): try to block known-bad patterns
# reject_patterns = ["'", '--', 'UNION', 'SELECT', 'DROP']
# Problem: attacker uses: SE%00LECT, UNION%0aALL, encoded chars
# Denylist is incomplete by definition -> prefer allowlist

Параметризованные запросы предотвращают SQL-инъекции

Для взаимодействия с базами данных параметризованные запросы (подготовленные выражения) являются надёжной защитой от SQL-инъекций. Структура запроса определяется отдельно от данных, предоставленных пользователем, поэтому обработчик базы данных никогда не воспринимает входные данные как синтаксис SQL. Даже если пользователь введёт ' OR '1'='1, это будет обработано как строковый параметр, а не как исполняемый SQL-код. Параметризованные запросы доступны во всех основных языках и драйверах баз данных.

# VULNERABLE: string concatenation (SQL injection possible)
# query = 'SELECT * FROM users WHERE name = ' + user_input
# Attack: user_input = "' OR '1'='1" -> returns ALL users

# SAFE: parameterized query
# query = 'SELECT * FROM users WHERE name = ?'
# cursor.execute(query, (user_input,))
# The ? is a placeholder; user_input is passed separately
# The DB driver handles escaping automatically
# Attack input: "' OR '1'='1" -> treated as literal string

Что такое кодирование выходных данных

Кодирование выходных данных преобразует специальные символы в данных перед их вставкой в контекст вывода (HTML, JavaScript, SQL, URL, команды оболочки). Это гарантирует, что данные из одного контекста не будут интерпретироваться как исполняемый код в другом. Основной принцип — кодирование с учётом контекста: применяемое кодирование должно соответствовать контексту вывода. Кодирование HTML, кодирование URL, кодирование JavaScript и заключение аргументов команд оболочки в кавычки нейтрализуют внедрение в соответствующих контекстах.

Кодирование выходных данных HTML предотвращает XSS

Когда данные, предоставленные пользователем, отображаются в HTML, специальные символы необходимо кодировать в формате HTML, чтобы предотвратить межсайтовый скриптинг (XSS). Символ < превращается в &lt;, > — в &gt;, а & — в &amp;. Если злоумышленник введёт <script>alert('XSS')</script>, кодирование HTML отобразит это как видимый текст, а не выполнит сценарий. Каждая платформа веб-разработки предоставляет функции кодирования HTML — используйте их последовательно.

# Without encoding (VULNERABLE to XSS):
# html = '<p>Hello, ' + username + '</p>'
# If username = '<script>document.cookie</script>'
# -> script executes in victim browser

# With HTML encoding (SAFE):
# html = '<p>Hello, ' + html_encode(username) + '</p>'
# html_encode('<script>...') -> '&lt;script&gt;...&lt;/script&gt;'
# -> Displays as text, not executable script

Правила кодирования для конкретного контекста

Для разных контекстов вывода требуются разные стратегии кодирования. Тело HTML: кодируйте < > & ' ". Атрибуты HTML: кодируйте те же символы и обязательно заключайте атрибуты в кавычки. Контекст JavaScript: используйте кодирование JSON или экранирование строк JavaScript. Параметры URL: применяйте процентное кодирование специальных символов. Команды оболочки: полностью избегайте построения команд оболочки из пользовательских данных; вместо конкатенации строк с интерпретаторами оболочки используйте API языка с массивами аргументов.

# Context-aware encoding examples:

# HTML body context:
# safe_html = '&lt;script&gt;' (renders as text)

# URL parameter context:
# safe_url = 'search?q=hello%20world%26more'

# JavaScript string context (in JSON):
# safe_js = '{"name": "O\\u0027Reilly"}'

# Shell command (AVOID string concat - use array instead):
# UNSAFE: os.system('ping ' + user_input)
# SAFE:   subprocess.run(['ping', '-c', '1', user_input])

Проверка на нескольких уровнях

Проверка входных данных должна выполняться на нескольких уровнях, а не только в конечной точке API. Проверка на стороне Client улучшает взаимодействие с пользователем (обеспечивает немедленную обратную связь), но ей ни в коем случае нельзя доверять с точки зрения безопасности. Проверка API/контроллера — основной уровень защиты. Проверка в службе и бизнес-логике обеспечивает соблюдение предметных правил. Ограничения базы данных (NOT NULL, CHECK, FOREIGN KEY) обеспечивают последний уровень защиты. Многоуровневая защита означает, что обход одного уровня не приводит немедленно к эксплуатации уязвимости.

Проверка загружаемых файлов

Входные данные при загрузке файлов особенно опасны. Злоумышленники загружают веб-оболочки (замаскированные под изображения), вредоносные документы (с макросами) или файлы чрезмерного размера (DoS). Проверка должна включать: подтверждение типа файла по содержимому (магическим байтам), а не только по расширению; ограничение максимального размера файла; хранение загруженных данных за пределами корневого каталога веб-сервера; переименование файлов на Server для предотвращения предсказуемых путей; проверку с помощью антивируса или изолированной среды; и запрет на непосредственное выполнение загруженных файлов.

# File upload validation steps:
# 1. Check Content-Type header (client-provided, not trusted alone)
# 2. Read first bytes (magic bytes):
#    JPEG: FF D8 FF | PNG: 89 50 4E 47 | PDF: 25 50 44 46
# 3. Reject if magic bytes don't match expected type
# 4. Enforce max size: reject > 10MB
# 5. Strip original filename, assign random UUID filename
# 6. Store in /var/uploads/ (NOT /var/www/html/)
# 7. Serve via CDN or application route (not direct URL)

Проверка входных данных в API

Современные приложения широко используют REST API и GraphQL, поэтому необходимо проверять тела запросов JSON/XML. Средства проверки API, такие как схема JSON, определяют обязательные поля, типы данных, шаблоны строк и диапазоны значений. Ограничение глубины GraphQL предотвращает DoS из-за чрезмерно вложенных запросов. Ограничение частоты запросов предотвращает автоматизированные злоупотребления, даже если отдельные входные данные корректны. Проверка схемы должна выполняться до того, как запрос будет обработан бизнес-логикой.

# JSON Schema validation example:
# POST /api/register body schema:
# {
#   'type': 'object',
#   'required': ['username', 'email', 'password'],
#   'properties': {
#     'username': {'type': 'string', 'pattern': '^[a-zA-Z0-9_]{3,20}$'},
#     'email':    {'type': 'string', 'format': 'email', 'maxLength': 254},
#     'password': {'type': 'string', 'minLength': 12, 'maxLength': 128}
#   },
#   'additionalProperties': false
# }

Сообщения об ошибках и раскрытие информации

Сообщения об ошибках, возвращаемые пользователям, могут непреднамеренно раскрывать конфиденциальную информацию, помогающую злоумышленникам. Сообщения об ошибках базы данных могут раскрыть имена таблиц, типы столбцов или синтаксис SQL. Трассировки стека раскрывают версии платформы application и пути к файлам. Подробные сообщения об ошибках проверки входных данных могут подтвердить злоумышленнику, какие символы отклоняются, и помочь подготовить попытки обхода. Рекомендуется возвращать Client понятные обобщённые сообщения об ошибках (например, «Invalid input»), а подробные сведения об ошибках записывать на Server для отладки разработчиками. Никогда не раскрывайте конечным пользователям необработанные сообщения об исключениях.

# UNSAFE: returning detailed database error to user
# Error: 'You have an error in your SQL syntax near ... at line 1'
# Reveals: database type (MySQL), partial query structure

# UNSAFE: stack trace in API response
# Error: 'java.sql.SQLException at com.company.UserDAO.findByName:47'
# Reveals: framework (Java), class names, line numbers

# SAFE: generic error response to client
# HTTP 400 Bad Request: { 'error': 'Invalid request parameters' }
# Server log (internal only): full exception with stack trace
# Monitoring: alert on high error rates -> investigate internally

Быстрая проверка

Проверьте своё понимание концепций CompTIA Security+ (SY0-701), рассмотренных в этом уроке.

Итоги урока

В этом уроке Вы узнали, что проверка входных данных на стороне Server с использованием Allowlist гарантирует обработку только ожидаемых данных; параметризованные запросы предотвращают SQL-инъекции, отделяя данные от структуры запроса; а кодирование выходных данных с учётом контекста предотвращает XSS и другие атаки с внедрением, нейтрализуя специальные символы до их попадания в контексты HTML, JavaScript, URL или оболочки. Далее мы рассмотрим безопасное управление секретами и внедрение переменных окружения.

Часто задаваемые вопросы

Урок «Проверка входных данных и кодирование выходных данных» бесплатный?

Да — полный текст урока «Проверка входных данных и кодирование выходных данных» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Security+ Academy, подпишись на CoddyKit PRO. Курс Security+ Academy содержит 4 уроков всего.

Чему я научусь в уроке «Проверка входных данных и кодирование выходных данных»?

Внедряйте проверку входных данных на сервере и контекстно-зависимое кодирование выходных данных, чтобы нейтрализовать уязвимости, связанные с внедрением кода и XSS, до их эксплуатации. Ты практикуешь Security+ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Security+ Academy?

Предыдущий опыт не требуется. Security+ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Проверка входных данных и кодирование выходных данных»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Security+ Academy?

Да. Каждый урок Security+ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Проверка входных данных и кодирование выходных данных
  2. Безопасное управление секретами и переменными окружения
  3. Безопасность зависимостей и анализ состава программного обеспечения
  4. DevSecOps: перенос безопасности в начало конвейеров
← Назад к Security+ Academy