Skip to content

Безопасный режим

Безопасный режим предоставляет функциональность обнаружения опасных паттернов для предотвращения инъекций JSON, загрязнения прототипа и других угроз безопасности.

Структура DangerousPattern

DangerousPattern представляет паттерн угрозы безопасности. Это структура.

go
type DangerousPattern struct {
    Pattern string       // Подстрока для обнаружения во входных данных
    Name    string       // Описательное имя паттерна
    Level   PatternLevel // Уровень серьёзности, определяющий способ обработки паттерна
}

Описание полей

ПолеТипОписание
PatternstringПодстрока для обнаружения во входных данных
NamestringОписательное имя паттерна
LevelPatternLevelУровень серьёзности, определяющий способ обработки паттерна

Тип PatternLevel

PatternLevel представляет уровень серьёзности опасного паттерна.

go
type PatternLevel int

Константы

go
const (
    // PatternLevelCritical всегда блокирует операцию
    // Используется для паттернов, представляющих немедленную угрозу безопасности (например, загрязнение прототипа)
    PatternLevelCritical PatternLevel = iota

    // PatternLevelWarning блокирует в строгом режиме, записывает предупреждение в мягком режиме
    // Используется для паттернов, которые могут указывать на злонамеренность, но имеют легитимное применение
    PatternLevelWarning

    // PatternLevelInfo только записывает в лог, никогда не блокирует
    // Используется для целей аудита/отслеживания без прерывания операций
    PatternLevelInfo
)

Метод String

go
func (pl PatternLevel) String() string

Возвращает строковое представление PatternLevel.


Встроенные опасные паттерны

Паттерны по умолчанию

Внутренний API

Список встроенных паттернов управляется внутренними функциями и больше не экспортируется как публичный API. Пользовательские паттерны можно управлять через поле AdditionalDangerousPatterns в Config.

Ниже приведён список встроенных опасных паттернов, все уровня Critical:

ПаттернНазваниеКатегория
__proto__prototype pollutionЗагрязнение прототипа
constructor[constructor accessДоступ к конструктору
prototype.prototype manipulationМанипуляция прототипом
<scriptscript tag injectionHTML-инъекция
<iframeiframe injectionHTML-инъекция
<objectobject injectionHTML-инъекция
<embedembed injectionHTML-инъекция
<svgsvg injectionHTML-инъекция
javascript:javascript protocolИнъекция протокола
vbscript:vbscript protocolИнъекция протокола
eval(dynamic code executionВыполнение кода
setTimeout(timer manipulationМанипуляция таймерами
setInterval(interval manipulationМанипуляция интервалами
require(code injectionИнъекция кода
new function(dynamic function creationСоздание динамических функций
document.cookiecookie accessДоступ к DOM
window.locationredirect manipulationМанипуляция перенаправлением
innerhtmlDOM manipulationМанипуляция DOM
onerror, onload, onclick, onmouseover, onfocusevent handler injectionИнъекция обработчиков событий
fromcharcode(character encoding bypassОбход кодировки
atob(base64 decodingДекодирование base64
expression(CSS expression injectionCSS-инъекция
__defineGetter__getter definitionЗагрязнение прототипа
__defineSetter__setter definitionЗагрязнение прототипа

Ключевые паттерны

Внутренний API

GetCriticalPatterns стал внутренней функцией и больше не экспортируется как публичный API. Ключевые паттерны (__proto__, constructor[, prototype.) всегда проверяются принудительно и не могут быть отключены.

Следующие ключевые паттерны всегда полностью сканируются независимо от размера JSON:

ПаттернОписание
__proto__prototype pollution
constructor[constructor access
prototype.prototype manipulation

Методы регистрации паттернов

Опасные паттерны настраиваются через структуру Config, а не через глобальные функции регистрации.

Config.AddDangerousPattern

Сигнатура: func (c *Config) AddDangerousPattern(pattern DangerousPattern)

Добавление пользовательского опасного паттерна в конфигурацию.

go
cfg := json.DefaultConfig()
cfg.AddDangerousPattern(json.DangerousPattern{
    Pattern: "malicious_keyword",
    Name:    "Пользовательский опасный паттерн",
    Level:   json.PatternLevelCritical,
})

processor, err := json.New(cfg)
if err != nil {
    panic(err)
}
defer processor.Close()

Config.AdditionalDangerousPatterns

Также можно напрямую установить поле Config.AdditionalDangerousPatterns:

go
cfg := json.DefaultConfig()
cfg.AdditionalDangerousPatterns = []json.DangerousPattern{
    {Pattern: "eval(", Name: "eval-call", Level: json.PatternLevelCritical},
    {Pattern: "exec(", Name: "exec-call", Level: json.PatternLevelWarning},
}

Методы конфигурации Config

AddDangerousPattern

Добавление паттерна безопасности в конфигурацию.

go
func (c *Config) AddDangerousPattern(pattern DangerousPattern)
go
cfg := json.DefaultConfig()
cfg.AddDangerousPattern(json.DangerousPattern{
    Pattern: "custom_dangerous_string",
    Name:    "Пользовательская опасная строка",
    Level:   json.PatternLevelWarning,
})

Поля конфигурации

go
type Config struct {
    // ... другие поля ...

    // AdditionalDangerousPatterns добавляет паттерны безопасности помимо паттернов по умолчанию
    AdditionalDangerousPatterns []DangerousPattern

    // DisableDefaultPatterns отключает встроенные паттерны безопасности по умолчанию (кроме ключевых)
    // При значении true используются только AdditionalDangerousPatterns
    // Примечание: ключевые паттерны (__proto__, constructor[, prototype.) всегда применяются принудительно и не могут быть отключены
    DisableDefaultPatterns bool
}

Глобальная регистрация паттернов

Помимо настройки паттернов на уровне экземпляра через Config, можно управлять глобальным реестром паттернов через функции уровня пакета. Паттерны в глобальном реестре действуют во всех экземплярах Processor.

RegisterDangerousPattern

Сигнатура: func RegisterDangerousPattern(pattern DangerousPattern)

Добавление пользовательского опасного паттерна в глобальный реестр. Зарегистрированные паттерны действуют во всех экземплярах Processor.

go
json.RegisterDangerousPattern(json.DangerousPattern{
    Pattern: "malicious_keyword",
    Name:    "Пользовательский опасный паттерн",
    Level:   json.PatternLevelCritical,
})

UnregisterDangerousPattern

Сигнатура: func UnregisterDangerousPattern(pattern string)

Удаление указанного паттерна из глобального реестра.

go
json.UnregisterDangerousPattern("malicious_keyword")

ListDangerousPatterns

Сигнатура: func ListDangerousPatterns() []DangerousPattern

Возвращает все пользовательские паттерны из глобального реестра.

go
patterns := json.ListDangerousPatterns()
for _, p := range patterns {
    fmt.Printf("Паттерн: %s, Имя: %s, Уровень: %s\n", p.Pattern, p.Name, p.Level)
}

Глобальные паттерны vs паттерны Config

  • Глобальные паттерны (RegisterDangerousPattern): разделяются всеми экземплярами Processor, подходят для политик безопасности на уровне приложения
  • Паттерны Config (Config.AddDangerousPattern): влияют только на Processor, использующий данный Config, подходят для настройки на уровне экземпляра

Полные примеры

Пользовательская политика безопасности

go
package main

import (
    "fmt"
    "github.com/cybergodev/json"
)

func main() {
    // Способ 1: через поле конфигурации
    cfg := json.DefaultConfig()
    cfg.AdditionalDangerousPatterns = []json.DangerousPattern{
        {Pattern: "company_secret", Name: "Корпоративная конфиденциальная информация", Level: json.PatternLevelCritical},
    }

    // Способ 2: через метод конфигурации
    cfg.AddDangerousPattern(json.DangerousPattern{
        Pattern: "internal_api",
        Name:    "Ссылка на внутренний API",
        Level:   json.PatternLevelWarning,
    })

    p, err := json.New(cfg)
    if err != nil {
        panic(err)
    }
    defer p.Close()

    // Тестирование обнаружения опасных паттернов
    _, err = p.Get(`{"data": "company_secret_info"}`, "data")
    if err != nil {
        fmt.Println("Обнаружен опасный паттерн:", err)
    }

    // Просмотр зарегистрированных паттернов
    fmt.Printf("Количество пользовательских паттернов: %d\n", len(cfg.AdditionalDangerousPatterns))
}

Отключение паттернов по умолчанию

go
cfg := json.DefaultConfig()

// Отключение встроенных паттернов по умолчанию (кроме ключевых), использование только пользовательских паттернов
// Примечание: ключевые паттерны (__proto__, constructor[, prototype.) всегда применяются принудительно
cfg.DisableDefaultPatterns = true

// Добавление пользовательских паттернов
cfg.AddDangerousPattern(json.DangerousPattern{
    Pattern: "xss_payload",
    Name:    "Нагрузка XSS-атаки",
    Level:   json.PatternLevelCritical,
})

p, err := json.New(cfg)
if err != nil {
    panic(err)
}
defer p.Close()

Обработка паттернов по уровню

go
// Регистрация паттернов разных уровней
cfg := json.DefaultConfig()
cfg.AddDangerousPattern(json.DangerousPattern{
    Pattern: "suspicious_but_allowed",
    Name:    "Подозрительно, но разрешено",
    Level:   json.PatternLevelInfo, // Только запись в лог, без блокировки
})

// Просмотр зарегистрированных пользовательских паттернов
for _, p := range cfg.AdditionalDangerousPatterns {
    fmt.Printf("Паттерн: %s, Имя: %s, Уровень: %s\n", p.Pattern, p.Name, p.Level)
}

Стратегия сканирования безопасности

Малый JSON (< 4 КБ)

Всегда выполняется полное сканирование безопасности с последовательной проверкой всех опасных паттернов.

Крупный JSON (≥ 4 КБ)

Применяется многоуровневое оптимизированное сканирование с гарантией 100% покрытия (без слепых зон выборки):

  • Ключевые паттерны (__proto__, constructor[, prototype.) всегда полностью сканируются
  • Сначала выполняется проверка индикаторных символов: если опасных символов нет — быстрый пропуск
  • Отслеживается плотность подозрительных символов: при высокой плотности выполняется полный регрессионный разворот сканирования, чтобы злоумышленник не мог спрятать вредоносное содержимое в плотных областях
  • Остальные паттерны сканируются скользящим окном 32 КБ (с перекрытием), что исключает пропуск паттернов на границах окон

Смотрите также