offtop: про таинтизмы понятным языком (имхо)
Watcher 24.10.2019 01:59
0. Схема:
У запущенного скрипта есть входные, внутренние и выходные данные.
Т.е.условно поток выглядит так, и с точки зрения обработки потока всех данных
есть 3 основные фазы:
IN - накопление/получение входных данных за все время работы скрипта
RUNTIME - какая-то работа с данными в процессе работы скрипта
OUT - вывод/отдача данных в самом конце(!) после отработки скрипта
read-files --+ (RUNTIME) +-- write-files
http-forms/get --+-> (IN) script.p (OUT) >-+-- http-response
sql-result --+ +-- sql-query
... ...
Схема построена так, что все строковые(!) данные полученные извне (т.е. незахардкоденные руками в коде, в виде значений переменных или html-текста прям в скрипте руками программиста) по-умолчанию нуждаются в "карантине" чтобы потом если какие-то входные данные или их кусочки попадут в OUT, то они не просачивались как-есть (as-is), а автоматически или кастомно подвергались преобразованию (экранировнию) дабы превентивно избегать xss-уязвимостей.
Механизм реализован так, что во время всей работы скрипта, он накапливает входные данные из внешних источников, и все эти входные данные "невидимо"(для кода) помечаются (маркируются), и только перед непосредственной отдачей во вне, эти данные мгновенно преобразуются (экранирование/замена опасных символов).
Если ничего кастомно не трогать, то по-умолчанию данные(строки/стринги) из всех внешних источников автоматически красятся в "dirty" - неопределенно грязные или т.н. "общий автоматический случай".
Все входные данные, которые получили невидимую маркировку типа "dirty" перед отдачей будут преобразованы по правилу этого общего случая, которое состоит в том, что парсер сам автоматически выберет преобразование нужного типа под конкретные входные/выходные источники.
Но(!) если кодер хочет немного подстроить маркировку входных данных(строк), чтобы получить на выход более желаемое преобразование, он может принудительно перекрасить "dirty" в какой-то ручной тип маркировки типа file-spec или url, чтобы экранировалось и заменялось всё не по правилу общего случая, а по конкретному. А может вообще очистить от какой бы то ни было маркировки (as-is)
И еще главное! Весь этот механизм работает только(!) со строками и подстроками. Т.е. весь этот винегрет маркировок живет только внутри стрингов, причем по-символьно, т.е. над каждым символом стринга (невидимо висит маркер определенного типа или его отсутствие).
А теперь собсна, сами операторы для работы со всем этим механизмом:
1. Все входные извне стринги автоматически красятся в маркер общего случая (dirty) *документация Парсера его называет tainted чтоб вы запутались с самого начала.
2. Оператор ^taint[тип][string] красит строку в заданный тип, если тип не указать то по-умолчанию покрасит в dirty. По сути надо, чтобы или перекрасить обратно в dirty то, что где-то по коду красили в другое. Или по какой-то причине покрасить часть ваших захардкоденных стрингов в грязные по общему случаю (ну мало ли). Если надо просто почистить от каких бы то ни было маркировок строку, то в качестве типа указываем тип "as-is", т.е. оставить данные как-есть, и снять маркировку.
3. Оператор ^untaint[тип]{string} - делает практически то же самое, но красит не всю указанную строку, а только те символы из строки, которые уже выкрашены в именно цвет dirty (грязный по общему случаю). Ну и чтобы вы окончательно и бесповоротно запутались, то ли историческая сырость первых версий, то ли какие-то нереализованные задумки раннего авторства (PAF'a) -- предлагают вам синтаксис с фигурными скобками и словом (код) в качестве аргумента.
На самом деле это баг, который не влияет на работу. Таинтизмы работают только(!) со строками, передавать код в качестве аргумента не имеет никакого смысла. Просто оно как бы работает, потому что и строки в этом вашем коде тоже есть, а просто строка это как бы тоже код по канонам парсера.
Поэтому, в уме просто представьте несуществующий, но более логический синтаксис ^untaint[тип][string], а еще лучше ^taint[тип][string][but-only-for-dirty-parts]
Т.е. ^untaint не обратная операция по отношению к ^taint, это просто такой же taint но применяемый не ко всей строке принудительно, а выборочно только для dirty-цвета.
4. Dirty-цвет в документации называют tainted - чтоб уж добить молодого бойца с гарантией :) Видите цвет tainted (в уме говорите dirty, чтобы не путать с оператором)
5. Оператор ^apply-taint[тип][строка] - применяет преобразование со строкой сразу по коду, в то время как обычный taint делает реальное преобразование стрингов(строк) только неподсрественно при отдаче во вне.
6. Каждый символ каждой строки в процессе скрипта несет свой индивидуальный маркер или его отсутствие.
Таким образом, получив кучу строк из нескольких источников, часть из которых, будут автоматически покрашены в dirty, часть, например, вы подкрасите в нужный цвет, и часть будут чистыми изначально, и потом где-то в коде все это многократно смешается, например в одну строку, той же банальной конкатенацией, то в итоге вы получите "стринг-винегрет" где каждый кусок строки, а точнее символ будет выкрашен в свой цвет. В этом собственно и суть удержания контроля над грязностью данных.
$a[$form:a] <- это автоматически в dirty-цвете
$b[^taint[url][http://site]] <- это вручную в url-цвете
$c[hello] <- это в as-is цвете, т.е. значение забито кодером
$d[$a$b$c] <- эта "колбаса" сохранит все цвета составных строк посимвольно
т.е. будет состоять из dirty,url и as-is цвета.
^untaint{$d} <- перекрасит в as-is только те куски строки (символы), которые были dirty-цвета.
в итоге строковая "колбаса" будет состоять из символов as-is и url-цветов (маркеров).
P.S.: Надеюсь не запутал еще сильнее ))
- offtop: про таинтизмы понятным языком (имхо), Watcher 24.10.2019 01:59