Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
safetext — Библиотека Go для безопасной генерации YAML и shell-команд, использующая синтаксически-зависимые шаблоны для обнаружения и блокировки атак с внедрением кода с помощью аннотаций для доверенных данных. | Kitploit
Инструменты/GitHubGitHub/google/safetext
Оборонительные ИнструментыСкриптинг и автоматизацияВеб-безопасностьDevSecOps
GitHubgoogle/safetext

safetext

Библиотека Go для безопасной генерации YAML и shell-команд, использующая синтаксически-зависимые шаблоны для обнаружения и блокировки атак с внедрением кода с помощью аннотаций для доверенных данных.

Репозиторий
1509176 месяцев назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

safetext

Это неофициальный продукт Google, не поддерживаемый официально.

Библиотеки, безопасные по построению, для создания таких форматов, как YAML, заменяющие не учитывающие синтаксис библиотеки вроде text/template и sprintf, которые подвержены риску инъекционных уязвимостей.

Пример использования

Поскольку text/template не учитывает синтаксис создаваемых форматов, он не обеспечивает никакой защиты от инъекционных уязвимостей.

Рассмотрим следующую функцию produceConfig, которая использует text/template для генерации YAML:

package main

import (
        "bytes"
        "fmt"
        "text/template"
)

func produceConfig(params any) (error, string) {
        tmpl, _ := template.New("test").Parse("{ hello: {{ .addressee }} }")

        var buf bytes.Buffer
        err := tmpl.Execute(&buf, params)
        if err != nil {
                return err, ""
        }

        return nil, buf.String()
}

func main() {
        goodReplacements := map[string]interface{}{
                "addressee": "safe",
        }

        err, config := produceConfig(goodReplacements)

        if err == nil {
                fmt.Println(config)
        } else {
                fmt.Printf("Error: %v\n", err)
        }

        badReplacements := map[string]interface{}{
                "addressee": "world, oops: true",
        }

        err, config = produceConfig(badReplacements)

        if err == nil {
                fmt.Println(config)
        } else {
                fmt.Printf("Error: %v\n", err)
        }
}

Эта программа демонстрирует, как вредоносный ввод addressee может вызвать инъекцию новых YAML-ключей в результат выполнения шаблона.

При использовании text/template в этом случае не возникнет никаких ошибок, и вывод программы будет следующим:

{ hello: safe }
{ hello: world, oops: true }

Если же вместо этого перейти с text/templateto safetext/yamltemplate, то инъекция была бы предотвращена, а вывод был бы таким:

{ hello: safe }
Error: YAML Injection Detected

Инструкции по заменам text/template

Обнаружение инъекций автоматически применяется при доступе к полям входных данных.

  • Обнаружение инъекций автоматически применяется при доступе к полям входных данных.

    {{ RetrieveUntrustedData | ApplyInjectionDetection }}
    
  • Логику обнаружения инъекций можно отключить для определённых полей, применив аннотацию StructuralData:

    {{ (StructuralData .x) }}
    
  • Аннотация StructuralData также необходима при передаче входных данных функции, где эти данные не должны изменяться, например, при выполнении какого-либо поиска:

    name: {{ readFile (StructuralData .pathToName) | ApplyInjectionDetection }}
    
  • Рекомендуется в полной мере использовать возможности text/template, такие как условные выражения, циклы range и т.д., чтобы по возможности избегать аннотации StructuralData. Например, вместо:

    properties:
        {{ (StructuralData .PropertiesYaml) }}
    

    Рассмотрите:

    properties:{{ range .Properties }}
        - {{ . }}{{ end }}
    

yamltemplate

Назначение yamltemplate — гарантировать, что по умолчанию ни одна строка во входных данных не повлияет на структуру результирующего YAML (только на значения).

  • Например, приведённый ниже шаблон будет совместим с yamltemplate как есть, автоматически предотвращая любые инъекции из входных данных Name:

    name: {{.Name}}
    
  • Однако любые узлы шаблона, которые должны изменять результирующую структуру YAML, например, вставка произвольной YAML-конфигурации, должны быть явно аннотированы как StructuralData:

    config: {{ (StructuralData .Config) }}
    
  • Ещё один случай, когда требуется аннотация StructuralData, — это необходимость включить полную карту (map) в структуру YAML. Использование только StructuralData может позволить инъекциям пройти через ключ, поэтому здесь нужен дополнительный уровень проверки:

    labels:
    {{- range $key, $value := .Labels }}
        {{ (StructuralData $key | MapKey) }}: {{ $value }}
    {{- end }}
    

    Соответствующая сторона на Go может выглядеть так:

    func mapKeyFunc(data any) (string, error) {
        if v, ok := data.(string); ok {
            matched, err := regexp.MatchString(`^[a-zA-Z0-9/\-.]+$`, v)
            if err != nil {
                return "", err
            }
            if !matched {
                return "", fmt.Errorf("invalid characters in the key: %v", v)
            }
            return v, nil
        }
    
        return "", errors.New("invalid input")
    
    } ...
    
    tmp:= template.New("something")
    tmp.Funcs(map[string]any{"MapKey":mapKeyFunc})
    tmpl := template.Must(tmp.Parse(yamlTemplate))
    
  • Вы можете комбинировать yamltemplate с shprintf. Рассмотрим следующий cloud-init YAML-шаблон:

    ---
    write_files:
    - path: /etc/nginx/refresh.sh
      owner: root:root
      permissions: 0755  # Don't forget the 0 (you are probably using octal...)
      content: |
        #!/bin/bash
        set -euo pipefail
    
        {{ shprintf `curl %s > /tmp/something` .userInput }}
    

    При вычислении этого шаблона с помощью safetext/yamltemplate будут предотвращены как инъекции shell-команд, так и YAML-инъекции.

    Для этого нужно настроить сторону Go следующим образом:

    tmp:= addons.WithShsprintf(template.New("something"))
    tmpl := template.Must(tmp.Parse(yamlTemplate))
    

Неподдерживаемые случаи использования yamltemplate

  • YAML с дублирующимися ключами. Дублирующиеся ключи — это нестандартный YAML, и они не поддерживаются этой библиотекой. Пожалуйста, отрефакторите ваш YAML-шаблон, чтобы удалить дублирующиеся ключи. Например:

    - project:
       members: member-a
       members: member-b
    

    На:

    - project:
      members: member-b
    

shtemplate

shtemplate предназначен для генерации shell-скриптов с гарантией того, что ни одна строка входных данных не сможет внедрить новые команды или флаги без явной аннотации.

  • Например, шаблонный скрипт, предназначенный для вывода одной строки, не сможет отобразиться, если эта строка внедряет новую команду `./evil`:

    echo "{{ .addressee }}"
    
  • Чтобы явно разрешить входной строке содержать новые команды, не входящие в строку шаблона, можно использовать аннотацию StructuralData:

    {{ (StructuralData .commands) }}
    
  • Флаги (аргументы, начинающиеся с -) также запрещены по умолчанию. Например, следующий шаблон не сможет отобразиться, если Filename равен --interactive:

    git add {{ .Filename }}
    
  • Чтобы явно разрешить входной строке, передаваемой в качестве аргумента команды, быть флагом, можно использовать аннотацию AllowFlags:

    git add {{ (AllowFlags .FilenameOrGitAddFlag) }}
    
  • Несколько аргументов из одной входной строки также запрещены по умолчанию. Вместо этого данную конструкцию следует реализовывать с помощью массива и выражения range:

    ls {{ range .Paths }}{{.}} {{end}}
    

Неподдерживаемые случаи использования замен text/template

  • Логика экранирования вне системы шаблонов. Вместо этого вы должны встроить логику экранирования в шаблон (например: .UntrustedField | escape).

  • Частичные форматы. Библиотеки предназначены для генерации полных файлов. Если вы генерируете сегменты, а затем склеиваете их вместе, вам следует перенести эту логику в саму систему шаблонов (используя конструкции вроде if или range).

  • Функции с побочными эффектами. Библиотеки работают путём многократного выполнения шаблонов, поэтому если вы регистрируете функции с побочными эффектами, это может вызвать неожиданное поведение (например: id: {{ AllocateID }}).

Скачать инструмент