Изследователи по сигурността от depthfirst публикуваха на 24 юли работещ код за експлойт за уязвимост в GitLab, която компанията коригира шест седмици по-рано, на 10 юни. Кодът изпълнява команди като git на всеки самостоятелно управляван сървър (self-managed) с версия 18.11.3, на който не е инсталирано съответното обновяване.
Всеки автентифициран потребител, който има права да изпраща промени (push) към даден проект, може да я експлоатира. Атакуващият качва специално изготвен Jupyter notebook и отваря неговия commit diff (разлика в комитите), което води до изтичане на указател към динамичната памет (heap pointer). Чрез достатъчен брой такива опити автоматизирана сонда може да локализира библиотеките в паметта. След това още два notebook-а задействат злонамерения код. Не са необходими администраторски права, достъп до CI или runner, взаимодействие с жертвата или достъп до чужд проект.
GitLab не класифицира корекцията като свързана със сигурността. Преглед от The Hacker News установи, че преминаването към Oj 3.17.3 е вписано в раздела за отстранени грешки (bug fixes) в пакета от 10 юни, а не в таблицата с корекции за сигурност. Липсва CVE идентификатор, CVSS оценка или споменаване на веригата с разликата в notebook файловете. Системните администратори, които са анализирали тази версия спрямо таблицата за сигурност, са нямали основание да я третират като спешна.
Веригата работи благодарение на две грешки, свързани с компрометиране на паметта (memory corruption) в Oj – Ruby JSON парсер, имплементиран до голяма степен на чист C. От depthfirst посочват, че системата им ги е открила автономно, а изследователите са ги свързали във верига ръчно.
Модулът за визуализация на notebook файлове в GitLab – вграден gem, наречен ipynbdiff – предава контролирания от хранилището .ipynb JSON файл на Oj::Parser.usual.parse в рамките на дълго работещ Puma worker процес. По този начин контролираните от атакуващия байтове достигат до ръчно управляваната C памет на Oj в процеса на приложението.
Едната грешка записва данни извън фиксиран стек за влагане (nesting stack) от 1024 байта, докато придобие контрол над функцията за обратно повикване при стартиране на парсера (start callback). Другата съкращава ключ на обект от 65 565 байта до 29 в 16-битово поле със знак и връща указател към активната памет, който GitLab визуализира в diff секцията. Изтичането на информация позволява локализирането на libc, а записът насочва функцията за обратно повикване към system().
Засегнати са всички планове – CE (Community Edition) и EE (Enterprise Edition), от Free до Ultimate. Самият език Ruby не е засегнат. Версия Oj 3.17.2 включваше други корекции от същия одит, но не и тези две.
Необходимо е обновяване до версии 18.10.8, 18.11.5 или 19.0.2. Нито GitLab, нито depthfirst предлагат алтернативно решение (workaround) за тези, които не могат да обновят в момента.
Критична точка при Helm и Operator инсталациите: проверете версията на GitLab вътре в Webservice контейнера, работещ с Puma, а не версията на chart-а или Operator-а. Версиите от 15.2 до 18.9 няма да получат обратна съвместимост (backport), тъй като тези версии са извън поддържаните от GitLab цикли за сигурност. Поради това тези инсталации трябва да преминат към поддържана версия.
Командите се изпълняват от името на git – акаунта, зад който стои Puma. Степента на компрометиране зависи от това доколко е изолирана инсталацията. В обсега на атаката влизат: сорс код, Rails тайни ключове, идентификационни данни за услуги, CI/CD данни и вътрешни услуги, с които приложението може да комуникира.
Публичният експлойт е разработен за GitLab 18.11.3 на архитектура x86-64. Отместванията на приспособленията (gadget offsets), състоянието на регистрите и поведението на jemalloc са взети от този конкретен образ, а възстановената база на библиотеката е валидна само до рестартирането на Puma master процеса, така че експлойтът не може да се използва директно срещу произволна цел.
Уязвимостите в Oj са от общ характер, но портването на експлойта изисква сериозни усилия. От depthfirst оценяват на 5 до 10 минути търсенето в паметта при нова инсталация с два worker процеса и прогнозират 1 до 2 часа за системи, които работят от по-дълго време. Техният технически анализ описва пълната верига.
depthfirst съобщават за уязвимостите в Oj на 21 май, поддържащият ги разработчик е слял корекциите на 27 май, а Oj 3.17.3 е пуснат на 4 юни. Веригата за експлоатиране в GitLab е изпратена до GitLab на 5 юни, потвърдена на 8 юни и коригирана на 10 юни. От depthfirst заявяват, че не са запознати с експлоатиране на уязвимостта в реална среда, както и че GitLab са възпроизвели отдалеченото изпълнение на код независимо. Техният по-широк анализ на Oj доведе до още девет съобщения за CVE, но нито едно от тях не е тази верига.
Медията The Hacker News се свърза с GitLab с въпрос защо корекцията не е класифицирана като проблем със сигурността и дали ще бъде назначен CVE идентификатор, както и с depthfirst относно преносимостта на експлойта. Към момента се очакват отговори.