Аннотирование C# кода в формате JSON
- Структура файла с аннотациями
- Аннотации для taint-анализа
- Аннотации методов
- Аннотации конструкторов
- Аннотации свойств
- Аннотации параметров
- Схема JSON
- Примеры
Примечание. На данный момент в C# анализаторе поддержаны только аннотации для taint-анализа. В будущем также будут поддержаны аннотации общего назначения.
Способы подключения файла c аннотациями
Подробнее о способе подключения файла аннотаций вы можете узнать в этой документации.
Структура файла с аннотациями
Содержимое файла — JSON-объект, состоящий из трёх обязательных полей: language, version и annotations.
Поле language должно иметь значение 'csharp'. Поле version принимает значение целого типа и задаёт версию механизма. В зависимости от значения файл с разметкой может обрабатываться по-разному. На данный момент поддерживается только одно значение — 1.
Поле annotations — массив объектов "аннотация":
{
"language": "csharp",
"version": 1,
"annotations":
[
{
...
},
{
...
}
]
}
Аннотации могут быть трёх типов:
- аннотации методов;
- аннотации конструкторов;
- аннотации свойств.
Аннотации для taint-анализа
В анализаторе существует ряд аннотаций для taint-анализа. С их помощью можно размечать источники и приёмники заражения. Также существует возможность помечать методы/конструкторы, которые производят валидацию taint-данных. Таким образом, если taint-данные прошли валидацию, то при их попадании в приёмник предупреждения анализатора не будет.
За каждый из видов уязвимостей отвечает отдельное диагностическое правило. На данный момент в анализаторе представлены следующие taint-диагностики:
- V5608 — SQL injection;
- V5609 — Path traversal vulnerability;
- V5610 — XSS vulnerability;
- V5611 — Insecure deserialization vulnerability;
- V5614 — XXE vulnerability;
- V5615 — XEE vulnerability;
- V5616 — Command injection;
- V5618 — Server-side request forgery;
- V5619 — Log injection;
- V5620 — LDAP injection;
- V5622 — XPath injection;
- V5623 — Open redirect vulnerability;
- V5624 — Configuration vulnerability;
- V5626 — ReDoS vulnerability;
- V5627 — NoSQL injection;
- V5628 — Zip Slip vulnerability.
Принцип работы taint-аннотаций
Для каждого из диагностических правил существуют специальные аннотации, которые позволяют разметить приёмники и методы/конструкторы, производящие валидацию.
Что касается источников taint-данных, то они являются общими для всех диагностик. Такие данные также можно разметить с помощью аннотаций.
Примечание. Атрибуты для разметки taint-аннотаций описаны в следующих разделах.
Стоит отметить, что, помимо пользовательских аннотаций, в анализаторе уже имеется ряд taint-аннотаций для различных библиотек. Например, при передаче результата выполнения метода System.Console.ReadLine в конструктор System.Data.SqlClient.SqlCommand возможно возникновение SQL injection. В анализаторе есть аннотации, которые говорят, что System.Console.ReadLine — источник taint-данных, а System.Data.SqlClient.SqlCommand — приёмник, при попадании в который taint-данных может возникнуть SQL injection.
Таким образом, размечая источники taint-данных, анализатор будет учитывать их для уже существующих приёмников и наоборот. Если добавить аннотацию приёмника, то анализатор будет выдавать предупреждение при попадании в него уже размеченных источников taint-данных (например, System.Console.ReadLine).
Аннотации методов
Примечание. Объект аннотации метода должен содержать хотя бы одно опциональное поле.
Объект аннотации метода состоит из следующих полей:
Поле "type"
Обязательное поле. Принимает строку со значением method.
Поле "namespace_name"
Обязательное поле. Принимает строку с именем пространства имён, которое содержит метод.
Поле "type_name"
Обязательное поле. Принимает строку с именем класса, в котором определён метод.
Поле "method_name"
Обязательное поле. Принимает строку с именем метода.
Поле "attributes"
Опциональное поле. Массив строк, который задаёт свойства сущности.
Возможные атрибуты метода
# |
Название атрибута |
Описание атрибута |
---|---|---|
1 |
not_apply_to_child_class |
Аннотация не будет применяться при вызове проаннотированного метода у объекта дочернего класса. |
2 |
caller_is_xml_parser |
Объект, вызывающий метод, является XML-парсером, который может быть уязвим (V5614, V5615). |
Поле "params"
Опциональное поле. Данное поле описано в разделе "Аннотации параметров".
Поле "returns"
Примечание. Объект аннотации возвращаемого значения должен либо содержать поля 'namespace_name' и ' type_name', либо оба поля должны отсутствовать (или иметь значение null). Если оба поля отсутствуют, то при выборе аннотации не будет учитываться тип возвращаемого значения.
Опциональное поле. Объект возвращаемого значения, состоит из следующих полей:
Поле "namespace_name"
Опциональное поле. Принимает строку с именем пространства имён, которое содержит тип возвращаемого значения метода.
Поле "type_name"
Опциональное поле. Принимает строку с именем класса, в котором определён тип возвращаемого значения метода.
Поле "attributes"
Опциональное поле. Массив строк, который задаёт свойства возвращаемого значения метода.
Возможные атрибуты возвращаемого значения
# |
Название атрибута |
Описание атрибута |
---|---|---|
1 |
not_apply_to_child_class |
Аннотация не будет применяться для методов, тип возвращаемого значения которых является дочерним для проаннотированного типа. |
2 |
always_taint |
Метод возвращает taint-данные. |
3 |
transfer_annotations_from_caller |
Если вызывающий объект содержит аннотацию, она будет перенесена на возвращаемое значение метода. |
Аннотации конструкторов
Примечание. Объект аннотации конструктора должен содержать хотя бы одно опциональное поле.
Объект аннотации конструктора состоит из следующих полей:
Поле "type"
Обязательное поле. Принимает строку со значением ctor.
Поле "namespace_name"
Обязательное поле. Принимает строку с именем пространства имён, которое содержит конструктор.
Поле "type_name"
Обязательное поле. Принимает строку с именем класса, в котором определён конструктор.
Поле "attributes"
Опциональное поле. Массив строк, который задаёт свойства сущности.
Возможные атрибуты конструкторов
# |
Название атрибута |
Описание атрибута |
---|---|---|
1 |
not_apply_to_child_class |
Аннотация не будет применяться для дочерних реализаций проаннотированного конструктора. |
2 |
create_taint_object |
Созданный конструктором объект — taint. |
Поле "params"
Опциональное поле. Данное поле описано в разделе "Аннотации параметров".
Аннотации свойств
Объект аннотации свойства состоит из следующих полей:
Поле "type"
Обязательное поле. Принимает строку со значением property.
Поле "namespace_name"
Обязательное поле. Принимает строку с именем пространства имён, которое содержит свойство.
Поле "type_name"
Обязательное поле. Принимает строку с именем класса, в котором определено свойство.
Поле "attributes"
Опциональное поле. Массив строк, который задаёт свойства сущности.
Возможные атрибуты свойств
Примечание. К каждому из атрибутов taint-приёмников прикреплена ссылка на соответствующую диагностику.
# |
Название атрибута |
Описание атрибута |
---|---|---|
1 |
not_apply_to_child_class |
Аннотация не будет применяться при обращении к проаннотированному свойству у объекта дочернего класса. |
2 |
transfer_annotation_to_return_value |
Если на вызывающем объекте есть аннотация, то она будет перенесена на возвращаемое значение. |
3 |
transfer_annotation_to_caller |
Если свойству присваивается значение, то аннотации этого значения будут перенесены на вызывающий объект свойства. |
4 |
return_taint |
Свойство возвращает taint-данные. |
5 |
sql_injection_target |
Запись в это свойство заражённых данных приводит к SQL Injection (V5608). |
6 |
path_traversal_target |
Запись в это свойство заражённых данных приводит к Path Traversal (V5609). |
7 |
xss_injection_target |
Запись в это свойство заражённых данных приводит к XSS Injection (V5610). |
8 |
insecure_deserialization_target |
Запись в это свойство заражённых данных приводит к Insecure Deserialization (V5611). |
9 |
command_injection_target |
Запись в это свойство заражённых данных приводит к Command Injection (V5616). |
10 |
ssrf_target |
Запись в это свойство заражённых данных приводит к Server-Side Request Forgery (V5618). |
11 |
log_injection_target |
Запись в это свойство заражённых данных приводит к Log Injection (V5619). |
12 |
ldapi_injection_target |
Запись в это свойство заражённых данных приводит к LDAP Injection (V5620). |
13 |
xpath_injection_target |
Запись в это свойство заражённых данных приводит к XPath Injection (V5622). |
14 |
open_redirect_target |
Запись в это свойство заражённых данных приводит к Open Redirect (V5623). |
15 |
configuration_attack_target |
Запись в это свойство заражённых данных приводит к Configuration Attack (5624). |
16 |
nosql_injection_target |
Запись в это свойство заражённых данных приводит к NoSQL Injection (V5627). |
17 |
redos_target |
Запись в это свойство заражённых данных приводит к ReDoS (V5626). |
18 |
zipslip_target |
Запись в это свойство заражённых данных приводит к ZipSlip (V5628). |
Аннотации параметров
Примечание 1. Объект аннотации параметра может находиться только внутри массива 'params', объекта аннотации метода или конструктора.
Примечание 2. Объект аннотации параметра должен либо содержать поля 'namespace_name' и 'type_name', либо оба поля должны отсутствовать (или иметь значение null).
Объект аннотации параметра состоит из следующих полей:
Поле "namespace_name"
Обязательное поле. Принимает строку с именем пространства имён, которое содержит тип параметра.
Поле "type_name"
Обязательное поле. Принимает строку с именем класса, в котором определён тип параметра.
Поле "attributes"
Опциональное поле. Массив строк, который задаёт свойства сущности.
Возможные атрибуты параметров
Примечание. К каждому из атрибутов taint-приёмников и taint-валидации прикреплена ссылка на соответствующую диагностику.
# |
Название атрибута |
Описание атрибута |
---|---|---|
1 |
ignore_current_and_next |
При подборе соответствующей аннотации не будут учитываться текущий и следующие параметры (данная аннотация может быть только у последнего аргумента). |
2 |
transfer_annotation_to_return_value |
Если параметр содержит аннотацию, она будет перенесена на возвращаемое значение метода. |
3 |
object_creation_infector |
Заражение нового созданного объекта происходит через этот параметр (актуально только для конструкторов). |
4 |
sql_injection_target |
Передача в этот параметр заражённых данных приводит к SQL Injection (V5608). |
5 |
sql_injection_validation |
Вызов метода сбрасывает SQL Injection taint-статус для данного параметра (V5608). |
6 |
path_traversal_target |
Передача в этот параметр заражённых данных приводит к Path Traversal (V5609). |
7 |
path_traversal_validation |
Вызов метода сбрасывает Path Traversal taint-статус для данного параметра (V5609). |
8 |
xss_injection_target |
Передача в этот параметр заражённых данных приводит к XSS Injection (V5610). |
9 |
xss_injection_validation |
Вызов метода сбрасывает XSS Injection taint-статус для данного параметра (V5610). |
10 |
insecure_deserialization_target |
Передача в этот параметр заражённых данных приводит к Insecure Deserialization (V5611). |
11 |
insecure_deserialization_validation |
Вызов метода сбрасывает Insecure Deserialization taint-статус для данного параметра (V5611). |
12 |
command_injection_target |
Передача в этот параметр заражённых данных приводит к Command Injection (V5616). |
13 |
command_injection_validation |
Вызов метода сбрасывает Command Injection taint-статус для данного параметра (V5616). |
14 |
xml_source_to_parse |
Параметр - источник XML, который будет парситься. Это может быть сам XML-файл, путь до него, поток с XML-файлов, парсер, содержащий поток XML-файла, и т. п. (V5614, V5615). |
15 |
transfer_xml_settings_to_return |
Передаёт настройки XML-парсера из этого аргумента в возвращаемое значение. (V5614, V5615). |
16 |
ssrf_target |
Передача в этот параметр заражённых данных приводит к Server-Side Request Forgery (V5618). |
17 |
ssrf_validation |
Вызов метода сбрасывает Server-Side Request Forgery taint-статус для данного параметра (V5618). |
18 |
log_injection_target |
Передача в этот параметр заражённых данных приводит к Log Injection (V5619). |
19 |
log_injection_validation |
Вызов метода сбрасывает Log Injection taint-статус для данного параметра (V5619). |
20 |
ldapi_injection_target |
Передача в этот параметр заражённых данных приводит к LDAP Injection (V5620). |
21 |
ldapi_injection_validation |
Вызов метода сбрасывает LDAP Injection taint-статус для данного параметра (V5620). |
22 |
xpath_injection_target |
Передача в этот параметр заражённых данных приводит к XPath Injection (V5622). |
23 |
xpath_injection_validation |
Вызов метода сбрасывает XPath Injection taint-статус для данного параметра (V5622). |
24 |
open_redirect_target |
Передача в этот параметр заражённых данных приводит к Open Redirect (V5623). |
25 |
open_redirect_validation |
Вызов метода сбрасывает Open Redirect taint-статус для данного параметра (V5623). |
26 |
configuration_attack_target |
Передача в этот параметр заражённых данных приводит к Configuration Attack (5624). |
27 |
configuration_attack_validation |
Вызов метода сбрасывает Configuration Attack taint-статус для данного параметра (5624). |
28 |
nosql_injection_target |
Передача в этот параметр заражённых данных приводит к NoSQL Injection (V5627). |
29 |
nosql_injection_validation |
Вызов метода сбрасывает NoSQL Injection taint-статус для данного параметра (V5627). |
30 |
redos_target |
Строка, которая разбирается с помощью регулярного выражения. Передача в этот параметр заражённых данных приводит к ReDoS, если регулярное выражение небезопасно (V5626). |
31 |
redos_validation |
Вызов метода сбрасывает ReDoS taint-статус для данного параметра (V5626). |
32 |
zipslip_target |
Строка, которая может быть использована как путь для извлечения файла из архива. Передача в этот параметр заражённых данных приводит к ZipSlip (V5628). |
33 |
zipslip_validation |
Вызов метода сбрасывает ZipSlip taint-статус для данного параметра (V5628). |
34 |
regex |
Параметр является регулярным выражением. |
Игнорирование типа параметра
Чтобы проигнорировать тип параметра, не нужно указывать поля 'namespace_name' и 'type_name' или нужно записать в оба поля null.
Схема JSON
Схема JSON поставляется в дистрибутиве или доступна по ссылке.
Примеры
Аннотация метода
Рассмотрим метод:
namespace MyNamespace
{
public class MyClass
{
public string GetUserInput()
{
....
}
}
}
Допустим, данный метод возвращает пользовательский ввод, который может содержать taint-данные. Аннотация, которая позволит анализатору понять это, будет выглядеть следующим образом:
{
"version": 1,
"language": "csharp",
"annotations": [
{
"type": "method",
"namespace_name": "MyNamespace",
"type_name": "MyClass",
"method_name": "GetUserInput",
"returns": {
"attributes": [ "always_taint" ]
}
}
]
}
Аннотация конструктора
Рассмотрим конструктор:
namespace MyNamespace
{
public class MyClass
{
public MyClass()
{
....
}
}
}
Допустим, данный конструктор создаёт объект, который может содержать taint-данные. Аннотация, которая позволит анализатору понять это, будет выглядеть следующим образом:
{
"version": 1,
"language": "csharp",
"annotations": [
{
"type": "ctor",
"namespace_name": "MyNamespace",
"type_name": "MyClass",
"attributes": [ "create_taint_object" ]
}
]
}
Аннотация свойства
Рассмотрим свойство:
namespace MyNamespace
{
public class MyClass
{
public string UserInput
{
get
{
....
}
}
}
}
Допустим, данное свойство возвращает пользовательский ввод, который может содержать taint-данные. Аннотация, которая позволит анализатору понять это, будет выглядеть следующим образом:
{
"version": 1,
"language": "csharp",
"annotations": [
{
"type": "property",
"namespace_name": "MyNamespace",
"type_name": "MyClass",
"property_name": "UserInput",
"attributes": [ "return_taint" ]
}
]
}
Аннотация метода/конструктора, тип параметра которых неважен
Примечание. В качестве примера используется аннотация метода. Игнорирование типа параметров конструктора производится аналогичным образом (не указывать 'type_name' и 'namespace_name' у аннотации параметра).
Рассмотрим две перегрузки метода 'GetUserInput':
namespace MyNamespace
{
public class MyClass
{
public string GetUserInput(string str)
{
....
}
public string GetUserInput(int index)
{
....
}
}
}
Допустим, данный метод возвращает пользовательский ввод, который может содержать taint-данные, вне зависимости от типа параметра. Аннотация, которая позволит анализатору понять это, будет выглядеть следующим образом:
{
"version": 1,
"language": "csharp",
"annotations": [
{
"type": "method",
"namespace_name": "MyNamespace",
"type_name": "MyClass",
"method_name": "GetUserInput",
"params": [
{ }
],
"returns": {
"attributes": [ "always_taint" ]
}
}
]
}
В данном случае для первого параметра нет аннотаций. Также при подборе аннотации метода неважно, какой тип будет иметь первый параметр. Поэтому аннотация параметра представлена пустым объектом.
Аннотация метода/конструктора, игнорируя некоторые параметры
Примечание. В качестве примера используется аннотация метода. Игнорирование параметров конструктора производится аналогичным образом (с помощью аннотации 'ignore_current_and_next').
Рассмотрим две перегрузки метода 'GetUserInput':
namespace MyNamespace
{
public class MyClass
{
public string GetUserInput(string str)
{
....
}
public string GetUserInput(string str, bool flag1, bool flag2)
{
....
}
}
}
Допустим, данный метод возвращает пользовательский ввод, который может содержать taint-данные, если использована перегрузка с одним или более параметрами. Также, если в первый параметр передать taint-данные, возникнет SQL injection. Аннотация, которая позволит анализатору понять это, будет выглядеть следующим образом:
{
"version": 1,
"language": "csharp",
"annotations": [
{
"type": "method",
"namespace_name": "MyNamespace",
"type_name": "MyClass",
"method_name": "GetUserInput",
"params": [
{
"namespace_name": "System",
"type_name": "String",
"attributes": [ "sql_injection_target" ]
},
{
"attributes": [ "ignore_current_and_next" ]
}
],
"returns": {
"attributes": [ "always_taint" ]
}
}
]
}
Для второго параметра есть аннотация 'ignore_current_and_next'. Она позволяет игнорировать количество параметров (включая проаннотированный параметр) при обработке аннотации.