Как SAST устраняет 10 самых распространенных уязвимостей по версии OWASP

Статический анализ кода для обеспечения безопасности: как SAST устраняет 10 наиболее распространенных уязвимостей по версии OWASP.

Уязвимости в системе безопасности проще предотвратить, чем исправить. Уязвимость SQL-инъекции, обнаруженная при проверке кода, устраняется за считанные минуты. Та же самая уязвимость, обнаруженная после взлома, требует недель реагирования на инцидент, расследования со стороны регулирующих органов и устранения последствий, плюс все данные, которые были украдены за это время. Статический анализ кода — это дисциплина, которая выявляет эти проблемы до запуска кода, изучая структуру исходного кода, потоки данных и закономерности на основе известных сигнатур уязвимостей. Применяемый систематически, он превращает безопасность из реактивной практики в неотъемлемое свойство процесса разработки.

OWASP Top 10 — это авторитетный каталог наиболее критических угроз безопасности веб-приложений, обновляемый проектом Open Web Application Security Project на основе реальных данных об уязвимостях в тысячах приложений. Каждый пункт в списке в той или иной степени может быть обнаружен инструментами статического анализа. В этом руководстве каждая категория OWASP сопоставляется с тем, что может обнаружить статический анализ, показаны уязвимые шаблоны кода и их безопасные эквиваленты, а также объясняется, какие инструменты применяют каждый метод.

Обнаружьте внедрение кода раньше злоумышленников.

SMART TS XL Отслеживает уязвимости в API JavaScript, сервисах Java и бэкэндах COBOL.

Подробнее

Содержание

Что такое статическое тестирование безопасности приложений (SAST)?

Статическое тестирование безопасности приложений (SAST) анализирует исходный код, байт-код или двоичные файлы без выполнения программы. Анализ исследует, как данные проходят через приложение, к каким операциям, чувствительным к безопасности, эти данные достигают, и приводит ли какой-либо путь от внешнего ввода (ввод пользователя, параметры HTTP, содержимое файла, переменные среды) к опасной операции (запрос к базе данных, системная команда, вывод HTML, криптографическая функция) без надлежащей проверки или очистки.

SAST — это один из уровней комплексной программы обеспечения безопасности приложений. Чтобы понять его место, необходимо сравнить его с альтернативными вариантами:

ПодходКогда это работаетЧто оно обнаруживаетЧего в нём не хватает
SAST (статический)Перед выполнением, в исходном кодеУязвимости на уровне кода, схемы внедрения кода, злоупотребления криптографическими функциями, жестко закодированные секреты.Уязвимости, проявляющиеся только во время выполнения, проблемы с конфигурацией при развертывании.
DAST (динамический)В отношении запущенного приложенияПоведение во время выполнения, недостатки аутентификации, проблемы с конфигурацией сервера.Шаблоны на уровне кода, не срабатывающие во время тестирования.
SCA (анализ состава программного обеспечения)О манифестах зависимостейИзвестные уязвимости CVE в библиотеках сторонних разработчиковУязвимости пользовательского кода
IAST (интерактивный)В ходе выполнения тестов с использованием измерительной аппаратуры.Потоки данных во время выполнения с высокой точностьюТребуется запущенное приложение, более медленная обратная связь.

SAST обеспечивает самую раннюю обратную связь: он выполняется на коде, который еще не развернут, в конвейере CI/CD или даже в IDE, еще до того, как уязвимость попадет в тестовую среду. Именно эта ранность является его основной ценностью в плане безопасности.

Какие типы угроз может предотвратить статический анализ кода?

Это один из самых популярных запросов по теме SAST. Прямой ответ:

Статический анализ кода может смягчить угрозы, проявляющиеся в шаблонах исходного кода : уязвимости внедрения (SQL, командные, XSS), злоупотребление криптографическими функциями, жестко закодированные учетные данные, небезопасные реализации аутентификации, нарушения контроля доступа в логике кода и сбои целостности данных. Он не может смягчить угрозы, возникающие из-за конфигурации во время выполнения, топологии сети или настройки инфраструктуры; для таких угроз требуются DAST, тестирование на проникновение или сканирование безопасности инфраструктуры.

Статический анализ против динамического анализа для анализа покрытия OWASP.

Динамический анализ (DAST) и статический анализ (SAST) выявляют разные подмножества уязвимостей OWASP. Ни один из них не охватывает все аспекты. Руководство по тестированию веб-безопасности OWASP (WSTG) — это методологическая основа для динамического тестирования; инструменты SAST, такие как CodeQL, Semgrep и SonarQube, предназначены для анализа исходного кода.

Категория OWASP Top 10Покрытие SASTПокрытие DAST
Сломанный контроль доступаЧастичные пробелы в логике кода.Качественное тестирование поведения во время выполнения.
Криптографические сбоиНадежное обнаружение с помощью алгоритмаСлабый, трудноразличимый снаружи
ВпрыскТщательный, анализ на наличие примесейИнтенсивные, активные испытания полезной нагрузки
Небезопасный дизайнЧастичное обнаружение шаблоновСлабый, требует знаний в области проектирования.
Неправильная настройка безопасностиЧастичная конфигурация в коде.Надежное тестирование в реальных условиях.
Уязвимые компонентыСлабый, SCA лучшеСлабый, SCA лучше
Ошибки аутентификацииЧастичные, жестко закодированные учетные данные, слабые шаблоныСтрогое тестирование сессий и аутентификации.
Сбои целостности данныхЧастичные шаблоны десериализацииСлабый, труднообнаружимый внешне.
Сбои регистрацииЧастично отсутствующие записи в журналеСлабое, труднообнаружимое отсутствие
ССРФНадежный, заражает HTTP-вызовИнтенсивное и активное тестирование запросов.

Вывод: SAST и DAST дополняют друг друга. Для максимального охвата OWASP используйте оба метода. Для команд с ограниченным бюджетом, начинающих с нуля, лучше сначала использовать SAST, поскольку он обеспечивает самую быструю обратную связь от разработчиков и наиболее широкое покрытие внедрения зависимостей.

OWASP Top 10: Что обнаруживает статический анализ и как?

A01, Нарушение контроля доступа

Нарушение контроля доступа — главный риск по OWASP. Статический анализ выявляет проявления на уровне кода: отсутствие проверок авторизации для функций и конечных точек, ссылки на объекты, раскрывающие внутренние идентификаторы без проверки, и жестко закодированные назначения ролей, обходящие предусмотренную структуру разрешений.

Что обнаруживает статический анализ: Методы, обрабатывающие конфиденциальные операции без соответствующей проверки авторизации; прямые ссылки на объекты, где идентификатор объекта берется из пользовательского ввода без проверки доступа; шаблоны принудительного просмотра, где проверяется состояние аутентификации, но не проверяется принадлежность объекта.

Ява

// Vulnerable: no ownership check -- any authenticated user can access any order
@GetMapping("/orders/{orderId}")
public Order getOrder(@PathVariable Long orderId) {
    return orderRepository.findById(orderId).orElseThrow();
}

// Secure: verify the order belongs to the requesting user
@GetMapping("/orders/{orderId}")
public Order getOrder(@PathVariable Long orderId,
                      @AuthenticationPrincipal UserDetails user) {
    Order order = orderRepository.findById(orderId).orElseThrow();
    if (!order.getOwnerId().equals(user.getUserId())) {
        throw new AccessDeniedException("Order does not belong to requesting user");
    }
    return order;
}

Что не может выявить статический анализ: сбои контроля доступа во время выполнения, когда логика верна, но данные, используемые для принятия решения, скомпрометированы. Для таких случаев необходимы DAST и тестирование на проникновение.

A02, Криптографические сбои

Слабая криптография надежно обнаруживается с помощью статического анализа, поскольку уязвимые шаблоны, такие как MD5, SHA-1, DES, режим ECB, жестко закодированные ключи, лексически идентифицируются в исходном коде.

питон

# Vulnerable: MD5 for password hashing (broken algorithm)
import hashlib
password_hash = hashlib.md5(password.encode()).hexdigest()

# Vulnerable: hardcoded encryption key
KEY = b"mysecretkey12345"
cipher = AES.new(KEY, AES.MODE_ECB)  # ECB mode also vulnerable

# Secure: bcrypt for passwords, environment-sourced keys
import bcrypt, os
password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))

# Secure: AES-GCM with environment-sourced key
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
key = os.environ["ENCRYPTION_KEY"].encode()
aesgcm = AESGCM(key)

Правила статического анализа: MD5/SHA-1 для обеспечения безопасности, режим DES/3DES/RC4/ECB, жестко закодированные криптографические ключи и секреты, HTTP вместо HTTPS для передачи конфиденциальных данных, а также отключенная проверка сертификатов.verify=False в запросах Python, setHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER) на Java).

А03, Инъекция

Внедрение вредоносного ПО, SQL-запросы, команды ОС, LDAP, XSS-атаки, внедрение шаблонов — это категории, где межпроцедурный анализ заражения данных приносит наибольшую пользу. Уязвимость требует отслеживания ненадежных входных данных от источника через вызовы функций к опасному приемнику.

Javascript

// Vulnerable: direct string interpolation in SQL (SQL injection)
app.get('/users', async (req, res) => {
    const name = req.query.name;
    const result = await db.query(`SELECT * FROM users WHERE name = '${name}'`);
    res.json(result.rows);
});

// Secure: parameterized query
app.get('/users', async (req, res) => {
    const name = req.query.name;
    const result = await db.query('SELECT * FROM users WHERE name = $1', [name]);
    res.json(result.rows);
});

PHP

// Vulnerable: unescaped output (XSS)
echo "Welcome, " . $_GET['username'];

// Secure: context-appropriate escaping
echo "Welcome, " . htmlspecialchars($_GET['username'], ENT_QUOTES, 'UTF-8');

острый

// Vulnerable: command injection in C#
var process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c " + userInput;
process.Start();

// Secure: avoid shell interpretation, validate and whitelist inputs
var allowedCommands = new HashSet<string> { "report", "export" };
if (!allowedCommands.Contains(userInput))
    throw new ArgumentException("Invalid command");

Инструменты, выполняющие межпроцедурный анализ заражения для инъекций: CodeQL (наиболее точный), Semgrep с режимом проверки заражения, Snyk Code, SonarQube с правилами безопасности.

A04, Небезопасный дизайн

Небезопасная архитектура — самая сложная категория OWASP для статического анализа, поскольку она касается архитектурных решений, а не шаблонов кода. Статический анализ может выявить следующие симптомы:

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

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

A05, Неправильная настройка безопасности

К ошибкам в настройке безопасности в коде относятся: отключенные функции безопасности, разрешающие заголовки CORS, отсутствующие заголовки ответа безопасности, включенный режим отладки в производственной среде и подробные сообщения об ошибках, отображающие трассировку стека.

питон

# Vulnerable: Flask debug mode enables interactive debugger in production
app = Flask(__name__)
app.run(debug=True)  # exposes console access if error occurs

# Vulnerable: overly permissive CORS
from flask_cors import CORS
CORS(app, origins="*")  # allows any origin

# Secure: environment-controlled debug, restricted CORS
import os
debug_mode = os.environ.get("FLASK_DEBUG", "false").lower() == "true"
CORS(app, origins=os.environ.get("ALLOWED_ORIGINS", "").split(","))
app.run(debug=debug_mode)

Флаг правил статического анализа: режим отладки установлен на True в источнике, использование символов подстановки CORS, отсутствие заголовков безопасности в конфигурациях HTTP-ответов, отключенная проверка SSL-сертификатов и учетные данные по умолчанию в конфигурационных файлах.

A06, Уязвимые и устаревшие компоненты

Данная категория в основном рассматривается с помощью анализа состава программного обеспечения (SCA), а не традиционного SAST. Сканирование SCA package.json, pom.xml, requirements.txtи аналогичные данные, полученные из баз данных уязвимостей (Национальная база данных уязвимостей, Консультативная база данных GitHub).

SAST вносит свой вклад, выявляя устаревшее использование API, вызовы библиотечных функций, которые были заменены устаревшими из-за уязвимостей в системе безопасности, или прямое использование уязвимых шаблонов, которые даже в современных библиотеках больше не рекомендуются.

Инструменты, специально предназначенные для A06: npm audit, pip-audit, snyk test, OWASP Dependency-Check, GitHub Dependabot и Mend (ранее WhiteSource).

A07, Сбои идентификации и аутентификации

Статический анализ выявляет антипаттерны аутентификации на уровне кода: жестко закодированные пароли, слабая проверка паролей, токены сессии, сгенерированные с использованием некриптографической случайности, отсутствие аннулирования сессии при выходе из системы и реализации JWT, которые принимают none алгоритм.

Javascript

// Vulnerable: JWT accepting 'none' algorithm -- allows signature bypass
const decoded = jwt.verify(token, secret, { algorithms: ['HS256', 'none'] });

// Vulnerable: hardcoded admin credentials
if (username === 'admin' && password === 'admin123') {
    grantAccess();
}

// Secure: algorithm whitelist, no hardcoded credentials
const decoded = jwt.verify(token, process.env.JWT_SECRET, {
    algorithms: ['HS256']  // explicit allowlist only
});

острый

// Vulnerable: weak random for session token generation in C#
var sessionToken = new Random().Next().ToString();

// Secure: cryptographically secure random
using var rng = RandomNumberGenerator.Create();
var bytes = new byte[32];
rng.GetBytes(bytes);
var sessionToken = Convert.ToBase64String(bytes);

A08, Сбои в работе программного обеспечения и обеспечении целостности данных

В этой категории рассматриваются небезопасная десериализация и непроверенные обновления программного обеспечения. Статический анализ обнаруживает: Java. ObjectInputStream Десериализация данных из ненадежных источников, Python pickle.loads() на внешних данных, PHP unserialize() с пользовательским вводом и парсерами YAML, использующими небезопасные загрузчики.

питон

# Vulnerable: pickle deserialization of untrusted data
import pickle
data = pickle.loads(request.data)  # arbitrary code execution risk

# Vulnerable: unsafe YAML loader
import yaml
config = yaml.load(user_input)  # yaml.load without Loader is unsafe

# Secure: safe alternatives
import json
data = json.loads(request.data)  # JSON cannot execute code

import yaml
config = yaml.safe_load(user_input)  # safe_load disables arbitrary object creation

A09, Сбои в работе систем регистрации и мониторинга безопасности

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

Что выявляет статический анализ: запись в лог паролей или токенов (запись в лог конфиденциальных данных также является уязвимостью), обработчики исключений, которые молча игнорируют ошибки без записи в лог, и блоки catch, которые записывают в лог необработанное сообщение об исключении (которое может содержать конфиденциальные данные).

Ява

// Vulnerable: swallowed exception, no logging
try {
    authenticateUser(username, password);
} catch (Exception e) {
    // silent failure -- no log, no audit trail
}

// Vulnerable: logging sensitive data
log.info("User logged in with password: " + password);

// Secure: log the event, not the credential
try {
    authenticateUser(username, password);
    auditLog.info("Authentication success for user: {}", username);
} catch (AuthenticationException e) {
    auditLog.warn("Authentication failure for user: {}", username);
    throw e;  // do not swallow
}

A10, Подделка запросов на стороне сервера (SSRF)

SSRF — это веский аргумент в пользу межпроцедурного анализа заражения данных. Уязвимость требует отслеживания пользовательского ввода вплоть до HTTP-запроса, часто через множественные вызовы функций. Инструмент, анализирующий только отдельные функции, не может обнаружить SSRF, если формирование URL-адреса и HTTP-вызов находятся в разных функциях.

питон

# Vulnerable: user-controlled URL in HTTP request (SSRF)
import requests

def fetch_resource(url):
    return requests.get(url).content  # no validation

def api_endpoint(request):
    target = request.json().get("url")    # attacker controls this
    return fetch_resource(target)          # SSRF across function boundary

# Secure: allowlist validation before making the request
from urllib.parse import urlparse

ALLOWED_HOSTS = {"api.internal.example.com", "cdn.example.com"}

def fetch_resource(url: str) -> bytes:
    parsed = urlparse(url)
    if parsed.hostname not in ALLOWED_HOSTS:
        raise ValueError(f"URL host not allowed: {parsed.hostname}")
    return requests.get(url, timeout=5).content

Инструменты статического анализа кода для обеспечения безопасности OWASP

В таблице ниже приведено соответствие основных инструментов SAST категориям OWASP, которые они наиболее эффективно охватывают:

ИнструментОсновные языкиСильные стороны OWASPПодход
КодQLJava, JS/TS, Python, C/C++, Go, RubyA03 Инъекция, A10 SSRF (глубокое загрязнение)Межпроцедурный семантический анализ
Семгреп30 + языкиA03, A02, A07 (режим на основе шаблона + режим обнаружения загрязнения)Сопоставление шаблонов + неглубокая порча
Код СныкаJava, JS/TS, Python, C#A03, A07, A08Анализ загрязнения на основе машинного обучения
SonarQube30 + языкиА02, А03, А05, А07, А09На основе правил + поток данных
галочка30 + языкиПолное покрытие OWASPМежпроцедурное загрязнение
VeracodeJava, .NET, JS, PHPПолное покрытие OWASPАнализ байт-кода и заражения данных
OWASP ZAPЯзыко-независимыйA01, A05, A07 (время выполнения)DAST, динамическое тестирование
SMART TS XLCOBOL, JCL, Java, Python, RPG, SQLМежъязыковая предвзятость, риск зависимостиМежъязыковая структурная + загрязнение

Как SMART TS XL Рассматриваются вопросы безопасности в корпоративных кодовых базах.

Программы обеспечения безопасности предприятий сталкиваются с проблемой, которую не могут решить инструменты SAST, ориентированные на один язык: поверхность атаки охватывает несколько языков. Веб-приложение может принимать ввод пользователя на JavaScript, обрабатывать его на Java, передавать через очередь сообщений в программу на COBOL, которая выполняет SQL-запросы к базе данных DB2. Уязвимость внедрения существует на границе четырех языков. Ни один сканер, работающий с отдельными языками, не видит полного пути заражения.

SMART TS XLАвтора статический анализ кода охватывает все языки в этой цепочке одновременно. Когда ненадежные входные данные поступают из обработчика API JavaScript через службу Java в программу COBOL, которая формирует динамический SQL-запрос, SMART TS XL отслеживает этот путь по всему графу вызовов между языками программирования, используя тот же метод отслеживания ошибок между процедурами, который CodeQL применяет в Java, но применяется одновременно к Java, COBOL и SQL.

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

Функция анализа влияния уязвимости используется в программах по устранению уязвимостей в системе безопасности: при обнаружении уязвимости в компоненте анализ влияния выявляет все остальные компоненты, зависящие от уязвимого компонента, точно определяя масштабы работ по устранению уязвимости до внесения каких-либо изменений в код. Для больших устаревших кодовых баз, где программа на COBOL с уязвимостью в системе безопасности включена в сотни других программ, знание полного масштаба работ по устранению уязвимости до их начала является решающим фактором между управляемым исправлением и каскадным инцидентом.

Для организаций, управляющих модернизация наследия Анализ безопасности устаревшего кода является обязательным условием, а не второстепенным моментом. Миграция уязвимых программ на COBOL в Java приводит к появлению уязвимых программ на Java. SMART TS XLАнализ безопасности, проводимый компанией, гарантирует, что уязвимости будут выявлены и устранены в рамках процесса модернизации, а не обнаружены в мигрированной системе.

Интеграция SAST в жизненный цикл разработки

Статический анализ безопасности наиболее эффективен, когда он выполняется в момент принятия решения, в процессе написания и проверки кода, а не после его развертывания.

В IDE: SonarLint, расширения IDE от Snyk и расширение CodeQL для VS Code отображают обнаруженные уязвимости непосредственно во время написания кода. Устранение уязвимости, связанной с SQL-инъекцией, которая появляется в момент ввода уязвимого шаблона, занимает всего несколько секунд.

В запросах на слияние: интегрированная в GitHub Actions, GitLab CI или Jenkins система SAST запускает каждый запрос на слияние и публикует результаты в виде комментариев к коду непосредственно в процессе проверки. Разработчик видит результат в контексте, вместе с кодом, который его вызвал.

В качестве критерия качества: модель контроля качества SonarQube блокирует слияния при появлении новых критически важных уязвимостей в системе безопасности. Это делает проверку безопасности не необязательной, а структурным требованием процесса слияния.

В плановом порядке: глубокий межпроцедурный анализ, CodeQL, Checkmarx, полные наборы правил Semgrep, обычно слишком медленный для выполнения на уровне отдельных коммитов, но запускается ежедневно или еженедельно в основной ветке, выявляя уязвимости, для обнаружения которых требуется полный анализ графа вызовов.

Многоуровневый подход, быстрые правила на основе шаблонов в IDE и при внесении изменений, глубокий анализ заражения данных в запросах на слияние и ночных сборках, обеспечивают как оперативность, необходимую разработчикам, так и тщательность, требуемую программами безопасности.