— Можно ли говорить, что работавшие на выборах в Москве 8 сентября 2013 года КОИБы были начинены именно тем кодом, который раскопали юзеры на сайте госзакупок и обсуждают на «Хабре»?
Утверждать это со стопроцентной уверенностью мы не можем, потому что вполне вероятно, что с тех пор программа видоизменялась, в нее были добавлены или удалены какие-то возможности, исправлены какие-то ошибки. Тем не менее фундаментальное устройство программы, которое программисты называют архитектурой, изменить весьма непросто. Для этого надо потратить очень много ресурсов: заново реализовать многие программные модули, внести капитальные изменения в оставшиеся части программы, заново пройти все этапы тестирования, найти множество ошибок, исправить их, потом снова тестирование и, наконец, сертификация и приемка. Это очень долгий и дорогостоящий процесс. Поэтому без особых причин таких серьезных изменений разработчики всегда стараются избегать. Это дает основания полагать, что современные КОИБы работают на том же или незначительно измененном программном обеспечении. Достоверно известно, что на выборах мэра 8 сентября 2013 года использовались КОИБ-2010. Именно программный код КОИБа-2010 мы и анализировали, найдя его на сайте госзакупок.
— Какие уязвимости в программном коде КОИБов видны вам как программисту? Есть ли возможности для манипуляций и фальсификаций результатов голосования?
Я не стану утверждать, что описанная ниже уязвимость — это намеренно оставленный бэкдор, лазейка для посвященных. Вполне возможно, что это просто промах разработчиков. Но учитывая, что код КОИБов проходил аудит на соответствие требованиям безопасности, это уже двойной промах — и разработчиков, и аудиторов. Что наводит на мысли о том, что все так и было задумано.
Если говорить техническим языком, то найденная уязвимость относится к классу code injection. Она позволяет в момент формирования итогового протокола при помощи специальным образом подготовленных для КОИБ исходных данных выполнить на компьютере, встроенном в КОИБ, произвольный код. В том числе и такой, который изменит количество голосов, отданных за кандидатов. Утром в день голосования председатель УИК вставляет в КОИБ «ключевой носитель», представляющий собой обычную флешку, которую заранее выдают в вышестоящей комиссии. На этой флешке сохраняется XML-файл с полной информацией о выборах: когда начинается и заканчивается голосование, какой есть список кандидатов, какого формата бюллетени и много других данных. Примеры записей взяты из технического задания, которое было размещено на госзакупках:
Однако кроме вышеперечисленных (очевидных) параметров в том же файле сохраняется информация о правилах заполнения протокола: сколько в нем строк, какой текст должен быть написан в этих строках, по каким формулам вычисляются числовые значения и так далее.
Взглянем на пример исходных данных, по которым КОИБ формирует строки протокола:
Код, который выполняет замену строк типа {BlankType=NoMarks,VotingMode=Portable} на соответствующий им программный код, находится в файле Common/Voting/Line.cs. Затем после подстановки значений код передается в компилятор C# (Common/Voting/SourceData.cs строка 434), где он будет скомпилирован и отложен до окончания голосования. Когда голосование заканчивается и формируется протокол, строка за строкой скомпилированная программа выполняется (Common/Voting/Line.cs, строка 262). Здесь-то и оказалась запрятана уязвимость. В формулу можно подставить вызов любой функции, в том числе которая будет менять итоги выборов:
Managers.VotingResultManager.VotingResults.SetNewVotesValue(111, 100500)
Например, таким образом можно проставить кандидату #111 (из примера выше) 100 500 голосов. Кому-то добавить, кому-то отнять. Причем логику прописать любой сложности, которая будет проверять текущий процент за каждого из кандидатов, принимать решение, сколько голосов перекинуть и так далее. Понятно, что просто добавить голосов какому-то кандидату не получится — в протоколе не сойдется общее количество бюллетеней, и подтасовка сразу будет видна. А перекинуть некоторое число голосов с одного кандидата на другого — беспроигрышный вариант. Никаким контролем, кроме ручного пересчета, обнаружить эту фальсификацию будет невозможно. Де-факто выходит, что, не нарушая целостности пломб на КОИБе, можно повлиять на результат голосования.
— Как непосредственно это можно сделать?
В программном коде КОИБа есть описанная выше логика, позволяющая исполнять программный код с флешки. Само по себе это очень серьезная дыра в безопасности. Однако для того чтобы воспользоваться таким способом фальсификации, нужно, чтобы подмененные данные каким-либо образом попали в КОИБ.
Согласно инструкции по эксплуатации КОИБ, с утра в день голосования оператор должен включить КОИБ и загрузить в него исходные данные: «После запроса «Вставьте Flash» вставить ключевой носитель в главное сканирующее устройство (сканирующее устройство, к которому подключен принтер) и нажать клавишу «ДА» на задней панели сканирующего устройства. После этого на информационном табло главного сканирующего устройства появится сообщение «Загрузка исходных данных...».
Ключевой носитель (флешка) выдается председателю УИК накануне выборов в вышестоящей ТИК, чтобы можно было провести тестовое включение КОИБ, убедиться в его работоспособности. Ответственность за сохранность ключа с этого момента лежит на председателе УИК. Но самое интересное, что закон даже не требует от него хранить ключ-флешку в сейфе! Председатель может взять ключ домой и внести в него нужные изменения.
Хотя я не исключаю, что для сохранения данных «от председателей» используются и дополнительные уровни защиты, которые сделают такую «лобовую» атаку невозможной. Например, флешка, на которой хранятся данные, вполне может содержать в себе криптоконтейнер, например, выпускаемый какой-либо отечественной компанией, который не позволит посторонним лицам (председателю УИК) подменить данные.
Однако никакого контроля со стороны наблюдателей за тем, кто имеет право шифровать и подписывать исходные данные для флешек, законодательно не установлено. Это значит, что лица, которые имеют доступ к криптографическим ключам, все равно могут изменить данные так, как им заблагорассудится. Какая бы совершенная криптосистема ни использовалась, все равно ее стойкость ограничена уровнем доверия к тем, кто формирует исходные данные. Пусть их готовит хоть сама ЦИК. Кто может гарантировать, что вводимые ею исходные данные кристально честные?
— Может быть, просто КОИБ делали немножечко криворукие программисты без всякого злого умысла?
В технических требованиях ЦИКа к КОИБам сказано: «КОИБ-2010 должен иметь действующий сертификат соответствия Федеральной службы по техническому и экспортному контролю по требованиям безопасности информации (в части контроля отсутствия недекларированных возможностей в специальном программном обеспечении)». А также: «Встроенное предустановленное специальное программное обеспечение КОИБ-2010 входит в стоимость изделия на условиях бессрочной лицензии с ежегодным обновлением, при необходимости, в рамках технической поддержки». Выводы о криворукости либо об умысле можете делать сами.
— А кто автор-исполнитель этого интересного кода для КОИБа?
В исходниках кода через строчку написано, что разработчики — КРОК:
[assembly: AssemblyCompany(\"Croc inc.\")]
[assembly: AssemblyProduct(\"Croc.Bpc.Workflow\")]
[assembly: AssemblyCopyright(\"Copyright © Croc inc. 2010\")]
Но это все, понятно, ерунда, так как вписать что угодно можно. Однако более весомое подтверждение, что это дело именно их рук, — участие КРОК в аукционе на право изготовления КОИБов. Собственно, КРОК и не скрывает, что плотно работает с ЦИКом и осуществляет, например, даже сервисную и техническую поддержку системы ГАС «Выборы».
— Понятно. Итак, как же может выглядеть фальсификация результатов голосования с использованием выявленных в программном коде КОИБа скрытых возможностей?
Способ фальсификации может выглядеть так: голосование идет без каких-либо видимых нарушений — нет никаких огромных дополнительных списков, каруселей, вбросов, массового голосования на дому. А когда голосование заканчивается, КОИБ выдает результат, где соотношение голосов перераспределено в пользу нужного кандидата. Все происходило на глазах у наблюдателей, комар носа не подточит — никаких оснований для ручного пересчета голосов нет. Ничего не подозревающие наблюдатели вынуждены согласиться, что выборы прошли честно.
Чтобы защититься от «заряженных» КОИБов, законодательство предусматривает обязательный ручной пересчет голосов на 5 процентов участков, выбираемых жребием. Как бы на месте жуликов сделать так, чтобы КОИБы, где будет ручной пересчет, показали правильный результат, а все остальные 95 процентов — «нужный»? Как бы подать сигнал КОИБу, что вот тут считай правильно, а тут можно жульничать? Идея! А давайте сделаем так: если КОИБ перезагрузят перед тем, как распечатывать протокол, то будем считать честно. А если не перезагрузят, то «как надо». Сделать это очень просто: например, как только станет известно, что пересчет будет на участке N, мы звоним доверенному лицу на участке и просим его выключить рубильник на минутку. Ну или кто-то о кабель питания «случайно» споткнется. КОИБ перезагрузится и выдаст правильный протокол. Перезагрузка КОИБа — это самое простое решение на такой случай. Кстати, в этот момент можно и ключевой носитель (флешку) подменить. Ведь председатель должен достать его из кармана (или где он там его хранит) и снова после перезагрузки вставить в КОИБ. Ему могут выдать два ключа: один честный, другой нет. И инструкция — в случае проблем с наблюдателями, пересчетом и т.д. перезагрузить КОИБ и вставить честный ключ.
Противодействовать этому можно только одним способом: сначала все КОИБы выдают электронные протоколы, которые подписываются членами УИК, и с них снимаются копии для наблюдателей, а только потом производится жеребьевка, выбираются участки для ручного пересчета и, собственно, производится пересчет. В таком случае можно будет реально удостовериться в честности КОИБа.
— То есть нынешних мер обеспечения честности голосования с помощью КОИБ недостаточно?
Их явно недостаточно. Вот пример алгоритма фальсификации, который построен на основании выявленных уязвимостей программного кода КОИБа. Уполномоченные лица (из ЦИК, ТИК или другой организации, кто готовит исходные данные для КОИБ) загружают на ключевой носитель исходные данные, которые при выполнении каких-либо внешних условий будут выполнять фальсификацию. Таким условием может быть, например, отсутствие перезагрузок с момента включения КОИБ или определенное время. Скажем, если протокол снимается в первой половине часа, то фальсификации не будет, а если во второй — то будет. Найденная уязвимость позволяет описать программную логику любой сложности.
Председателю УИК дается инструкция, что если ему будет объявлено о проведении ручного пересчета на участке, то необходимо протокол с КОИБ снять в первой половине часа. Тогда данные будут честными. Если ручного пересчета не будет, то под любым предлогом задержать снятие протокола до второй половины часа.
Косвенными признаками того, что на вашем участке могла быть такая фальсификация, являются: необъяснимые задержки в снятии протокола с КОИБ, внезапные отключения света перед снятием протокола с КОИБ, какие-либо другие нелогичные действия комиссии по отношению к КОИБ перед снятием протокола (перезагрузка, переключение шнуров), настоящей целью которых является подать сигнал КОИБу, как он должен считать — честно или нет.
— Другой вопрос, который волнует в связи с КОИБами: не нарушается ли КОИБом тайна голосования, если учесть, что он фиксирует время и отданный голос избирателя с ведущейся одновременно видеосъемкой голосования?
Действительно, после обработки бюллетеня КОИБ формирует запись об этом (Recognizer/RecognitionManager.cs, строка 744):
"Бюллетень N {0} {1}. Печать: {2}. {3}. Время: {4}",
И заносит ее в журнал (Recognizer/RecognitionManager.cs, строка 616):
WriteRecognitionResultToLog(recResult, stampResult, stampNumber, recLogAddInfoSb.ToString());
Учитывая, что время {4} фиксируется с точностью до тысячной доли секунды (Recognizer/RecognitionManager.cs, строка 750):
DateTime.Now.ToString("HH:mm:ss.fff"));
Это позволяет со стопроцентной точностью соотнести бюллетень с изображением человека с видеокамеры.
Стоит уточнить, что в системах, подключенных к Интернету, время обычно синхронизируется со службами точного времени. Но КОИБ ни к чему не подключен, и часы на нем выставляются вручную через меню оператора. Однако при желании сопоставить время КОИБ и время видеорегистратора все равно, конечно, можно. Посмотрели на видео — кто-то опустил бюллетень в 15:20:21, и в это время никто больше не опускал (ни до, ни после). Нашли эту запись в журнале КОИБ — там она зафиксирована, допустим, в 15:19:38. Вычислили разницу во времени между КОИБ и камерой — 43 секунды, и дальше с учетом этого можно точно все остальные бюллетени опознать.
— Если видеотрансляция с участка идет в открытом доступе в Интернете, то кто может иметь доступ к журналу времени и «качества» голосования КОИБа? То есть кто может выяснить, как голосовал конкретный человек, сопоставив видео и записи журнала?
Учитывая, что эти данные на ключевой носитель не записываются, их можно будет получить только после выборов, подключившись к встроенным в КОИБ компьютерам. Доступом к компьютерам как минимум обладают техники, проводящие наладку, диагностику и ремонт КОИБов. Также, скорее всего, доступ есть и у сотрудников вышестоящих избирательных комиссий, поскольку извлечение данных из КОИБов может потребоваться для проведения разбирательств-проверок. Ну и, наверное, доступ к этой информации могут получить спецслужбы в рамках имеющихся у них компетенций.
— Можно ли вообще организовать чистое и честное голосование с КОИБами технически? Это должен быть open-source-код у КОИБов, чтобы все желающие могли спокойно его проверять, а не выискивать следы в госзакупках?
Делать КОИБ с открытыми исходниками бесполезно, поскольку никаким образом перед голосованием проверить, что в КОИБ загружен именно тот код, что выложен на всеобщее обозрение, нельзя. Хотя в целом, на мой взгляд, КОИБ — отличное решение, чтобы автоматически проверять подлинность бюллетеней, препятствовать вбросу пачек в урну, проводить альтернативный, не зависящий от людей подсчет голосов. Однако чтобы организовать чистое и честное голосование, необходимо на каждом участке считать голоса и при помощи КОИБов, и вручную. Ручной пересчет даст гарантию, что КОИБ не мухлевал с голосами, а КОИБ даст гарантию, что комиссия не будет перекладывать бюллетени из одной стопки в другую, сбегать с неподписанными протоколами, топить бюллетени в луже и так далее. Процедура должна требовать посчитать все вручную, а затем распечатать протокол из КОИБ. Если не сошлось, пересчитывать вручную еще раз. Если по-прежнему не сошлось, в обязательном порядке фиксировать нарушение.
Резюмируя, есть два варианта организации честного голосования. Первый — когда пересчитываются только 5 процентов участков. Тогда критически важно, чтобы сначала вышел протокол из КОИБ, а потом была жеребьевка. Так у комиссии не будет возможности сообщить КОИБу, чтобы он считал честно. Второй вариант — обязательный ручной пересчет всех участков. Тогда никакой разницы нет, что будет сначала: ручной подсчет или снятие электронного протокола.
Материал подготовили: Алексей Барановский, Евгений Порошин, Мария Пономарева
Комментарии