SlideShare a Scribd company logo
1 of 67
Исключительно простая
теория AppSec .NET
Владимир Кочетков
Application Inspector/Compiling Applications Analysis/Team Lead
Positive Technologies
Июньская встреча SPB.NET Community, 2015
:~$ whoami && whonotme
― .NET-разработчик, руководитель группы анализа
компилируемых приложений в Positive Technologies
― AppSec-исследователь
― RSDN тимер
― Оторванный от реальности теоретик
― Упоротый параноик
Всего один вопрос…
…что такое уязвимость?
Какой из фрагментов кода уязвим?
1)
var cmd = new SqlCommand("SELECT Value FROM Discounts WHERE CouponCode = '" +
Request["CouponCode"] + "'");
var connection = new SqlConnection(connectionString);
connection.Open();
cmd.Connection = connection;
var couponValue = cmd.ExecuteScalar();
...
2)
var cmd = new SqlCommand("SELECT Value FROM Discounts WHERE CouponCode =
@CouponCode");
cmd.Parameters.AddWithValue("@CouponCode ", Request["CouponCode"]);
var connection = new SqlConnection(connectionString);
connection.Open();
cmd.Connection = connection;
var couponValue = cmd.ExecuteScalar();
...
Какой из фрагментов кода уязвим?
1)
[Authorize(Roles = "All")]
public ActionResult SomeAction()
{
...
return View();
}
2)
[Authorize(Roles = "Baz, Qux")]
public ActionResult SomeAction()
{
...
return View();
}
Уязвимость к RCE?
var code = wrapCode("Foo", "Bar", "Qux", Request["code"]);
var provider = new CSharpCodeProvider();
var compilerParams = new CompilerParameters
{
GenerateInMemory = true,
GenerateExecutable = false
};
var results = provider.CompileAssemblyFromSource(
compilerParams, code);
if (!results.Errors.Any())
{
var o = results.CompiledAssembly.CreateInstance("Foo.Bar");
var mi = o.GetType().GetMethod("Qux");
mi.Invoke(o, null);
}
Критерии уязвимости
определяются
множествами правил
предметных областей
приложения
Примеры предметных областей
Нефункциональные:
― управление потоками данных;
― управление потоками выполнения;
― контроль доступа.
Функциональные:
― интернет-торговля;
― онлайн-банкинг;
― бухучет;
― …
Театр начинается с
вешалки, а уязвимость –
с недостатка
Недостаток
- неэффективный контроль выполнения правил предметных
областей приложения
Примеры недостатков:
― неэффективная предварительная обработка данных;
― неэффективный контроль аутентичности источника
запросов;
― неэффективный контроль доступа;
― неэффективный контроль жизненного цикла транзакции;
― неэффективный контроль распределения ролей.
Приложение - это поток
управления,
обрабатывающий
множество потоков
данных
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки данных
var name = Request.Params["name"];
var key1 = Request.Params["key1"];
var parm = Request.Params["parm"];
var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm);
string str1;
if (name + "in" == "admin")
{
if (key1 == "validkey")
{
str1 = Encoding.UTF8.GetString(data);
}
else
{
str1 = "Wrong key!";
}
Response.Write(str1);
}
Потоки управления
являются производными
от потоков данных
Множества значений
всех потоков данных в
конкретной точке потока
выполнения определяют
состояние приложения
Угроза
- возможность обхода правил предметных областей
приложения, приводящего к нарушению свойств
защищенности хотя бы одного потока данных:
― конфиденциальности;
― целостности;
― доступности;
― аутентичности;
― авторизованности.
Уязвимость – состояние
приложения, в котором
возможна реализация
угрозы
То, что может сделать с потоками данных атакующий,
нарушив правила предметных областей, называется
угрозой (threat)
То, где и благодаря чему он может это сделать, называется
уязвимостью (vulnerability), обусловленной недостатком
(weakness)
То, как он может это сделать, называется атакой (attack)
То, с какой вероятностью у него это удастся и какие
последствия может повлечь, называется риском (risk)
Иными словами…
То, что не позволяет атакующему провести атаку,
обеспечивает защищенность (security)
То, что минимизирует риск, обеспечивает безопасность
(safety)
Разработчикам следует обеспечивать
защищенность, не допуская появления
недостатков в коде
Иными словами…
Причинно-следственные связи
Недостаток Угроза
Уязвимость Атака
Риск
Незащищенность
Небезопасность
Бороться необходимо с причинами, а не со следствиями!
* на основе результатов опроса http://www.rsdn.ru/?poll/3488
Осведомленность разработчиков*
0.00%
10.00%
20.00%
30.00%
40.00%
50.00%
60.00%
70.00%
80.00%
90.00%
AbuseofFunctionality
BruteForce
Buffer/FormatStringOverflow
ContentSpoofing
Credential/SessionPrediction
Cross-SiteRequestForgery
Cross-SiteScripting
DenialofService
Fingerprinting
HPP/HPC
HRS
IntegerOverflows
LDAPInjection
MailCommandInjection
NullByteInjection
OSCommanding
PathTraversal
PredictableResourceLocation
Remote/LocalFileInclusion
RoutingDetour
SessionFixation
SOAPArrayAbuse
SQLInjection
SSIInjection
URLRedirectorAbuse
XMLAttributeBlowup
XMLEntityExpansion
XMLExternalEntities
XMLInjection
XPath/XQueryInjection
Attacks based on WASC classification Attacks included at OWASP Top 10 risks
Классификация
Классификация уязвимостей возможна по:
― предметной области; // управление потоками данных
― недостатку; // неэффективная
предварительная обработка данных
― потоку данных; // первообразная потока
управления
― угрозе; // нарушение целостности
== уязвимость к атакам инъекций (в зависимости от
интерпретатора потока данных: XSS, SQLi,XMLi, XPATHi, Path
Traversal, LINQi,XXE и т.п.)
Предварительная
обработка данных
― Типизация — создание объектного представления
входных данных из строкового типа (парсинг и
десериализация).
― Санитизация — приведение данных в соответствие с
грамматикой, допускаемой политикой защищенности.
― Валидация — проверка данных на соответствие
установленным критериям:
• грамматическая;
• семантическая.
Подходы к предварительной обработке
Типизация и валидация на входе, санитизация — на выходе!
Смотри, не перепутай…
Протоколы потоков данных— формальные языки.
Некоторые языки распознаются сложнее, чем остальные.
Для некоторых языков распознавание неразрешимо.
Чем сложнее язык, тем тяжелее
сформировать критерии к входным
данным, описывающим множества
конфигураций системы.
Обобщенный подход
Тестирование эквивалентности конечных автоматов или
детерминированных стековых автоматов* разрешимо.
Для недетерминированных стековых автоматов и более
мощных моделей вычислений такое тестирование является
неразрешимым.
В первом случае возможно полное покрытие тестами
элементов парсера языка обрабатываемых данных или их
статический анализ.
Во втором случае — НЕТ!
Обобщенный подход
Упрощение или декомпозиция языка входных данных до
множества регулярных или детерминированных
контекстно-свободных грамматик.
Внедрение в код проверок (типизации/валидации)
входных данных в соответствии с грамматикой их языка
как можно ближе к началу потока управления.
Внедрение в код санитайзеров выходных данных,
построенных в соответствии с грамматикой принимающей
стороны, как можно ближе к потенциально уязвимому
состоянию.
Обобщенный подход
Островными – называются языки, грамматики которых
описывают правила распознавания отдельных выражений
(«островов»), окруженных выражениями, принадлежащими
другому языку («морем»).
string.Format("SELECT * FROM Table WHERE Id= {0}", Request["Id"]);
море (C#) остров (SQL) море (C#)
Работа с любыми выходными данными сводится к
формированию текста на островном языке, а также
приводит к образованию новых островных языков, т.к.:
острова с параметрами являются верхнеуровневыми
островными языками
Островные языки
Формальные признаки инъекции
― Потенциально уязвимая операция PVO(text): операция
прямой или косвенной интерпретации текста text на
формальном островном языке
― text = transform(argument), где argument – элемент
множества аргументов точки входа EP, а transform –
функция промежуточных преобразований
― Не существует или недостижимо ни одно множество таких
значений элементов EP, при которых происходит
изменение структуры синтаксического дерева значения
text, достигающего PVO, не предусмотренное правилами
прочих предметных областей
1' AND 1=(SELECT COUNT(*) FROM tablenames); --
'><script>alert/XSS/</script><!--
../../../../../../../etc/passwd%00
admin*)((|userPassword=*)
Что общего между ними?
Анатомия атак инъекций
1' AND 1=(SELECT COUNT(*) FROM tablenames); --
'><script>alert/XSS/</script><!--
../../../../../../../etc/passwd%00
admin*)((|userPassword=*)
Атакующие используют синтаксические элементы основной
грамматики, чтобы выбраться за пределы острова и
нарушить целостность потока выполнения принимающей
стороны
Анатомия инъекций
Какой грамматике соответствует запрос:
SELECT * FROM Table WHERE Id={:int}
?
Островные языки
select stmt ::= SELECT select list from clause
| SELECT select list from clause where clause
select list ::= id list
| *
id list ::= id
| id , id list
from clause ::= FROM tbl list
tbl list ::= id list
where clause ::= WHERE bool cond
bcond ::= bcond OR bterm
| bterm
bterm ::= bterm AND bfactor
| bfactor
bfactor ::= NOT cond
| cond
cond ::= value comp value
value ::= id
| str lit
| num
str lit ::= ' lit '
comp ::= = | < | > | <= | >= | !=
… (+ еще ~1000 страниц отборной EBNF)
Контекстно-свободная SQL?
SELECT * FROM Table WHERE Id=[0-9]+
Море Остров
Явное выделение всех островных грамматик облегчает
реализацию контроля выходных данных
Чтобы реализовать достаточный и эффективный контроль
выходных данных, в общем случае, необходимо взять из
основной островной грамматики правила, описывающие
разбор токена, в который попадают входные данные и
обеспечить невозможность их выхода за пределы этого
токена.
Регулярная, островная!
Пример: LINQ Injection
public AjaxStoreResult GetCustomers(int limit, int start, string dir, string sort)
{
var query = (from c in this.DBContext.Customers
select new
{
c.CustomerID,
c.CompanyName,
c.ContactName,
c.Phone,
c.Fax,
c.Region
}).OrderBy(string.Concat(sort, " ", dir));
int total = query.ToList().Count;
query = query.Skip(start).Take(limit);
return new AjaxStoreResult(query, total);
}
Пример: LINQ Injection
public AjaxStoreResult GetCustomers(int limit, int start, string dir, string sort)
{
var query = (from c in this.DBContext.Customers
select new
{
c.CustomerID,
c.CompanyName,
c.ContactName,
c.Phone,
c.Fax,
c.Region
}).OrderBy(string.Concat(sort, " ", dir));
int total = query.ToList().Count;
query = query.Skip(start).Take(limit);
return new AjaxStoreResult(query, total);
}
Пример: LINQ Injection
public AjaxStoreResult GetCustomers(int limit, int start, string dir, string sort)
{
if (!Regex.IsMatch(dir, "(?-m:)(?i:)^asc|desc$")) { dir = "ASC"; }
if (!Regex.IsMatch(sort,
"(?-m:)(?i:)^customerid|companyname|contactname|phone|fax|region$"))
{ sort = "CustomerID"; }
var query = (from c in this.DBContext.Customers
select new
{
c.CustomerID,
c.CompanyName,
c.ContactName,
c.Phone,
c.Fax,
c.Region
}).OrderBy(string.Concat(sort, " ", dir));
var total = query.ToList().Count;
query = query.Skip(start).Take(limit);
return new AjaxStoreResult(query, total);
}
{DEMO}
Вопросы?
Владимир Кочетков
vkochetkov@ptsecurity.com
@kochetkov_v
Application Inspector/Compiling Applications Analysis/Team Lead
Positive Technologies
Исключительно простая теория AppSec .NET

More Related Content

What's hot

Конкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыcorehard_by
 
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...corehard_by
 
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)Ontico
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU
 
Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!RAMBLER&Co
 
Formal verification of C code
Formal verification of C codeFormal verification of C code
Formal verification of C codeDenis Efremov
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыcorehard_by
 
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Mikhail Matrosov
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Yauheni Akhotnikau
 
Miasm defcon russia 23
Miasm defcon russia 23Miasm defcon russia 23
Miasm defcon russia 23DefconRussia
 
Haskell
HaskellHaskell
HaskellDevDay
 
Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Sergey Platonov
 
C:\fakepath\кмсзи экз
C:\fakepath\кмсзи   экзC:\fakepath\кмсзи   экз
C:\fakepath\кмсзи экзdarina andr
 
Тестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиТестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиSQALab
 
TMPA-2013 Vert Krikun: Finding Defects in C and C++ Pointers Using Static Ana...
TMPA-2013 Vert Krikun: Finding Defects in C and C++ Pointers Using Static Ana...TMPA-2013 Vert Krikun: Finding Defects in C and C++ Pointers Using Static Ana...
TMPA-2013 Vert Krikun: Finding Defects in C and C++ Pointers Using Static Ana...Iosif Itkin
 

What's hot (18)

course js day 2
course js day 2course js day 2
course js day 2
 
Конкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнеры
 
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
 
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)
Консервативный Backend на Node.js / Дмитрий Ляпин (Recrumatic)
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
 
XML Magic
XML MagicXML Magic
XML Magic
 
Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!
 
Formal verification of C code
Formal verification of C codeFormal verification of C code
Formal verification of C code
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтеры
 
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Fiche Révision POO
Fiche Révision POOFiche Révision POO
Fiche Révision POO
 
Miasm defcon russia 23
Miasm defcon russia 23Miasm defcon russia 23
Miasm defcon russia 23
 
Haskell
HaskellHaskell
Haskell
 
Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++
 
C:\fakepath\кмсзи экз
C:\fakepath\кмсзи   экзC:\fakepath\кмсзи   экз
C:\fakepath\кмсзи экз
 
Тестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиТестирование программных фильтров безопасности
Тестирование программных фильтров безопасности
 
TMPA-2013 Vert Krikun: Finding Defects in C and C++ Pointers Using Static Ana...
TMPA-2013 Vert Krikun: Finding Defects in C and C++ Pointers Using Static Ana...TMPA-2013 Vert Krikun: Finding Defects in C and C++ Pointers Using Static Ana...
TMPA-2013 Vert Krikun: Finding Defects in C and C++ Pointers Using Static Ana...
 

Viewers also liked

Поиск ошибок в программах на языке C#
Поиск ошибок в программах на языке C#Поиск ошибок в программах на языке C#
Поиск ошибок в программах на языке C#Mikhail Shcherbakov
 
Илья Фофанов "Обработка ошибок в C#"
Илья Фофанов "Обработка ошибок в C#"Илья Фофанов "Обработка ошибок в C#"
Илья Фофанов "Обработка ошибок в C#"Yulia Tsisyk
 
Владимир Кошелев «Автоматический поиск ошибок»
Владимир Кошелев «Автоматический поиск ошибок»Владимир Кошелев «Автоматический поиск ошибок»
Владимир Кошелев «Автоматический поиск ошибок»MskDotNet Community
 
Кирилл Маурин «Проектирование и разработка модульных приложений»
Кирилл Маурин «Проектирование и разработка модульных приложений» Кирилл Маурин «Проектирование и разработка модульных приложений»
Кирилл Маурин «Проектирование и разработка модульных приложений» Yulia Tsisyk
 
[1.4] «Ой, не шмогла». Обзор ограничений современных технологий в области ...
[1.4] «Ой, не шмогла». Обзор ограничений современных технологий в области ...[1.4] «Ой, не шмогла». Обзор ограничений современных технологий в области ...
[1.4] «Ой, не шмогла». Обзор ограничений современных технологий в области ...OWASP Russia
 
Waf.js: How to Protect Web Applications using JavaScript
Waf.js: How to Protect Web Applications using JavaScriptWaf.js: How to Protect Web Applications using JavaScript
Waf.js: How to Protect Web Applications using JavaScriptDenis Kolegov
 

Viewers also liked (6)

Поиск ошибок в программах на языке C#
Поиск ошибок в программах на языке C#Поиск ошибок в программах на языке C#
Поиск ошибок в программах на языке C#
 
Илья Фофанов "Обработка ошибок в C#"
Илья Фофанов "Обработка ошибок в C#"Илья Фофанов "Обработка ошибок в C#"
Илья Фофанов "Обработка ошибок в C#"
 
Владимир Кошелев «Автоматический поиск ошибок»
Владимир Кошелев «Автоматический поиск ошибок»Владимир Кошелев «Автоматический поиск ошибок»
Владимир Кошелев «Автоматический поиск ошибок»
 
Кирилл Маурин «Проектирование и разработка модульных приложений»
Кирилл Маурин «Проектирование и разработка модульных приложений» Кирилл Маурин «Проектирование и разработка модульных приложений»
Кирилл Маурин «Проектирование и разработка модульных приложений»
 
[1.4] «Ой, не шмогла». Обзор ограничений современных технологий в области ...
[1.4] «Ой, не шмогла». Обзор ограничений современных технологий в области ...[1.4] «Ой, не шмогла». Обзор ограничений современных технологий в области ...
[1.4] «Ой, не шмогла». Обзор ограничений современных технологий в области ...
 
Waf.js: How to Protect Web Applications using JavaScript
Waf.js: How to Protect Web Applications using JavaScriptWaf.js: How to Protect Web Applications using JavaScript
Waf.js: How to Protect Web Applications using JavaScript
 

More from Vladimir Kochetkov

Практическое использование средств криптографии в .NET, Java и PHP
Практическое использование средств криптографии в .NET, Java и PHPПрактическое использование средств криптографии в .NET, Java и PHP
Практическое использование средств криптографии в .NET, Java и PHPVladimir Kochetkov
 
Do WAFs dream of static analyzers
Do WAFs dream of static analyzersDo WAFs dream of static analyzers
Do WAFs dream of static analyzersVladimir Kochetkov
 
AppSec -- хакерский путь
AppSec -- хакерский путьAppSec -- хакерский путь
AppSec -- хакерский путьVladimir Kochetkov
 
Подводные камни прикладной криптографии, I
Подводные камни прикладной криптографии, IПодводные камни прикладной криптографии, I
Подводные камни прикладной криптографии, IVladimir Kochetkov
 
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Vladimir Kochetkov
 
Hack an ASP .NET website? Hard, but possible!
Hack an ASP .NET website? Hard, but possible! Hack an ASP .NET website? Hard, but possible!
Hack an ASP .NET website? Hard, but possible! Vladimir Kochetkov
 
Automated Patching for Vulnerable Source Code
Automated Patching for Vulnerable Source CodeAutomated Patching for Vulnerable Source Code
Automated Patching for Vulnerable Source CodeVladimir Kochetkov
 
How to Develop a Secure Web Application and Stay in Mind? (PHDays 3)
How to Develop a Secure Web Application and Stay in Mind? (PHDays 3)How to Develop a Secure Web Application and Stay in Mind? (PHDays 3)
How to Develop a Secure Web Application and Stay in Mind? (PHDays 3)Vladimir Kochetkov
 
Как разработать защищенное веб-приложение и не сойти при этом с ума (вебинар)
Как разработать защищенное веб-приложение и не сойти при этом с ума (вебинар)Как разработать защищенное веб-приложение и не сойти при этом с ума (вебинар)
Как разработать защищенное веб-приложение и не сойти при этом с ума (вебинар)Vladimir Kochetkov
 

More from Vladimir Kochetkov (9)

Практическое использование средств криптографии в .NET, Java и PHP
Практическое использование средств криптографии в .NET, Java и PHPПрактическое использование средств криптографии в .NET, Java и PHP
Практическое использование средств криптографии в .NET, Java и PHP
 
Do WAFs dream of static analyzers
Do WAFs dream of static analyzersDo WAFs dream of static analyzers
Do WAFs dream of static analyzers
 
AppSec -- хакерский путь
AppSec -- хакерский путьAppSec -- хакерский путь
AppSec -- хакерский путь
 
Подводные камни прикладной криптографии, I
Подводные камни прикладной криптографии, IПодводные камни прикладной криптографии, I
Подводные камни прикладной криптографии, I
 
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!
 
Hack an ASP .NET website? Hard, but possible!
Hack an ASP .NET website? Hard, but possible! Hack an ASP .NET website? Hard, but possible!
Hack an ASP .NET website? Hard, but possible!
 
Automated Patching for Vulnerable Source Code
Automated Patching for Vulnerable Source CodeAutomated Patching for Vulnerable Source Code
Automated Patching for Vulnerable Source Code
 
How to Develop a Secure Web Application and Stay in Mind? (PHDays 3)
How to Develop a Secure Web Application and Stay in Mind? (PHDays 3)How to Develop a Secure Web Application and Stay in Mind? (PHDays 3)
How to Develop a Secure Web Application and Stay in Mind? (PHDays 3)
 
Как разработать защищенное веб-приложение и не сойти при этом с ума (вебинар)
Как разработать защищенное веб-приложение и не сойти при этом с ума (вебинар)Как разработать защищенное веб-приложение и не сойти при этом с ума (вебинар)
Как разработать защищенное веб-приложение и не сойти при этом с ума (вебинар)
 

Исключительно простая теория AppSec .NET

  • 1.
  • 2. Исключительно простая теория AppSec .NET Владимир Кочетков Application Inspector/Compiling Applications Analysis/Team Lead Positive Technologies Июньская встреча SPB.NET Community, 2015
  • 3. :~$ whoami && whonotme ― .NET-разработчик, руководитель группы анализа компилируемых приложений в Positive Technologies ― AppSec-исследователь ― RSDN тимер ― Оторванный от реальности теоретик ― Упоротый параноик
  • 6. Какой из фрагментов кода уязвим? 1) var cmd = new SqlCommand("SELECT Value FROM Discounts WHERE CouponCode = '" + Request["CouponCode"] + "'"); var connection = new SqlConnection(connectionString); connection.Open(); cmd.Connection = connection; var couponValue = cmd.ExecuteScalar(); ... 2) var cmd = new SqlCommand("SELECT Value FROM Discounts WHERE CouponCode = @CouponCode"); cmd.Parameters.AddWithValue("@CouponCode ", Request["CouponCode"]); var connection = new SqlConnection(connectionString); connection.Open(); cmd.Connection = connection; var couponValue = cmd.ExecuteScalar(); ...
  • 7. Какой из фрагментов кода уязвим? 1) [Authorize(Roles = "All")] public ActionResult SomeAction() { ... return View(); } 2) [Authorize(Roles = "Baz, Qux")] public ActionResult SomeAction() { ... return View(); }
  • 8. Уязвимость к RCE? var code = wrapCode("Foo", "Bar", "Qux", Request["code"]); var provider = new CSharpCodeProvider(); var compilerParams = new CompilerParameters { GenerateInMemory = true, GenerateExecutable = false }; var results = provider.CompileAssemblyFromSource( compilerParams, code); if (!results.Errors.Any()) { var o = results.CompiledAssembly.CreateInstance("Foo.Bar"); var mi = o.GetType().GetMethod("Qux"); mi.Invoke(o, null); }
  • 10. Примеры предметных областей Нефункциональные: ― управление потоками данных; ― управление потоками выполнения; ― контроль доступа. Функциональные: ― интернет-торговля; ― онлайн-банкинг; ― бухучет; ― …
  • 11. Театр начинается с вешалки, а уязвимость – с недостатка
  • 12. Недостаток - неэффективный контроль выполнения правил предметных областей приложения Примеры недостатков: ― неэффективная предварительная обработка данных; ― неэффективный контроль аутентичности источника запросов; ― неэффективный контроль доступа; ― неэффективный контроль жизненного цикла транзакции; ― неэффективный контроль распределения ролей.
  • 13. Приложение - это поток управления, обрабатывающий множество потоков данных
  • 14. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 15. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 16. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 17. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 18. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 19. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 20. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 21. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 22. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 23. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 24. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 25. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 26. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 27. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 28. Потоки управления var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 29. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 30. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 31. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 32. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 33. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 34. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 35. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 36. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 37. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 38. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 39. Потоки данных var name = Request.Params["name"]; var key1 = Request.Params["key1"]; var parm = Request.Params["parm"]; var data = string.IsNullOrEmpty(parm) ? new char[0]: Convert.FromBase64String(parm); string str1; if (name + "in" == "admin") { if (key1 == "validkey") { str1 = Encoding.UTF8.GetString(data); } else { str1 = "Wrong key!"; } Response.Write(str1); }
  • 41. Множества значений всех потоков данных в конкретной точке потока выполнения определяют состояние приложения
  • 42. Угроза - возможность обхода правил предметных областей приложения, приводящего к нарушению свойств защищенности хотя бы одного потока данных: ― конфиденциальности; ― целостности; ― доступности; ― аутентичности; ― авторизованности.
  • 43. Уязвимость – состояние приложения, в котором возможна реализация угрозы
  • 44. То, что может сделать с потоками данных атакующий, нарушив правила предметных областей, называется угрозой (threat) То, где и благодаря чему он может это сделать, называется уязвимостью (vulnerability), обусловленной недостатком (weakness) То, как он может это сделать, называется атакой (attack) То, с какой вероятностью у него это удастся и какие последствия может повлечь, называется риском (risk) Иными словами…
  • 45. То, что не позволяет атакующему провести атаку, обеспечивает защищенность (security) То, что минимизирует риск, обеспечивает безопасность (safety) Разработчикам следует обеспечивать защищенность, не допуская появления недостатков в коде Иными словами…
  • 46. Причинно-следственные связи Недостаток Угроза Уязвимость Атака Риск Незащищенность Небезопасность Бороться необходимо с причинами, а не со следствиями!
  • 47. * на основе результатов опроса http://www.rsdn.ru/?poll/3488 Осведомленность разработчиков* 0.00% 10.00% 20.00% 30.00% 40.00% 50.00% 60.00% 70.00% 80.00% 90.00% AbuseofFunctionality BruteForce Buffer/FormatStringOverflow ContentSpoofing Credential/SessionPrediction Cross-SiteRequestForgery Cross-SiteScripting DenialofService Fingerprinting HPP/HPC HRS IntegerOverflows LDAPInjection MailCommandInjection NullByteInjection OSCommanding PathTraversal PredictableResourceLocation Remote/LocalFileInclusion RoutingDetour SessionFixation SOAPArrayAbuse SQLInjection SSIInjection URLRedirectorAbuse XMLAttributeBlowup XMLEntityExpansion XMLExternalEntities XMLInjection XPath/XQueryInjection Attacks based on WASC classification Attacks included at OWASP Top 10 risks
  • 48. Классификация Классификация уязвимостей возможна по: ― предметной области; // управление потоками данных ― недостатку; // неэффективная предварительная обработка данных ― потоку данных; // первообразная потока управления ― угрозе; // нарушение целостности == уязвимость к атакам инъекций (в зависимости от интерпретатора потока данных: XSS, SQLi,XMLi, XPATHi, Path Traversal, LINQi,XXE и т.п.)
  • 50. ― Типизация — создание объектного представления входных данных из строкового типа (парсинг и десериализация). ― Санитизация — приведение данных в соответствие с грамматикой, допускаемой политикой защищенности. ― Валидация — проверка данных на соответствие установленным критериям: • грамматическая; • семантическая. Подходы к предварительной обработке
  • 51. Типизация и валидация на входе, санитизация — на выходе! Смотри, не перепутай…
  • 52. Протоколы потоков данных— формальные языки. Некоторые языки распознаются сложнее, чем остальные. Для некоторых языков распознавание неразрешимо. Чем сложнее язык, тем тяжелее сформировать критерии к входным данным, описывающим множества конфигураций системы. Обобщенный подход
  • 53. Тестирование эквивалентности конечных автоматов или детерминированных стековых автоматов* разрешимо. Для недетерминированных стековых автоматов и более мощных моделей вычислений такое тестирование является неразрешимым. В первом случае возможно полное покрытие тестами элементов парсера языка обрабатываемых данных или их статический анализ. Во втором случае — НЕТ! Обобщенный подход
  • 54. Упрощение или декомпозиция языка входных данных до множества регулярных или детерминированных контекстно-свободных грамматик. Внедрение в код проверок (типизации/валидации) входных данных в соответствии с грамматикой их языка как можно ближе к началу потока управления. Внедрение в код санитайзеров выходных данных, построенных в соответствии с грамматикой принимающей стороны, как можно ближе к потенциально уязвимому состоянию. Обобщенный подход
  • 55. Островными – называются языки, грамматики которых описывают правила распознавания отдельных выражений («островов»), окруженных выражениями, принадлежащими другому языку («морем»). string.Format("SELECT * FROM Table WHERE Id= {0}", Request["Id"]); море (C#) остров (SQL) море (C#) Работа с любыми выходными данными сводится к формированию текста на островном языке, а также приводит к образованию новых островных языков, т.к.: острова с параметрами являются верхнеуровневыми островными языками Островные языки
  • 56. Формальные признаки инъекции ― Потенциально уязвимая операция PVO(text): операция прямой или косвенной интерпретации текста text на формальном островном языке ― text = transform(argument), где argument – элемент множества аргументов точки входа EP, а transform – функция промежуточных преобразований ― Не существует или недостижимо ни одно множество таких значений элементов EP, при которых происходит изменение структуры синтаксического дерева значения text, достигающего PVO, не предусмотренное правилами прочих предметных областей
  • 57. 1' AND 1=(SELECT COUNT(*) FROM tablenames); -- '><script>alert/XSS/</script><!-- ../../../../../../../etc/passwd%00 admin*)((|userPassword=*) Что общего между ними? Анатомия атак инъекций
  • 58. 1' AND 1=(SELECT COUNT(*) FROM tablenames); -- '><script>alert/XSS/</script><!-- ../../../../../../../etc/passwd%00 admin*)((|userPassword=*) Атакующие используют синтаксические элементы основной грамматики, чтобы выбраться за пределы острова и нарушить целостность потока выполнения принимающей стороны Анатомия инъекций
  • 59. Какой грамматике соответствует запрос: SELECT * FROM Table WHERE Id={:int} ? Островные языки
  • 60. select stmt ::= SELECT select list from clause | SELECT select list from clause where clause select list ::= id list | * id list ::= id | id , id list from clause ::= FROM tbl list tbl list ::= id list where clause ::= WHERE bool cond bcond ::= bcond OR bterm | bterm bterm ::= bterm AND bfactor | bfactor bfactor ::= NOT cond | cond cond ::= value comp value value ::= id | str lit | num str lit ::= ' lit ' comp ::= = | < | > | <= | >= | != … (+ еще ~1000 страниц отборной EBNF) Контекстно-свободная SQL?
  • 61. SELECT * FROM Table WHERE Id=[0-9]+ Море Остров Явное выделение всех островных грамматик облегчает реализацию контроля выходных данных Чтобы реализовать достаточный и эффективный контроль выходных данных, в общем случае, необходимо взять из основной островной грамматики правила, описывающие разбор токена, в который попадают входные данные и обеспечить невозможность их выхода за пределы этого токена. Регулярная, островная!
  • 62. Пример: LINQ Injection public AjaxStoreResult GetCustomers(int limit, int start, string dir, string sort) { var query = (from c in this.DBContext.Customers select new { c.CustomerID, c.CompanyName, c.ContactName, c.Phone, c.Fax, c.Region }).OrderBy(string.Concat(sort, " ", dir)); int total = query.ToList().Count; query = query.Skip(start).Take(limit); return new AjaxStoreResult(query, total); }
  • 63. Пример: LINQ Injection public AjaxStoreResult GetCustomers(int limit, int start, string dir, string sort) { var query = (from c in this.DBContext.Customers select new { c.CustomerID, c.CompanyName, c.ContactName, c.Phone, c.Fax, c.Region }).OrderBy(string.Concat(sort, " ", dir)); int total = query.ToList().Count; query = query.Skip(start).Take(limit); return new AjaxStoreResult(query, total); }
  • 64. Пример: LINQ Injection public AjaxStoreResult GetCustomers(int limit, int start, string dir, string sort) { if (!Regex.IsMatch(dir, "(?-m:)(?i:)^asc|desc$")) { dir = "ASC"; } if (!Regex.IsMatch(sort, "(?-m:)(?i:)^customerid|companyname|contactname|phone|fax|region$")) { sort = "CustomerID"; } var query = (from c in this.DBContext.Customers select new { c.CustomerID, c.CompanyName, c.ContactName, c.Phone, c.Fax, c.Region }).OrderBy(string.Concat(sort, " ", dir)); var total = query.ToList().Count; query = query.Skip(start).Take(limit); return new AjaxStoreResult(query, total); }