Публічні сторінки SaaS можуть залишатися відкритими для всіх, поки адміністративні операції за ними відмовляють кожному поза VPN. Механізм, що це забезпечує, — не приховане меню і не окрема сторінка входу; це перевірка мережевого шляху, яким надійшов запит. Помилитеся з доказом адреси — і перевірка або заблокує справжніх адміністраторів, або пропустить будь-кого, хто вміє набрати заголовок. Почніть із того, що джерело справді отримує.

Що джерело справді отримує після тунелю

Коли браузер потрапляє на публічний сайт через VPN, який несе й інтернет-трафік, шлюз перетворює з'єднання до того, як воно вийде. SaaS бачить публічну вихідну адресу шлюзу, зазвичай одну адресу або невеликий діапазон, і ніколи не бачить адресу тунелю ноутбука. Тому внесення 10.90.0.42 до списку дозволених не спрацьовує, і тому внесення всього RFC 1918 не спрацьовує ще гучніше: друге пропускає будь-яку приватну мережу, яка може до вас дістатися. Єдина адреса, варта умови, — та, якою ваша організація справді володіє на виході.

curl -s https://ifconfig.me
dig +short admin.example.com

Розділене тунелювання тихо ламає це припущення. Якщо VPN несе лише приватні офісні маршрути, запит до публічного імені адміністративного хоста виходить через місцевого провайдера, і джерело бачить житлову адресу. Значок підключеного VPN нічого не доводить про це конкретне призначення, тож перевіряйте призначення, а не тунель.

Зупиніться і виправте маршрутизацію, перш ніж писати будь-яку політику, якщо вихідна адреса різниться для різних користувачів. Умова, що збігається лише з частиною адміністраторів, гірша за відсутність умови, бо приховує проблему до інциденту.

Довіряйте лише проксі, який переписує адресу

Більшість публічних сайтів стоять за CDN або зворотним проксі, тож адреса сокета джерела належить цьому фронтенду, а не відвідувачу. Фронтенд зазвичай передає початкову адресу в заголовку, і цей заголовок контролює нападник, якщо джерело не приймає його лише від відомих проксі. Явно налаштуйте список довірених джерел і зробіть джерело недосяжним звідусіль інде. Без цієї другої половини нападник обходить проксі й надсилає заголовок напряму.

set_real_ip_from 192.0.2.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
curl -H 'X-Forwarded-For: 198.51.100.27' https://origin.example.com/admin

Те саме міркування стосується протоколу PROXY: він надійний лише тоді, коли слухач прив'язаний до інтерфейсу, до якого проксі може дістатися, а більше ніхто не може. Відсутній контекст адреси має провалити захищену перевірку, а не перейти до дозволу за замовчуванням. Відсутній заголовок не є доказом довіреного шляху.

Прив'яжіть умову до кожної захищеної операції

Помістіть перевірку на межу авторизації, яку проходить кожна захищена операція, а не в сторінку, що малює меню. Групи маршрутів, middleware або шар політик працюють усі; копія на кожен обробник — ні, бо в обробника, доданого наступного кварталу, її не буде.

user = requireAuthenticatedSession()
requirePermission(user, "admin")
requireVpnEgress(verifiedClientAddress(request))
performProtectedOperation(user, request)

Та сама межа має охоплювати JSON API, експорти, підписані URL завантаження і рукостискання WebSocket, оскільки жодному з них не потрібно, щоб сторінку HTML запитували першою. Посилання на завантаження, створене поки VPN працював, лишається чинним і потім, якщо кінцева точка завантаження не перевірить знову. Довгим сесіям також потрібне правило переоцінки, інакше один автентифікований запит стає постійним винятком. Відмова за замовчуванням — єдине налаштування, яке переживає зміну персоналу.

Спільні кеші — це інший шлях обійти перевірку. Кеш, який уже містить захищену відповідь, може віддати її, не звертаючись до джерела, тож позначайте адміністративні відповіді як приватні й тримайте їх поза спільним сховищем. Якщо кеш усе ж має їх віддавати, перевірка доступу має виконуватися до віддачі, а це зазвичай означає, що він взагалі не може бути спільним кешем.

Перевірте обходи, які ви щойно закрили

Відпрацюйте матрицю, а не щасливий шлях: адміністратор через VPN, той самий адміністратор без нього, неадміністратор через нього і підроблений заголовок адреси. Додайте запит напряму до джерела і запит із кешованою відповіддю, бо саме ці два повністю обходять фронтенд.

curl -sI https://admin.example.com/export.csv
curl -s -H 'X-Forwarded-For: 198.51.100.27' https://origin.example.com/admin
curl -s https://admin.example.com/api/me -o /dev/null -w '%{http_code}\n'

Кожен запит має повертати статус, який обіцяє політика, а журнал має фіксувати, який доказ адреси використано. Покрийте IPv6 окремо, бо джерело з подвійним стеком може бачити іншу родину джерел, ніж перевірена. Тримайте звичайні клієнтські операції робочими поза VPN, інакше зміну відкотять після першої скарги клієнта. Запишіть очікуваний результат для кожного рядка до запуску, щоб несподіваний прохід було видно.

Вихідна адреса доводить дозволений мережевий шлях, а не людину і не керований пристрій. Тримайте її однією умовою поруч з автентифікацією та дозволом, і адміністративна зона лишається вузькою, не перетворюючи весь продукт на сервіс лише для VPN. Це розділення і є дизайн, а не його обмеження.

Схожі статті