Исследуем «Ревизор» Роскомнадзора

от автора

ФСБшник хороший

Ревизор — программно±аппаратный комплекс для мониторинга доступа к сайтам из реестра со стороны провайдеров — берет свое начало в октябре 2015 года, когда компания «МФИ Софт», та же компания, что сделала СОРМы, выиграла тендер на разработку ПО за 84 миллиона рублей. Согласно условиям тендера, разработчик должен был предоставить работоспособное ПО под Windows и Linux и 700 аппаратных «Агентов» в срок до 14.12.2015, всего через 2.5 месяца, и, похоже, все было готово даже на пару недель раньше дедлайна. Провайдерам в добровольно-принудительном порядке уже в начале декабря предлагалось установить один из трех вариантов Ревизора: в виде образа виртуальной машины VMWare, основанной на OpenWRT 14.07, в виде программы-сервиса под Windows, либо же в виде железного «Агента», который представлял из себя маршрутизатор TP-Link MR3020 с установленным на него OpenWRT и необходимым ПО. Многие провайдеры отказывались от установки комплекса из-за того, что он не сертифицирован, а использоваться будет только им во вред, а другим устройств просто не досталось, и им пришлось установить софтовую версию.

Итак, у меня в руках последняя версия VMWare-образа и exe-файла Ревизора. Давайте же посмотрим, что внутри!
image

Исследование образа VM

Первым делом, образ я переконвертировал в RAW, чтобы иметь возможность просто подмонтировать его, не запуская в вирутальной машине. Для этого есть замечательная утилита в составе qemu, qemu-img, которая умеет конвертировать все популярные форматы образов виртуальных машин между собой:

$ qemu-img convert -O raw ra-wrt-x86-disk1.vmdk rev-clean.raw

Подмонтировать файл образа нам поможет прекрасная программа kpartx из пакета multipath-tools, которая умеет анализировать образ и делать все автоматически, иначе нам бы пришлось монтировать каждый раздел вручную, указывая его смещение, что очень неудобно:

$ sudo kpartx -a rev-clean.raw

Нас встречают два раздела с файловыми системами ext2 и ext4:

                         Disk: /dev/loop1           Size: 52.5 MiB, 55050240 bytes, 107520 sectors                 Label: dos, identifier: 0x00000000      Device         Boot    Start     End  Sectors  Size  Id Type >>  /dev/loop1p1   *         512    8703     8192    4M  83 Linux       /dev/loop1p2            9216  107519    98304   48M  83 Linux 

Первый раздел — загрузочный, монтируется в /boot. На нем находится Grub2 и ядро. Ничего интересного.
Второй раздел представляет из себя файловую систему OpenWRT. Каким образом нам найти отличия от штатной сборки OpenWRT? Элементарно — по дате изменения файлов!

Скрытый текст

2014-04-10+18:34:34.0000000000  ./lib/firmware/rtl_nic/rtl8105e-1.fw 2014-04-10+18:34:34.0000000000  ./lib/firmware/rtl_nic/rtl8106e-1.fw 2014-04-10+18:34:34.0000000000  ./lib/firmware/rtl_nic/rtl8106e-2.fw 2014-04-10+18:34:34.0000000000  ./lib/firmware/rtl_nic/rtl8168d-1.fw … 2014-09-16+23:45:16.0000000000  ./lib/netifd/netifd-proto.sh 2014-09-16+23:45:16.0000000000  ./lib/netifd/netifd-wireless.sh 2014-09-16+23:45:16.0000000000  ./lib/netifd/utils.sh 2014-09-21+14:46:54.0000000000  ./bin/ipcalc.sh … 2015-10-23+12:04:49.0000000000  ./bin/revizor_postboot 2015-10-23+12:04:49.0000000000  ./bin/revizor_postupdate 2015-10-23+12:04:49.0000000000  ./dev 2015-10-23+12:04:49.0000000000  ./dev/console 2015-10-23+12:04:49.0000000000  ./etc/agent_id 2015-10-23+12:04:49.0000000000  ./etc/config/dropbear 2015-10-23+12:04:49.0000000000  ./etc/dropbear/dropbear_dss_host_key 2015-10-23+12:04:49.0000000000  ./etc/dropbear/dropbear_rsa_host_key 2015-10-23+12:04:49.0000000000  ./etc/opkg.conf 2015-10-23+12:04:49.0000000000  ./etc/shadow 2015-10-23+12:04:49.0000000000  ./etc/shells 2015-10-23+12:04:49.0000000000  ./etc/ssl 2015-10-23+12:04:49.0000000000  ./etc/ssl/certs 2015-10-23+12:04:49.0000000000  ./etc/ssl/certs/revizor_opkg.crt 2015-10-23+12:04:49.0000000000  ./root 2015-10-23+12:04:49.0000000000  ./root/.ssh 2015-10-23+12:04:49.0000000000  ./root/.ssh/id_rsa 2015-10-23+14:49:17.0000000000  ./etc/crontabs 2015-10-23+14:49:17.0000000000  ./etc/crontabs/root 2015-10-23+14:49:17.0000000000  ./etc/revizor_server 2015-10-29+14:27:19.0000000000  ./bin/revizor_boot 2015-10-29+14:27:19.0000000000  ./etc/config/network 2015-10-29+14:27:19.0000000000  ./etc/netfallback.conf 2015-10-29+14:27:19.0000000000  ./etc/rc.local 2015-11-03+15:43:21.0000000000  ./etc/init.d/dropbear 2015-11-03+15:43:21.0000000000  ./usr/lib/opkg/info/dropbear.conffiles 2015-11-03+15:43:21.0000000000  ./usr/lib/opkg/info/dropbear.control 2015-11-03+15:43:21.0000000000  ./usr/sbin/dropbear 2015-11-03+17:05:22.0000000000  ./bin/admin/admsrv 2015-11-03+17:05:22.0000000000  ./bin/revizor_logger 2015-11-03+17:05:22.0000000000  ./bin/revizor_preboot 2015-11-03+17:05:22.0000000000  ./etc/passwd 2015-11-09+17:10:52.0000000000  ./bin 2015-11-09+17:10:52.0000000000  ./bin/admin/admcli 2015-11-09+17:10:52.0000000000  ./bin/revizor_updater 2015-11-09+17:10:52.0000000000  ./etc/config 2015-11-09+17:10:52.0000000000  ./etc/config/system 2015-11-09+17:10:52.0000000000  ./etc/dropbear 2015-11-09+17:10:52.0000000000  ./etc/dropbear/authorized_keys 2015-11-09+17:10:52.0000000000  ./etc/inittab 2015-11-13+12:06:31.0000000000  ./bin/admin/netfallback 2015-11-16+15:31:23.0000000000  ./bin/admin 2015-11-16+15:31:23.0000000000  ./bin/admin/pwd-sh 2016-02-09+11:09:52.0000000000  ./etc 2016-02-09+11:09:52.0000000000  ./etc/revizor_firmware_version 2016-02-09+11:09:53.0000000000  ./bin/ash 2016-02-09+11:09:53.0000000000  ./bin/cat 2016-02-09+11:09:53.0000000000  ./bin/chgrp …

Можем проследить процесс создания образа: первые файлы появились 23 октября, затем файлов докидывали в течение ноября, и, похоже, 16 ноября появился готовый базовый образ, который обновили и кастомизировали 9 февраля.

Процесс загрузки скриптов, относящихся к Ревизору, сделан небрежно — они просто добавлены в /etc/rc.local:

# Put your custom commands here that should be executed once # the system init finished. By default this file does nothing.  /bin/admin/admsrv & /bin/admin/netfallback & /bin/revizor_boot & exit 0

/bin/admin/admsrv меняет пароль пользователя admin путем хеширования первой строки файла /etc/agent_id, который уникальный для каждой виртуальной машины и устройства (вида DICK-BUTT-I386), без первого символа, алгоритмом MD5, и обрезает полученный хеш до 12 символов, который и будет паролем. В самом же файле /etc/agent_id защита от дурака — 28 переносов строк, которые не влезут в стандартный терминал размером 80×24. Вероятно, предполагается, что кто-то не знает про Shift+PgUp/PgDown. Этот же скрипт запускает SSH-сервер (dropbear) на порту 2222, доступный извне, на 2 минуты после старта.

Скрытый текст

#!/bin/sh  sleep 2 chmod a+rw /etc/opkg.conf chmod a+rw /etc/netfallback.conf  ADMIN_PORT=2222 ADMIN_TIMEOUT=120  read ADMIN_PWD </etc/agent_id if [ ! -z ADMIN_PWD ]; then   ADMIN_PWD=`echo $ADMIN_PWD | tail -c +2 | md5sum | head -c 12`   if [ ! -z ADMIN_PWD ]; then     echo "admin password: $ADMIN_PWD" | revizor_logger     echo -e "$ADMIN_PWD\n$ADMIN_PWD" | passwd admin   fi fi  /usr/sbin/dropbear -F -p 0.0.0.0:$ADMIN_PORT -n -K 30 -I 300 & PID=$!  sleep $ADMIN_TIMEOUT kill -9 $PID

В скрипте /bin/admin/netfallback происходит непотребство — если через 5 секунд после загрузки Ревизор не получил IP-адрес от DHCP-сервера, он устанавливает статический адрес 192.168.0.254, и далее в цикле каждые 30 секунд пытается понять, не появился ли DHCP-сервер и не выдал ли он нам IP-адрес.
Отвечающий за загрузку ПО скрипт /bin/revizor_boot добавляет собственный репозиторий в файл пакетного менеджера opkg.conf, запускает процесс обновления и стартует cron, в котором настроена проверка обновлений каждые 15 минут. Другие репозитории отсутствуют.

Скрытый текст

#!/bin/sh  if [ ! -f /rom/etc/opkg.conf ]; then   read REVIZOR_SERVER </etc/revizor_server   if [ -z "$REVIZOR_SERVER" ]; then     REVIZOR_SERVER="revizor.mfisoft.ru"   fi    mkdir -p /rom/etc   OPKG_CFG=`cat /etc/opkg.conf | grep -v '^src revizor '`   echo "$OPKG_CFG" > /rom/etc/opkg.conf   echo "src revizor https://$REVIZOR_SERVER/updates/openwrt-x86/common" >> /rom/etc/opkg.conf   cp -f /rom/etc/opkg.conf /etc/opkg.conf fi  rm -f /usr/lib/opkg/lock /bin/revizor_preboot  sleep 2 /bin/revizor_updater -f /rom/etc/opkg.conf  /etc/init.d/cron start /bin/revizor_postboot

Файлы /bin/revizor_preboot и /bin/revizor_postboot пусты.

Скрипт /bin/admin/pwd-sh, который используется в качестве логин-шелла (прописан в /etc/inittab для tty1 и ttyS0), использует крайне необычную технику входа — запуск SSH-клиента на localhost. Дело в том, что OpenWRT используется преимущественно в домашних роутерах, у которых нет ни экрана, ни легкого доступа к параллельному порту, поэтому пароль на доступ просто не нужен. В случае Ревизора это бы означало, что любой может получить root-доступ, просто нажав Enter для активации консоли в виртуальной машине. Как правило, для осуществления логина используют программы вроде getty, вы их видели в любом дистрибутиве, именно getty спрашивает и проверяет логин и пароль. Здесь же, по какой-то причине, разработчики не стали устанавливать getty, а просто подключались к самому себе через SSH, ведь SSH-сервер запросит аутентификацию. Поначалу я думал, что сделано это не просто так, что таким образом захотели хитро отключить вход из-под пользователя root, но нет, SSH-сервер настроен самым обычным образом.

Шеллом для пользователя admin задан скрипт /bin/admin/admcli, который позволяет выполнять следующие команды:

system reboot system resetfs system update log info ifconfig route arp ping nslookup traceroute net proxy clear net proxy set net fallback

Пакеты из репозитория подписываются ключом «МФИ Софт», подпись проверяется средствами opkg:

Скрытый текст

Certificate:     Data:         Version: 3 (0x2)         Serial Number: 12303214825491704792 (0xaabdccb2d4c0abd8)     Signature Algorithm: sha256WithRSAEncryption         Issuer: C=RU, ST=Russia, O=MFISOFT         Validity             Not Before: Oct 21 10:21:46 2015 GMT             Not After : Aug  5 10:21:46 2289 GMT         Subject: C=RU, ST=Russia, O=MFISOFT         Subject Public Key Info:             Public Key Algorithm: rsaEncryption                 Public-Key: (1024 bit)                 Modulus:                     00:cc:ed:e0:84:c4:7b:4e:49:2d:11:86:41:0f:f8:                     51:97:42:91:76:34:38:96:e0:9e:a4:3c:7b:30:f6:                     15:b2:1e:03:0e:12:46:96:f9:57:a1:db:2d:63:8a:                     dc:01:2e:e7:10:56:8d:c3:d5:de:5a:bb:d7:75:e3:                     6b:e3:d5:6a:04:4d:f4:65:81:05:07:d7:d0:a8:29:                     ab:9d:83:81:00:04:73:27:39:db:d3:c8:ba:d3:78:                     41:84:d9:8b:62:21:00:51:fc:78:06:ce:f7:db:e6:                     5b:fd:d7:b6:2b:0f:72:9e:63:d8:06:f1:dd:2d:c5:                     17:f1:a9:b8:d3:5e:ad:6c:d5                 Exponent: 65537 (0x10001)         X509v3 extensions:             X509v3 Subject Key Identifier:                  F6:F9:BB:39:1B:20:4F:B4:11:B5:CE:EA:C2:F5:95:DB:24:DB:49:53             X509v3 Authority Key Identifier:                  keyid:F6:F9:BB:39:1B:20:4F:B4:11:B5:CE:EA:C2:F5:95:DB:24:DB:49:53              X509v3 Basic Constraints:                  CA:TRUE     Signature Algorithm: sha256WithRSAEncryption          16:31:a0:2f:01:1b:06:a3:31:d3:d2:50:38:b4:c2:57:ec:6d:          a0:25:5e:e0:35:68:92:dd:38:fc:1a:ef:88:2d:e8:b9:1b:d7:          f5:ef:97:14:75:ef:65:1c:f9:ae:61:43:05:49:74:08:8a:d5:          19:01:e3:63:ff:69:57:34:74:9e:b8:7d:6d:5b:2a:66:59:a6:          9d:b4:a3:3f:41:91:30:26:1f:0e:3a:24:2b:36:0e:68:f8:e8:          44:f5:5a:18:ea:5e:48:8e:a9:8f:03:25:87:ba:60:9c:93:ac:          cb:43:b7:ee:6d:6c:85:88:77:40:a7:b4:a8:c9:ce:d0:29:6d:          78:0a -----BEGIN CERTIFICATE----- MIICMDCCAZmgAwIBAgIJAKq9zLLUwKvYMA0GCSqGSIb3DQEBCwUAMDAxCzAJBgNV BAYTAlJVMQ8wDQYDVQQIDAZSdXNzaWExEDAOBgNVBAoMB01GSVNPRlQwIBcNMTUx MDIxMTAyMTQ2WhgPMjI4OTA4MDUxMDIxNDZaMDAxCzAJBgNVBAYTAlJVMQ8wDQYD VQQIDAZSdXNzaWExEDAOBgNVBAoMB01GSVNPRlQwgZ8wDQYJKoZIhvcNAQEBBQAD gY0AMIGJAoGBAMzt4ITEe05JLRGGQQ/4UZdCkXY0OJbgnqQ8ezD2FbIeAw4SRpb5 V6HbLWOK3AEu5xBWjcPV3lq713Xja+PVagRN9GWBBQfX0Kgpq52DgQAEcyc529PI utN4QYTZi2IhAFH8eAbO99vmW/3XtisPcp5j2Abx3S3FF/GpuNNerWzVAgMBAAGj UDBOMB0GA1UdDgQWBBT2+bs5GyBPtBG1zurC9ZXbJNtJUzAfBgNVHSMEGDAWgBT2 +bs5GyBPtBG1zurC9ZXbJNtJUzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA A4GBABYxoC8BGwajMdPSUDi0wlfsbaAlXuA1aJLdOPwa74gt6Lkb1/XvlxR172Uc +a5hQwVJdAiK1RkB42P/aVc0dJ64fW1bKmZZpp20oz9BkTAmHw46JCs2Dmj46ET1 WhjqXkiOqY8DJYe6YJyTrMtDt+5tbIWId0CntKjJztApbXgK -----END CERTIFICATE-----

Вход по SSH открыт пользователю, обладающему следующим ключом:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCAxFzEe20FUIegQ8p25S/b1SIhVi0XTWZtLDF7FLpMsoxi+JhgzoVEwmCIpoQ9c5Flid0jiqKCVhnm8GRe+qjkxibAOa8WlfiQ16eapqA0Dd6laFW4RzTTiinebPRlLJBsj8xGhrvf4lsKXng5+ZDWXnrz7pICbh62U7MYNEpOuy9x4P4285Xq9ccIuCrCAS8rZ4TdFdzeM+270asIQB/vsQ2joJ1vNn3WzdISmRepknR4eTo6H881vHAiWVTpGioXssvOGyLYfqn0rqVECC9/tknV0hQJP+iYU3mov4+JYvRVa+5m1DLD0Nj0QWKFXl79VNxstwyOt6RDvQrhlxNB root@revizor-agent

Но где же сам Ревизор?

Обновляемся!

Файлов самого ПО в прошивке нет, они поставляются пакетом из репозитория. Загрузим список пакетов с сайта:
n01.rfc-revizor.ru/updates/openwrt-x86/common/Packages

Как видим, репозиторий содержит один пакет «revizor»:

Package: revizor Version: 1.2.2-34720 Depends: libc, libstdcpp, libpthread, libpcre, libopenssl Section: utils Architecture: x86 MD5Sum: 0afc31c21b785690ca38a89d24d749ed Size: 322098 Filename: revizor_1.2.2-34720_x86.ipk Source: package/revizor Description: revizor agent

Скачаем же его!
n01.rfc-revizor.ru/updates/openwrt-x86/common/revizor_1.2.2-34720_x86.ipk

Файл формата IPK представляет из себя архив .tar.gz со структурой DEB-пакета. Собран он неким abelyak.
image
Внутри пакета имеется несколько скриптов и два исполняемых ELF-файла: revizor-crypto и urlcheck. Первый совсем простой, на данный момент, насколько я понимаю, не используется, и служит для получения публичного ключа из приватного, чтобы использовать его в качестве идентификатора ноды. Файл ключа, который передается в качестве параметра этой утилите, отсутствует, и идентификатор ноды генерируется каждый раз разный.

Перейдем к главному Ревизору — файлу urlcheck. Он написан на C++, динамически слинкован, использует libevent и его OpenSSL-обертку, и обладает нижеперечисленными функциями:

  • Выполнение HTTP/HTTPS GET/POST-запросов по определенному URL
  • Выполнение запросов по определенному URL с заданным IP-адресом (без разрешения доменного имени через DNS)
  • Выполнение нестандартных запросов для обхода DPI: добавление точки в конец домена, двойной слеш в начале URL, экранирование URL
  • Определение факта блокировки сайта путем поиска совпадений регулярного выражения в теле и заголовках ответа сервера
  • Отправка ICMP-запросов к определенному хосту
  • Запуск traceroute до определенного хоста
  • Создание SSH-туннеля до сервера Ревизора для предоставления Socks5-прокси
  • Отправка журнала из syslog на сервер разработчика
  • Перезагрузка устройства

Программа поддерживает IPv6 и работу через прокси.

Общение с сервером Lens, как его называют сами разработчики, происходит по протоколу JSON-RPC, для чего используется URL n01.rfc-revizor.ru/rpclens. Lens отправляет клиенту «задания», которые он должен выполнить. Каждое задание имеет идентификатор, тип, различные опции и параметры. Для проверки заблокированности веб-сайтов сервер передает клиенту белый список адресов, который на данный момент состоит из сайтов ya.ru, google.ru, cbr.ru, gov.ru, hotlog.ru, kremlin.ru, onf.ru, ria.ru, rostelecom.ru, kp.ru, и случайные URL из реестра запрещенных сайтов. Проверка выполняется путем поиска совпадений по регулярным выражениям в теле и заголовке ответа от веб-сайта. Если какие-то ссылки, которые не должны были открыться, не проходят проверки по регулярным выражениям, сервер отсылает запрос на предоставление SSH-туннеля до Socks5-прокси, который поднимается самим urlcheck, чтобы самостоятельно загрузить страницу с помощью curl, проанализировать ее, и сделать скриншот с помощью wkhtmltoimage.
Помимо заданий, сервер также может корректировать настройки Ревизора, например, изменять таймаут подключения и ожидания ответа, ограничивать количество одновременных подключений, устанавливать размер пула потоков для DNS-резолвера.

Развлекаемся!

Хоть общение с API и происходит по протоколу HTTPS, а у сервера имеется сертификат, выданный GeoTrust, Ревизор не выполняет проверку подлинности сертификата, а это значит, что ничто не помешает нам выполнить атаку типа «человек посередине», чтобы прослушивать и модифицировать проходящий трафик. По всей видимости, на сертификаты просто не хватило места в аппаратном решении: в TP-Link MR3020 памяти всего 4 МБ, а образ для x86 не стали переделывать.
Запускаем mitmproxy!

Общение с сервером начинается с команды SetMyParams, в которой клиент передает версию ПО, свой идентификатор агента и случайные 4 цифры в качестве идентификатора сессии.

POST /rpclens HTTP/1.1 Host:            n01.rfc-revizor.ru Connection:      close Content-Length:  176  {"method":"SetMyParams","params":{"version":"WRT-1.2.2.34720","traf":{"duration":3600,"bytes_in":24055,"bytes_out":32636}},"id":"DICK-BUTT-I386---1AE822EF40","session_id":1488}
Server:                  nginx Date:                    Mon, 01 Apr 2016 12:34:56 GMT Content-Type:            text/html Transfer-Encoding:       chunked Connection:              keep-alive X-Powered-By:            PHP/5.2.6 X-Frame-Options:         SAMEORIGIN X-Content-Type-Options:  nosniff  {"jsonrpc":"2.0","result":{"status":"done"},"id":"DICK-BUTT-I386---1AE822EF40"}

Далее происходит вызов GetMyTasks, в ответ на который сервер возвращает какое-то задание для клиента. Вот пример настроек для проверки сайтов:

Скрытый текст

{"method":"GetMyTasks","params":"","id":"DICK-BUTT-I386---1AE822EF40","session_id":1488}

{"jsonrpc":"2.0","result":{"tasks":[{"id_task":"493629","id_task_meta":null,"type":"check","priority":"1","checklist":"own","checklist_count":"2","params":"{\"checklist\":{\"group_id\":1,\"records\":{\"records_type\":2},\"requests\":{\"get\":1,\"post\":0,\"use_dns\":1,\"check_escaped\":0,\"add_slashes\":0,\"add_dot\":0,\"randomize\":0,\"report_success\":0,\"max_redirects\":5,\"use_dns_only\":1,\"all_resolved_ips\":0},\"screenshots\":{\"fail_screenshots\":1,\"skip_if_protocol_exist\":0,\"skip_if_exists_hours\":null,\"skip_if_over\":null,\"only_200\":1,\"skip_3xx\":null}}}","status":"CREATED","completion":null,"result":null,"pass":null,"fail":null,"passed_items":null,"failed_items":null,"id_creator":"WWW-ANUS-PYOS","id_lens":"DICK-BUTT-I386---1AE822EF40","ts_create":"1461299321","ts_start":null,"ts_stop":null}],"params":{"DnsThreadsMax":20,"MAXfailedChecklistDownloadCount":100,"MAXfailedReportUploadCount":25,"whiteCheckMinInterval":60000,"connectTimeout":10000,"soTimeout":10000,"maxTotalConnections":50,"maxHttpsConnections":20,"maxContentSize":3000},"ts":1461299347,"zip":1,"tests":[{"id":1,"statusCode":"200","header":null,"headerRegexp":null,"contentRegexp":"\u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d","content":null},{"id":9,"statusCode":"200","header":null,"headerRegexp":null,"contentRegexp":"\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d","content":null},{"id":2661,"statusCode":"409","header":null,"headerRegexp":null,"contentRegexp":".*","content":null},{"id":2919,"statusCode":"404","header":null,"headerRegexp":null,"contentRegexp":".*","content":null},{"id":2922,"statusCode":"403","header":null,"headerRegexp":null,"contentRegexp":".*","content":null},{"id":2923,"statusCode":"451","header":null,"headerRegexp":null,"contentRegexp":".*","content":null},{"id":2924,"statusCode":"500","header":null,"headerRegexp":null,"contentRegexp":".*","content":null},{"id":2925,"statusCode":"502","header":null,"headerRegexp":null,"contentRegexp":".*","content":null},{"id":2926,"statusCode":"503","header":null,"headerRegexp":null,"contentRegexp":".*","content":null},{"id":2932,"statusCode":"307","header":null,"headerRegexp":null,"contentRegexp":".*","content":null},{"id":2936,"statusCode":"301","header":null,"headerRegexp":null,"contentRegexp":".*","content":null},{"id":2967,"statusCode":"302","header":null,"headerRegexp":null,"contentRegexp":".*","content":null},{"id":2968,"statusCode":"302","header":"Location","headerRegexp":"62.33.207.195","contentRegexp":null,"content":null},{"id":3228,"statusCode":"404","header":"Connection","headerRegexp":"close","contentRegexp":null,"content":null},{"id":3580,"statusCode":"307","header":"Location","headerRegexp":".*","contentRegexp":null,"content":null}]},"id":"DICK-BUTT-I386---1AE822EF40"}

Как мы можем видеть, Ревизор будет определять страницы-заглушки по наличию слов «заблокирован» и «ограничен», будет искать IP-адрес заглушки провайдера ТТК 62.33.207.195 в заголовке, а также проверять статус, отдаваемый веб-сервером.

Чтобы установить SSH-туннель с клиентом, сервер посылает команду tunnel_on с портом и количеством миллисекунд, после которого его следует завершить, в качестве параметров к команде:

"method":"GetMyTasks","params":"","id":"DICK-BUTT-I386---1AE822EF40","session_id":1488}      {"jsonrpc":"2.0","result":{"tasks":[{"id_task":"148411","id_task_meta":null,"type":"service","priority":"1","checklist":null,"checklist_count":"0","params":"{\"format\":1,\"command\":\"tunnel_on\",\"param1\":64123,\"param2\":60000}","status":"RUNNING","completion":"0","result":null,"pass":"0","fail":"0","passed_items":null,"failed_items":null,"id_creator":"N01-KONA-CHAN","id_lens":"DICK-BUTT-I386---1AE822EF40","ts_create":"1460000000","ts_start":"1460000000","ts_stop":null}],"params":{"DnsThreadsMax":20,"MAXfailedChecklistDownloadCount":100,"MAXfailedReportUploadCount":25,"whiteCheckMinInterval":60000,"connectTimeout":10000,"soTimeout":10000,"maxTotalConnections":50,"maxHttpsConnections":20,"maxContentSize":3000},"ts":1460000000,"zip":1,"tests":null},"id":"DICK-BUTT-I386---1AE822EF40"}

После этого система запускает SSH-клиент Dropbear, который часто используют во встраиваемых системах, путем совершения вызовов fork() и execv(), со следующими параметрами:

/usr/bin/ssh -y -y -K 30 -N -T -R 0.0.0.0:6412:127.0.0.1:1080 -p 22 -i /root/.ssh/id_rsa

Два параметра -y отключают проверку ключа SSH-сервера (зачем?), -N и -T отключают выполнение команд, а -R включает режим проброса порта от сервера клиенту, т.е. открывает на стороне сервера заданный порт (64123) и перенаправляет запросы с него на порт 1080 клиента, на прослушивание которого настроен Socks5-сервер.
Конечно же, первым делом -R была заменена на -D, однако на все исходящие соединения возвращался ICMP Administratively Prohibited.
Если подумать, никто нам не запрещает указать несколько портов для проброса. Почему бы не воспользоваться этим моментом, и не пробросить на себя чуточку больше портов, скажем, диапазон с 1024 до 65535? К сожалению, одно соединение может пробросить около 1000 портов. Не знаю, чем вызвано это ограничение, быть может, виноваты настройки ulimit, а может и OpenSSH. Итак, Socks5-сервер запущен, 65 SSH-соединений установлено, и мы принимаем первое подключение на порт прокси!
Что же произошло? Проверяющий сервер отправляет какому-то действующему Ревизору команду tunnel_on с портом, не проверяя, используется ли он уже кем-то в системе, Ревизор подключается к серверу, но пробросить порт не может, так как мы заняли его раньше. Сервер подключается к нашему Socks5-серверу и открывает сайты, думая, что открывает их через проверяемого провайдера, у которого стоит Ревизор.
Прошу прощения у пострадавшего провайдера, у которого внезапно открылись все заблокированные сайты, да еще и из Чехии!

Вместо заключения

Быть может, Роскомнадзор затеял этот проект из-за зависти к Blockcheck? Кто знает…

ссылка на оригинал статьи https://habrahabr.ru/post/282087/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *