Досліджуємо «Ревізор» Роскомнадзора

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

Ревізор — програмно±апаратний комплекс для моніторингу доступу до сайтів з реєстру з боку провайдерів — бере свій початок в жовтні 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 -rev a-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 Type Id
>> /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.ua"
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, який дозволяє виконувати наступні команди:
reboot system
system resetfs
system update
log
info
ifconfig
route
arp
ping
nslookup
traceroute
net proxy clear
net proxy set
net fallback
Пакунки з репозиторію підписуються ключем «МФІ Софт», підпис перевіряється засобами opkg:
Прихований текст
Certificate:
Data:
Версія: 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 : 5 Aug 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
Версія: 1.2.2-34720
Depends: libc, libstdcpp, libpthread, libpcre, libopenssl
Section: utils
Архітектура: 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-сервера і відкриває сайти, думаючи, що відкриває їх через перевіряється провайдера, в якого варто Ревізор.
image
Прошу вибачення у потерпілого провайдера, у якого раптово відкрилися всі заблоковані сайти, та ще й з Чехії!

Замість висновкуРобити API по HTTPS, але відключати перевірку SSL і SSH-сертифікатів? Використовувати роутери з 4 МБ ROM вартістю 1500₽ в роздріб? Тримати сервер з Debian Oldstable без оновлень безпеки? За 84 мільйони таке можна собі дозволити.
Бути може, Роскомнадзор затіяв цей проект із-за заздрості до Blockcheck? Хто знає…

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.