- PVSM.RU - https://www.pvsm.ru -
Процесс сигнатурного анализа кода в нашем проекте PT Application Inspector [1] разбит на следующие этапы:
О первых двух этапах было рассказано в предыдущих статьях "Теория и практика парсинга исходников с помощью ANTLR и Roslyn [2]" и "Обработка древовидных структур и унифицированное AST [3]". Данная статья посвящена третьему этапу, а именно: различным способам описания шаблонов, разработке специализированного языка (DSL) для их описания, а также примерам шаблонов на этом языке.
Шаблоны можно записывать в ручную прямо в коде. Для этого не требуется разрабатывать парсер. Этот способ не подходит для не разработчиков, зато может использоваться для написания юнит-тестов. Также для записи новых шаблонов требуется перекомпиляция всей программы.
Части сопоставляемого AST можно непосредственно сохранять и загружать из JSON или других форматов. При таком подходе шаблоны можно будет загружать извне, однако синтаксис будет громоздким и не подойдет для редактирования пользователем. Однако этот способ можно использовать для сериализации древовидных структур. (О способах сериализации древовидных структур в .NET и их обходе будет рассказано в следующей статье.)
Третий подход заключается в разработке специального предметно-ориентированного языка, который можно было бы легко редактировать, который был бы лаконичным, но при этом обладал достаточной выразительной мощностью для описания существующих и будущих шаблонов. Недостатком такого подхода является необходимость разработки синтаксиса и парсера для него.
Как уже говорилось в первой статье, не все шаблоны можно просто и удобно описать с помощью регулярных выражений. DSL является смесью регулярных выражений и частоиспользуемых конструкций из популярных языков программирования. Кроме того, данный язык предназначается для конкретной предметной области и не предполагается, что он будет использоваться в качестве какого-либо стандарта.
Во второй статье цикла мы говорили, что основными конструкциями в императивных языках программирования являются примитивные типы (literals), выражения (expressions) и инструкции (statements). При разработке DSL мы сделали все так же. Примеры выражений:
expr(args);
вызов метода;Id expr = expr
; инициализация переменной;expr + expr
; конкатенация;new Id(args)
; создание объекта;expr[expr]
; обращение по индексу или ключу.Инструкции создаются путем добавления точки с запятой в конец выражения.
Литералами же являются примитивные типы, такие как:
Эти литералы позволяют описывать простые конструкции, однако с помощью них нельзя, например, описывать диапазоны чисел, регулярные выражения. Для поддержки таких более сложных случаев были введены расширенные конструкции (PatternStatement, PatternExpression, PatternLiteral). Такие конструкции обособляются специальными скобками <[
и ]>
. Подобный синтаксис был заимствован из Nemerle [24] (в нем такие скобки используются для квазицитирования, т. е. для преобразования кода внутри них в AST Nemerle).
Примеры поддерживаемых расширенных конструкций представлены в списке ниже. Для некоторых также конструкций предусмотрен синтаксический сахар, позволяющий сократить запись:
<[]>
; оператор расширенного выражения (например, <[md5|sha1]> или <[0..2048]>);#
или <[expr]>`; любое Expression;...
или <[args]>
; произвольное количество любых аргументов;(expr.)?expr
; эквивалентно expr.expr
или просто expr
;<[~]>expr
— отрицание условия;expr (<[||]> expr)*
— объединение нескольких условий (ИЛИ);Comment: "regex"
— поиск по комментариям.
(#.)?<[(?i)password(?-i)]> = <["w*"]>
#
; любое выражение, может отсутствовать;<[(?i)password(?-i)]>
; регулярное выражение типа Id, может быть записано в любом регистре;<["w*"]>
; регулярное выражение типа String;
new Random(...)
Уязвимость заключается в использовании небезопасного алгоритма генерации случайных чисел. Пока что такие случаи отслеживаются с помощью поиска конструктора стандартного класса Random
.
Configure.<[(?i)^write$]>("debug", <[1..9]>)
<[(?i)^write$]>
; регулярное выражение типа ID, не зависит от регистра и определяет только точные вхождения; ("debug", <[1..9]>)
; аргументы функции;<[1..9]>
; диапазон целых чисел от 1 до 9.new AllowAllHostnameVerifier(...) <[||]> SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
.
Использование "логического ИЛИ" для целых синтаксических конструкций.
Comment: <[ "(?i)password(?-i)s*=" ]>
Поиск комментариев в исходном коде. Причем в C#, Java, PHP, как известно, однострочные комментарии начинаются с двойного слэша //
, а в SQL-подобных языках — с двойного дефиса --
.
<["(?i)selectsw*"]> + <[~"w*"]>
Простая SQL инъекция: конкатенация любой строки, начинающейся с select и не строковым выражением в правой части.
session_set_cookie_params(#,#,#)
Установка куки без флага защищенности, который задается в четвертом аргументе.
try {...} catch { }
Пустой блок обработки исключений. В C# модуль будет находить такой код:
try
{
}
catch
{
}
В T-SQL такой:
BEGIN TRY
SELECT 1/0 AS DivideByZero
END TRY
BEGIN CATCH
END CATCH
А в PL/SQL такой:
PROCEDURE empty_default_exception_handler IS
BEGIN
INSERT INTO table1 VALUES(1, 2, 3, 4);
COMMIT;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
Cookie <[@cookie]> = new Cookie(...);
...
~<[@cookie]>.setSecure(true);
...
response.addCookie(<[@cookie]>);
Добавление куки без установленного флага защищенности. Несмотря на то что данный шаблон правильнее реализовывать в taint-анализе, его удалось реализовать и с помощью более примитивного алгоритма сопоставления. В нем используется прикрепленная переменная @cookie
, отрицание выражения и произвольное количество утверждений.
<[@cursor]> = DBMS_SQL.OPEN_CURSOR;
...
<[~]>DBMS_SQL.CLOSE_CURSOR(<[@cursor]>);
declare_cursor(<[@cursor]>);
...
<[~]>deallocate(<[@cursor]>);
Незакрытый курсор потенциально может эксплуатироваться менее привилегированным пользователем.
В T-SQL будет находиться такой код:
DECLARE Employee_Cursor CURSOR FOR
SELECT EmployeeID, Title FROM AdventureWorks2012.HumanResources.Employee;
OPEN Employee_Cursor;
FETCH NEXT FROM Employee_Cursor;
WHILE @@FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM Employee_Cursor;
END;
--DEALLOCATE Employee_Cursor; is missing
GO
grant_all(...)
Данный недостаток чреват тем, что пользователю может быть выдано больше привилегий, чем это требуется.
Будет находиться такой код:
GRANT ALL ON employees TO john_doe;
Для демонстрации работы нашего модуля мы подготовили видео, в котором показан процесс поиска определенных шаблонов в коде на различных языках программирования (C#, Java, PHP) в нашем продукте PT Application Inspector. Демонстрируется также корректная обработка синтаксических ошибок, которая была затронута в первой [2] статье нашей серии.
В следующих статьях мы расскажем:
Автор: Positive Technologies
Источник [25]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/java/120833
Ссылки в тексте:
[1] PT Application Inspector: http://www.ptsecurity.ru/products/ai/
[2] Теория и практика парсинга исходников с помощью ANTLR и Roslyn: https://habrahabr.ru/company/pt/blog/210772/
[3] Обработка древовидных структур и унифицированное AST: https://habrahabr.ru/company/pt/blog/210060/
[4] Image: https://habrahabr.ru/company/pt/blog/300946/
[5] Способы описания шаблонов: #patterns-declaration-types
[6] Hardcoded: #hardcoded
[7] JSON, XML или другой язык разметки: #json-xml
[8] Собственный язык описания шаблонов: #dsl
[9] Целесообразность: #expediency
[10] Синтаксис: #dsl-syntax
[11] Примеры шаблонов: #pattern-samples
[12] Жестко заданный пароль (все языки): #hardcoded-password
[13] Слабый генератор случайных чисел (C#, Java): #weak-random-number-generator
[14] Утечка отладочной информации (PHP): #debug-information-leak
[15] Небезопасное SSL соединение (Java): #insecure-ssl-connection
[16] Пароль в комментарии (все языки): #password-in-comment
[17] SQL-инъекция (C#, Java, PHP): #sql-injection
[18] Куки без атрибута безопасности (PHP): #cookie-without-secure-attribute
[19] Пустой блок обработки исключения (все языки): #empty-try-catch-block
[20] Небезопасный куки (Java): #insecure-cookie
[21] Перехват незакрытого курсора (PL/SQL, T-SQL): #cursor-snarfing
[22] Чрезмерно расширенные полномочия (PL/SQL, T-SQL): #overly-broad-grant
[23] Заключение: #conclusion
[24] Nemerle: https://ru.wikipedia.org/wiki/Nemerle
[25] Источник: https://habrahabr.ru/post/300946/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.