LINUX.ORG.RU
ФорумTalks

Поттеринг не успел выкинуть sudo, а его уже поимели

 , ,


0

2

Привет, ЛОР!

Нашёл интересное чтиво про инициативу Лёнечки по замене sudo на что-то там новое и улучшенное. Вкратце: dbus дыра, systemd дыра, всё дыра, сплоиты уже готовы заранее.

Немного цитат:

Here’s a quick PoC to demonstrate root permission hijacking by exploiting the fact «systemd-run» (the basis of uid0/run0, the sudo replacer) creates a user owned pty for communication with the new «root» process.

This isn’t the only bug of course, it’s not possible on Linux to read the environment of a root owned process but as systemd creates a service in the system slice, you can query D-BUS and learn sensitive information passed to the process env, such as API keys or other secrets.

Это, кстати, правда. Если открыть консольку и забрать там busctl --user monitor, можно много интересного увидеть, включая свои пароли, летающие из keyring в запрашивающее их приложение.

Ссылка: https://twitter.com/hackerfantastic/status/1785495587514638559

UPD:

Для тех, у кого нет тваттера, вот другая ссылка: https://github.com/hackerhouse-opensource/exploits/blob/master/systemd-run-tty.txt

★★★★★

Последнее исправление: hateyoufeel (всего исправлений: 3)

Ответ на: комментарий от hateyoufeel

Нет, я хочу, чтобы процесс получатель не мог поднасрать другим.

И я уже сказал – если ты делаешь на стороне отправителя memory sealing, никто никому поднасрать не может.

Да, я о том же. Для широковещательных рассылок по шине это не слишком подходит.

С чего бы вдруг? Это буквально то, что ты хочешь – CoW + неизменяемость другими процессами.

Лол нет. Dbus всё ещё говно, потому что не делает кучу того, что могла бы и должна делать шина, и заставляет приложения жонглировать fd.

Ок.

cumvillain
()
Ответ на: комментарий от cumvillain

И я уже сказал – если ты делаешь на стороне отправителя memory sealing, никто никому поднасрать не может.

Да, но это ставит крест на CoW. Через F_SEAL_* можно только полностью запретить запись. Можно, конечно, копировать ручками, но ты понял.

С чего бы вдруг? Это буквально то, что ты хочешь – CoW + неизменяемость другими процессами.

Нет. Тут либо CoW, причём для этого получатель должен сам всё сделать (если успеет и туда не поднасрали, когда до него дошла очередь), либо неизменяемость через F_SEAL_*, и тогда опять же всё надо делать ручками.

Вот тебе пример:

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>

#define CHECK(cond, msg) do{ if(cond) { fprintf(stderr, "[!] ERROR: %s\n", (msg)); exit(EXIT_FAILURE);}}while(0)

// Messages are same length for consistency.
const char good_message[] = "hello there! :)))))))))))))))))))))))))))";
const char bad_message[] =  "HURR DURR YOUR MOTHER SUCKS COCKS IN HELL";

void map_and_print(int, size_t);

void map_and_print(int fd, size_t len) {
    char *ptr = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
    CHECK(ptr == MAP_FAILED, "mmap failed");
    printf("%s\n", ptr);
    fflush(stdout);
    int r = munmap(ptr, len);
    CHECK(r == -1, "munmap failed");
}

int main(void) {
    int fd = memfd_create("message", 0);
    int r = 0;
    CHECK(fd == -1, "memfd_create failed");

    r = write(fd, good_message, sizeof(good_message));
    CHECK(r < (int)sizeof(good_message), "write failed");

    pid_t good_boy = fork();
    if(!good_boy) {
        sleep(3);
        map_and_print(fd, sizeof(good_message));
        close(fd);
        exit(EXIT_SUCCESS);
    }

    pid_t bad_boy = fork();
    if(!bad_boy) {
        r = ftruncate(fd, 0);
        CHECK(r == -1, "ftruncate failed");
        r = write(fd, bad_message, sizeof(bad_message));
        CHECK(r == -1, "write failed");
        close(fd);
        exit(EXIT_SUCCESS);
    }

    waitpid(bad_boy, NULL, 0);
    waitpid(good_boy, NULL, 0);

    return 0;
}

Что нужно сделать со стороны родителя, чтобы второй ребёнок тут не мог поднасрать первому, но при этом оба могли писать в замапленный буфер?

Лол нет. Dbus всё ещё говно, потому что не делает кучу того, что могла бы и должна делать шина, и заставляет приложения жонглировать fd.

Ок.

В общем, тут та же проблема, что с GTK, гнумом, выделением текста и реакциями с эмоджи: вместо нормальной приблуды у нас полусырая поделка, которую нужно самому вот так-то допиливать. При этом разрабы утверждают, что им норм, а эти все фичи не нужны.

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 6)
Ответ на: комментарий от hateyoufeel

Тут меня потёрли, так что отвечу рядом:

Что в данном случае будет второй дырой? sudo, что ли?

Второй дырой будет лежащий в соседнем файле pty твоего терминального эмулятора, лол. И все остальные признаки того, что в линуксе в принципе никогда не было никаких security boundary внутри одного юзера.

intelfx ★★★★★
()
Ответ на: комментарий от hateyoufeel

буфер заворачивается в fd и превращается в очередь. Что, например, ставит крест на возможности передавать данные двум и более процессам сразу

Сфигали? man memfd, например.

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

Второй дырой будет лежащий в соседнем файле pty твоего терминального эмулятора, лол. И все остальные признаки того, что в линуксе в принципе никогда не было никаких security boundary внутри одного юзера.

Продемонстрируй, как это в случае с sudo эксплуатировать.

Сфигали? man memfd, например.

Дочитай тред до конца, потом отвечай. memfd уже обсудили.

hateyoufeel ★★★★★
() автор топика

Очень интересно, правда ничего непонятно.

wandrien ★★
()
Ответ на: комментарий от hateyoufeel

Нюансы возникают, когда ты хочешь сделать рассылку один-много. В текущем варианте это просто не будет работать без копирования для каждого получателя.

Что за задачу ты решаешь, делая рассылку один-много со скоростью 2 ГБ/с? И при чем тут dbus?

wandrien ★★
()
Ответ на: комментарий от hateyoufeel

Продемонстрируй, как это в случае с sudo эксплуатировать.

Абсолютно так же, как ты собрался эксплуатировать «дыру» из шапки, только вместо user-owned slave pty от run0 (подключенной к целевому процессу) у тебя user owned slave pty от терминального эмулятора (подключенный к run0).

intelfx ★★★★★
()
Ответ на: комментарий от wandrien

Нюансы возникают, когда ты хочешь сделать рассылку один-много. В текущем варианте это просто не будет работать без копирования для каждого получателя.

Что за задачу ты решаешь, делая рассылку один-много со скоростью 2 ГБ/с? И при чем тут dbus?

Мы тут пришли к тому, что шину в лялексе можно было бы сделать куда более вменяемо чем это делает dbus. Отсутствие нормальных широковещательных рассылок и необходимость жонглировать fd для адекватной передачи данных с низкими задержками и без копирования – один из симптомов ущербности dbus.

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

dbus не привязан к Linux. Это не «шина в лялексе» это просто «шина».

Как именно два процесса будут организовывать оптимизированный способ обмена данными, лежит за пределами тех вещей, которые решает dbus.

wandrien ★★
()
Ответ на: комментарий от hateyoufeel

Дочитай тред до конца, потом отвечай. memfd уже обсудили.

Не «обсудили», а «тебя ткнули в твоё же незнание матчасти» и «ты что-то промямлил в ответ».

Сначала ты поставил задачу «рассылки один-много» и пожаловался, что передача fd «ставит крест на возможности передавать данные двум и более процессам сразу». У этой задачи есть очевидное решение: memfd + sealing.

Потом ты начал двигать стулья и что-то говорить про то, что один ребёнок может поднасрать другому. Во-первых, это совсем другая задача, а во-вторых, она абсолютно высосана из пальца. Если у тебя есть два ребёнка в разных security domains, то тот, который менее привилегированный, должен перед сбросом привилегий дропнуть все ресурсы, в которые он не должен мочь поднасрать. Это как бы linux 101.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от wandrien

dbus не привязан к Linux. Это не «шина в лялексе» это просто «шина».

Это не важно, остальные системы где есть dbus не слишком релевантны.

Как именно два процесса будут организовывать оптимизированный способ обмена данными, лежит за пределами тех вещей, которые решает dbus.

А какие вещи решает dbus? Как красивше тормозить, что ли? Или как сделать неэффективную передачу данных?

@intelfx

Не «обсудили», а «тебя ткнули в твоё же незнание матчасти» и «ты что-то промямлил в ответ».

Ты мне эксплуатацию sudo так и не показал, только промямлил что-то.

Во-первых, это совсем другая задача, а во-вторых, она абсолютно высосана из пальца. Если у тебя есть два ребёнка в разных security domains, то тот, который менее привилегированный, должен перед сбросом привилегий дропнуть все ресурсы, в которые он не должен мочь поднасрать. Это как бы linux 101.

Причём здесь security domains? Речь о банальной рассылке сообщений и изоляции процессов друг от друга.

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 2)
Ответ на: комментарий от hateyoufeel

А какие вещи решает dbus?

Перечисление объектов и выполнение RPC к ним.

Это не важно, остальные системы где есть dbus не слишком релевантны.

Делать решения, прибитые гвоздями к деталям реализации здесь и сейчас – говноархитектура. Ты сам прибежишь создавать темы «XYZ говно», когда окажется, что XYZ в силу ограничений архитектуры не смог адаптироваться к новым технологиям в ядре.

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Ты мне эксплуатацию sudo так и не показал

NYPA, чтобы тебе рабочие PoC писать на каждый чих, в котором ты прикидываешься шлангом. Концепцию контрпримера к заявлению «в run0 дыра» я описал, если есть что возразить по существу — вперёд.

Причём здесь security domains? Речь о банальной рассылке сообщений и изоляции процессов друг от друга.

Ну ты совсем хлебушек или да? Давай ты сначала отчётливо поставишь задачу из своего пассажа про родителя и двух потомков, а потом будем разговаривать. Потому как пока что приходится угадывать, что ты имел в виду и что же тебе в очередной раз не понравилось.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 5)
Ответ на: комментарий от wandrien

Перечисление объектов и выполнение RPC к ним.

И это не обмен данными?

Делать решения, прибитые гвоздями к деталям реализации здесь и сейчас – говноархитектура.

Так он и так прибит. Много ли ты софта знаешь, использующего dbus ну например под вендой?

Тут ничего не поделаешь, шина – довольно низкоуровневая штука, завязываться на особенности ОС всё равно придётся.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от intelfx

NYPA, чтобы тебе рабочие PoC приводить на каждый чих

Ну, то есть, слив. Я тебя понял.

Давай ты сначала отчётливо поставишь задачу, которая не решается передачей memfd и/или sealing, а потом будем разговаривать.

Я не писал, что они не решаются memfd и/или sealing. Я написал, что dbus этого не делает и процессы, использующие dbus, вынуждены это сами запиливать.

К слову, я не понимаю, зачем ты со мной разговариваешь. Тебе это явно не по душе и тебе жопу реально каждый раз рвёт как в первый. Прямо ходячий человек-баттхёрт!

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Так он и так прибит. Много ли ты софта знаешь, использующего dbus ну например под вендой?

dbus будет работать при любой нижележащей архитектуре, в рамках которой возможно прокинуть UNIX_FD Unsigned 32-bit integer representing an index into an out-of-band array of file descriptors, transferred via some platform-specific mechanism.

Это – правильное разбиение на слои абстракции. dbus-у – dbus-ово.

Чо ты хочешь получить конкретно, ты так и не смог пояснить. Почему эти хотелки должен реализовывать dbus – тоже.

И это не обмен данными?

Всё есть обмен данными. Любой смысл можно обобщить до бессмыслицы.

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 3)
Ответ на: комментарий от wandrien

dbus будет работать при любой нижележащей архитектуре

Оригинальный – да, но на него забивают. Вместо него дефолтом хотят dbus-broker, который linux only.

https://github.com/bus1/dbus-broker

The requirements for dbus-broker are:

Linux kernel >= 4.17

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от wandrien

dbus – это спецификация, а не реализация.

Прости, мой компьютер не может запустить спецификацию. Только код.

Так-то POSIX тоже спецификация, но насколько она актуальна, ты сам знаешь.

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Давайте такой хернёй с intelfx вдвоём занимайтесь, я лучше пойду пива возьму.

wandrien ★★
()
Ответ на: комментарий от hateyoufeel

По-моему chown на tty мало на что в целом повлияет. От чего вообще ты пытаешься защититься? Если команду на запуск рут-проги отправил юзер, и юзер после этого общается с её терминалом, то юзер однозначно имеет к нему доступ. Безопасный способ запуска - ctrl-alt-f2, логин за рута, и делай там что надо, всё остальное условно перехватывается (не только sudo-подобный мусор, но и нормальная прога su в том числе).

firkax ★★★★★
()
Ответ на: комментарий от hateyoufeel

Ну, то есть, слив

Нет, ты Не знаю, зачем ты с @wandrien споришь. У вас на двоих одна тактика уровня детсада — кто первый произнесёт магическое слово.

тебе жопу реально каждый раз рвёт как в первый

«азаза у тебя жопу порвало»

Мде, дискуссия уровня @hateyoufeel одна штука.

Тебе это явно не по душе

Да не, мне максимально приятно смотреть, как ты каждый раз извиваешься :D

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 2)
Ответ на: комментарий от intelfx

Ну, то есть, слив

Нет, ты

Да нет, я просто попробовал через reptyr спереть у терминала с sudo консольку и это не работает. А вот у systemd-run работает. Такие дела.

 △ ~ pgrep konsole
548890
 ▲ ~ reptyr -T 548890         
[-] Child is not connected to a pseudo-TTY. Unable to steal TTY.
Unable to attach to pid 548890: Invalid argument

 △ ~ pgrep systemd-run
606511
 ▲ ~ reptyr -T 606511 
# id
uid=0(root) gid=0(root) groups=0(root)

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 3)
Ответ на: комментарий от hateyoufeel

Да ты угораешь что ли:

$ cat test.c
#define _GNU_SOURCE

#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>

#define DATA_LEN 9

void
map_and_print(int fd)
{
	char *s;

	s = mmap(NULL, DATA_LEN, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
	printf(" pre: %s\n", s);
	snprintf(s, DATA_LEN, "%d", getpid());
	printf("post: %s\n", s);
}

int
main(void)
{
	int fd, cfd;
	size_t written;
	pid_t pid;

	fd = memfd_create("data", MFD_ALLOW_SEALING);
	if (fd == -1)
		err(1, "cannot create memfd");

	written = write(fd, "xxxxxxxx", DATA_LEN);
	if (written == -1)
		err(1, "cannot write data to memory area");

	if (fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == -1)
		err(1, "cannot seal");

	pid = fork();
	if (pid == 0) {
		cfd = dup(fd);
		map_and_print(cfd);
		exit(0);
	}
	
	sleep(5);

	pid = fork();
	if (pid == 0) {
		cfd = dup(fd);
		map_and_print(cfd);
		exit(0);
	}

	wait(NULL);
	wait(NULL);

	return 0;
}
$ ./test
 pre: xxxxxxxx
post: 62583
 pre: xxxxxxxx
post: 62598
cumvillain
()
Последнее исправление: cumvillain (всего исправлений: 4)
Ответ на: комментарий от cumvillain

Да ты угораешь что ли:

Гыыы.. прикольно. Осталось только это сунуть в dbus для больших сообщений и у нас потенциально будет быстрая шина для передачи данных.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

Да, но это ставит крест на CoW. Через F_SEAL_* можно только полностью запретить запись. Можно, конечно, копировать ручками, но ты понял.

Кстати, ты обосрался.

memfd со всеми seal-ами отлично маппятся на запись с MAP_PRIVATE и имеют при этом CoW-семантику.

intelfx ★★★★★
()
Ответ на: комментарий от cumvillain

Лол, мы сейчас один и тот же тесткейс написали :D

$ ./client
Message: Secure zero-copy message from server: Thu May 16 14:22:47 2024
Message (modified): SECURE ZERO-COPY MESSAGE FROM SERVER: THU MAY 16 14:22:47 2024
Message (original): Secure zero-copy message from server: Thu May 16 14:22:47 2024
intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Потому что reptyr не всегда находит нужный fd. На LWN разобрали уже.

И ещё одно дежурное напоминание, что твой reptyr работает только потому что ты предварительно сделал sudo hack_me_harder.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Потому что reptyr не всегда находит нужный fd. На LWN разобрали уже.

Ну ты бы ссылку кинул хотя бы. А мы проверим.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от intelfx

У вас на двоих одна тактика уровня детсада — кто первый произнесёт магическое слово.

А почему ты всегда свой любимый приём пытаешься прилепить другим? =)

Напомню, что в предыдущих… я уже забыл скольки именно – трёх или же четырёх – темах, разговор заканчивался на том, что intelfx переходил на личность собеседника и с невнятными причитаниями покидал тему, не приводя никаких аргументов.

wandrien ★★
()
Ответ на: комментарий от hateyoufeel

Неа, не будет. CoW не бесплатный, если тебе ДЕЙСТВИТЕЛЬНО нужно передавать по 2 гига в секунду в N клиентов, каждый из которых пытается тут же модифицировать эти данные, то проблемы будут не у dbus.

В общем, кейс всё еще не понятен.

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

Неа, не будет. CoW не бесплатный, если тебе ДЕЙСТВИТЕЛЬНО нужно передавать по 2 гига в секунду в N клиентов, каждый из которых пытается тут же модифицировать эти данные, то проблемы будут не у dbus.

А ты уверен, что это не будет быстрее текущей реализации с копированием в почти любой ситуации? Потому что мне вот кажется, что будет.

hateyoufeel ★★★★★
() автор топика
$ busctl monitor
Call to org.freedesktop.DBus.Monitoring.BecomeMonitor failed: Access denied

наверное надо сначала получить рута? :)

sergej ★★★★★
()
Ответ на: комментарий от cumvillain

А бенчмарки нужны. Что быстрее: write()/read() или

Там не read/write. Там копирование из клиента в демон, а потом из демона в другой клиент. Против копирования в шареный буфер.

Ясен хер, на маленьких сообщениях это не имеет смысла. Но если речь идёт хотя бы о мегабайтах, то профит уже должен быть.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

Ссылку потерял, сорян. А теперь попробуй сделать в одном терминале echo $$ и потом sudo passwd, а в другом reptyr -T <PID баша-родителя sudo>.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 2)
Ответ на: комментарий от cumvillain

там unix-сокет, олол. Там sendmsg/recvmsg.

Да насрать, на самом деле. Вопрос исключительно в количестве копирований данных. Я сейчас пошерстил код dbus-broker и там ничего для этого нет, например.

При этом, memfd там используется чтобы срать логами в journald с космической скоростью. П – Приоритеты.

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Потому что танец с 8 сисколами это очень неочевидный выигрыш. Если бы там шареный ринг-буфер был, куда клиент сообщения шлет, это бы ещё куда ни шло. Но сложность всего этого без конкретных цифр, показывающих какой-то выигрыш, ни о чем. Не говоря уже о том, что dbus-broker это drop-in replacement, и менять API в сторону клиента нельзя.

cumvillain
()
Последнее исправление: cumvillain (всего исправлений: 1)
Ответ на: комментарий от cumvillain

Потому что танец с 8 сисколами это очень неочевидный выигрыш.

Ну да, было бы лучше если бы их было 1-2. То есть, лялекс всё таки сосёт, потому что для zero copy ipc нужно по 8 сисколлов?

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

Ну да, было бы лучше если бы их было 1-2. То есть, лялекс всё таки сосёт, потому что для zero copy ipc нужно по 8 сисколлов?

То есть из тебя жыр рекой лезет.

cumvillain
()
Ответ на: комментарий от cumvillain

Ну да, было бы лучше если бы их было 1-2. То есть, лялекс всё таки сосёт, потому что для zero copy ipc нужно по 8 сисколлов?

То есть из тебя жыр рекой лезет.

Я просто хочу нормальный zero copy ipc с быстрым переключением контекста, минуя ядро. Неужели это я так много хочу? :(

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

Я просто хочу нормальный zero copy ipc с быстрым переключением контекста, минуя ядро. Неужели это я так много хочу? :(

Мечты сбываются: https://github.com/bus1/bus1

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Я просто хочу нормальный zero copy ipc с быстрым переключением контекста, минуя ядро. Неужели это я так много хочу? :(

Он у тебя есть. Накладные расходы на его обслуживание могут оказаться того стоящими, а могут и нет. Но смысла этого обсуждать здесь нет, потому что все опять говном друг в друга кидаться будут.

cumvillain
()
Ответ на: комментарий от intelfx

Я просто хочу нормальный zero copy ipc с быстрым переключением контекста, минуя ядро. Неужели это я так много хочу? :(

Мечты сбываются:https://github.com/bus1/bus1

Последний коммит 5 лет назад. It’s dead, Jim. Я не думаю, что оно с последними ядрами вообще соберётся.

Другой вопрос, что в ядро вот этого монстра пихать совсем не обязательно. Достаточно объединить в один несколько описанных выше сисколлов.

hateyoufeel ★★★★★
() автор топика
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)