В пакете cups-filters, включающем компоненты для организации работы сервиса печати, найдена уязвимость (CVE-2023-24805), позволяющая удалённо выполнить произвольные команды на сервере печати через отправку специально оформленного задания вывода на печать. В настоящее время исправление доступно в виде патча. Проследить за выпуском обновлений пакетов в дистрибутивах можно на страницах Debian, Ubuntu, RHEL, SUSE/openSUSE, Fedora, Arch, FreeBSD...Подробнее: https://www.opennet.dev/opennews/art.shtml?num=59181
> beh.c
> char scheme[1024]
> '\0'Действительно, что же могло пойти не так //_-
Так развивай мысль дальше, что там не так?scheme[0] = '\0';
strncat(scheme, uri, sizeof(scheme) - 1);
вот это можно было заменить на
snprintf(scheme, sizeof(scheme),"%s", uri);
и всё.А исправление:
https://github.com/OpenPrinting/cups-filters/commit/8f274035...
оно совсем про другое.
> "';/usr/bin/id;'' #.pdf".Вообще-то это system() многострадальный - к си относится только тем что из си это можно использовать. Так стреляют пятки и на многих других ЯП которые вывешивают system() или сравнимый "упрощенный" интерфейс пуска программ.
И проблема тут не в си а в том что кроить упрощенному интерфейсу запуска программ параметры из передаваемых пользователем значений - дело гиблое и на этом кто только не налетал, от CGI интерфейсов на всем чем угодно до всяких питоняш и жабистов.
Общая идея атаки: если програмер вызывает внешнюю программу через подобный интерфейс и получает от пользователя на вход какие-то данные, можно попробовать оформить эти данные в виде когда "команда шелла" получится очень сильно отличной по смыслу от оригинального замысла. Вон та строка завершает параметры "слишком рано" по мнению шелла, начинает новую команду, и...
Как будто, из самого правильного языка невозможно вызвать эту злосчастную system().
Собственно исходники на сях имеет смысл прицельно сканировать на наличие вызова system и сильно думать насколько оно легитимно и безопасно в том или ином случае. Для сетевой программы, с параметрами от пользователя это одна из самых глупых идей. По тем же причинам шелскриптам не стоит давать параметры от недоверяемого ремотного пользователя. Слишком много специальной трактовки разных символов - и это вообще-то к шеллу, что он так работает, со стороны сей тут никаких проблем нет - что дали то и выполнили. А то что для шелла эти закорюки имели специальные значения - ну и вот при чем тут си, если это шелл вообще специальной трактовкой символов на@#$вается? Классика жанра.
А причём тут С?
Отсутствие/недостаточная фильтрация входных данных - частая болезнь в разных продуктах на разных языках.
Даже там где есть готовые функции для такой проверки/очистки - их периодически забывают вызывать.Помимо system() нефильтрованный ввод ещё попадает в *printf*() и *SQL*() и там тоже нехило разносит всё.
Частая ошибка передавать такое в open(), все вебсервера через это проходили.
Подозреваю даже что openat() могло появится только ради этого ))))
> А причём тут С?Только при том что я его знаю, поэтому знаю что для него сканировать надо :). Вот прямо system. Лучше poison'ом его gcc'шным, или типа того. Если в программе вызовы system() есть это уже повод напрячься в общем случае. Особенно если оно что-то делает с внешними данными при этом. Легитимных и безопасных поводов для system() в коде вообще не так уж много. Шелл очень капризная пакость чтобы ему внешние данные скармливать вообще.
А как это делать в каком-нибудь ruby, java или чем там еще - пусть специалисты в них и разбираются. И, если хотят, тут и пишут.
И да, разумеется, чтобы не скучать есть еще SQL-инъекции. Или вон даже directory traversal обыкновенный. Вот тут кстати стандартизаторы подгадили - все эти ../../etc/passwd довольно канительно и грабельно отфильтровывать так то. Ну вот буквально каждый второй вебсервер норовит все и вся отсервировать по первости, например.
Сишники и строки, том 2023, глава 24805.
Купс это что-то из набора штатных бэкдоров, как и гхостскрипт. Сишники тут ни при чём.
Канеш ни при чём, они всегда ни при чём
> Канеш ни при чём, они всегда ни при чёмСмотри кто автор.
Код в котором встречается system() вообще особого доверия не заслуживает. Если кто видит в коде system() - есть нехилый шанс что там вулн, если параметры подконтрольны пользователю. Это касается вообще любого яп где это или нечто сравнимое есть.
Он в этом случае виноват только тем что шелл вызвал. Шелл на#$%лся на хитром эскейпинге. И вопросы тут к шеллу и его синтаксису так то на самом деле. А к сишнику вопрос только "нафига это было?"
Чувак, причём тут С и строки?
Автор кода получил строку по сети и отправил её в system(), не проведя никаких проверок и очисток.
Можно на джаве, го, расте написать тоже самое.На пхп постоянно так делают и там SQL инекции случаются, именно это близкий аналог данной ошибки.
Действительно, можно такое написать на чём угодно, но написано на Си. И все эти проблемы с санитизацией ввода растут из отсутствия вменяемых способов работы со строками в Си. Как следствие, сишники не воспринимают строки иначе, чем массив байтов. Неназванное не может быть познано.
Нет.
Вы сами себе придумали строки а потом жалуетесь что с ними нечем работать.
Почти все веб сервера написаны на С и как то справились с очисткой входных данных.
Есть куча всяких кодеков и пр что работает с бинарными данными и обработки там намного сложнее.В данном случае надо смотреть, мне кажется там вообще не было смысла брать пользовательские данные, а можно было генерить рандомный уникальный идентификатор.
> Вы сами себе придумали строки а потом жалуетесь что с ними нечем работатьВот именно про это я и говорю: неназванное. Очень уж напоминает языки некоторых примитивных племён, где нет слов для определённых цветов и — о чудо — носители языка эти цвета не различают.
> Почти все веб сервера написаны на С и как то справились с очисткой входных данных
Ты совершенно прав, и про то, как именно справлялись с очисткой данных можно почитать в предыдущих томах этой саги.
Вы синтаксический сахар нужный для обработки строк возводите в мастхэв максимум.
На практике же всё сводится к тому чтобы найти уже готовое решение которое где то имплементировано и оттестировано.
Интересно за какой он синтаксический сахар топит? Кто-то заморочился позатыкать проблемы шелла на уровне либы? И если да - это для каких шеллов работает? Потому что шелл так то тоже не мировая константа. А какой-нибудь bash при необдуманном вызове позволяет и еще стрельнуть по пяткам добавочными способами. Рут по DHCP подтвердит.
Если вызвать шелл с вон теми закорючками из другого ЯП - результат будет тот же самый. Чем тут си виноват? Что шелл позволяет вызывать чтоли? И кто из ЯП так уж прямо заморачивается санитизацией параметров для вот именно posix shell например?
Если… Эх, вот только если… Но вызвали из Си и получили то, что получили.
Есть полно случаев когда вызывают и не из си, получая то же самое по смыслу. Вот прям таким же эксплойтом.А си в этой схеме что предъявляется? Что он шелл запускать видите ли умеет по простому? Ну охренеть вулн :)
Я правильно понимаю, у них критическая ошибка в обработчике ошибок? 😄
а вы думали что просто так оно жепой в интернет смотрит?
И кто его жепой в инет выставляет? Список в студию!
в сях (да и в плюсах) работа со строками одно мучение.
Поэтому меня всегда так радуют описания нововведений в сях и плюсах, то сё, пятое десятое, а нормальной удобной стандартной библиотеки для строк нет. А уж про utf и заикаться не надо - каждый как черепашка тащит свою реализацию ... куцую и убогую.
> в сях (да и в плюсах) работа со строками одно мучение.
> Поэтому меня всегда так радуют описания нововведений в сях и плюсах, то
> сё, пятое десятое, а нормальной удобной стандартной библиотеки для строк нет.
> А уж про utf и заикаться не надо - каждый как
> черепашка тащит свою реализацию ... куцую и убогую.Есть только ICU. В принципе есть только ICU, если ты хочешь юникод. ICU не куцая, ICU блотварь. Какие твои проблемы, всё прекрасно со строками в плюсах? В си нет строк, есть asciiz, что вполне себе неплохо и эффективно на практике. Не драматизируй, это всё вопрос привычки.
>>Не драматизируй, это всё вопрос привычки.нет. это вопрос - качаешь исходники, пытаешься сделать патч, чтоб появилось что тебе надо. а фиг тебе. utf-а нет, строковых операций нет. Прымер - нужно название песни разбить по словам, первую букву поднять, остальные опустить. название песен на русском, янгл, фран, япон. языках. когда удобно, делается в пару строк.
>>вполне себе неплохо и эффективно на практике.
эффективно нужно там где, надо. а в других местах, должно быть удобно для программирования. какая разница сколь эффективно формируется строка запроса к капс? а по коду там огород из str func. "эффективность" во всех дырах привела к преждевременной языковой смерти :-)))
> есть asciiz, что вполне себе неплохо и эффективно на практикепросто гомерический хохот. Особенно когда ждут заврешающие нули, переполняя буферы или когда их каждый раз ищут, чтобы длину посчитать.
Чем для тебя std::string и std:string_view ненормальны и неудобны?
Это настолько же удобно, насколько удобны жигули. Так ездите на жигулях[/w][/w][/w] используйте std:string сами.
Это не ответ на вопрос. Так чем неудобны то?
Тем, что большинство современных писак програмят по принципу:
"Хочу играть на гитаре, но учиться не хочу, хочу чтоб само!" (с)
Недостатком доступных методов для работы со строками. Жить можно, но неудобно.
Тем, что они не позволяют адекватно сделать посимвольный проход по строке. ASCII - ок, всё остальное это боль, мучения и тонна костылей. Попробуйте просто вывести строку "ОпенNet" посимвольно и посмотрите на кракозябры.
Самое очевидное на что не хватает ума хейтерам - это понять что никаких строк в С нет.
Есть выделенная область памяти, есть её размер и есть размер данных в ней - вот простое правило для работы с данными которые нужно интепретировать как строки.Но в данном случае ошибка вообще про другое: данные от пользователя не достаточно проверяются/экранируются и это отдаётся в system() - те на запуск.
У пхп програмистов такое сплошь и рядом встречается, хотя строки там типа совсем безопасные.
В общем то на любом языке такая ошибка возможна, потому что никакой компелятор мамкиному кодеру не подскажет что надо данные полученные неведомо откуда перед вызовом system() проверять.
> Самое очевидное на что не хватает ума хейтерам - это понять что
> никаких строк в С нет.да-да. формировать текстовые строки на сях нельзя, ведь их нет. поэтому придётся извращаться на радость почитателям и формировать отсутствующие строки недо str функциями. в миллионных раз изобретая велосипед.
В чём претензия то?
Язык низкоуровневый, если вам охота обмазыватся сахаром и не думать о таких мелочах - выбирайте другой язык.Меня лично всё устраивает, о строках я забыл лет 15 назад и счастливо живу, контролируя и размер буфера и размер данных в нём.
Всякие strn*(), strlcpy() - юзаю не часто, snprintf() всё сам делает что мне надо.
О, еще один. У одного "ничего никогда не падало", а у этого "никогда за пределы буфера не выходит"
Прямо слет пиноккио-программеров))
> Есть выделенная область памяти, есть её размер и есть размер данных в ней - вот простое правилоНо тут вдруг на данные простые вводные накладывается техника работы с завершающим нулем, унаследованная со времен бедности (когда диды-хакеры каждый байт экономили). И правила становятся непростыми, а решения - глючными и медленными. Нет чтобы хотя бы как в паскале, выделили в языке отдельные специализированные "области памяти" и хранили рядышком с каждой кол-во символов и счетчик ссылок на строку. Ведь памяти уже не 640 килобайт. Но нет, чтобы посчитать длину строки, мы будем всю ее сканировать в поисках нуля, которого может и не быть из-за разгильдяйства, это ведь так быстро.
Нет, правила не меняются.Хотите абстракции - да на здоровье, ищите/пишите либу которая вам строки как угодно будет представлять и обрабатывать.
Я себе давно написал такое: https://github.com/rozhuk-im/liblcb/blob/master/include/util...
и использую это в основном на данных получаемых/отправляемых по сети/диск.
Для не частых операций со строками проще руками проконтролировать без таких абстракций.
>Но тут вдруг на данные простые вводные накладывается техника работы с завершающим нулемОу, а потом программисту поступает задача из Азии, он узнаёт про unicode, UTF-16, UTF-32, и у него начинает подгорать про завершающий нуль. А затем подгорать в кошельке.
> а привычной для меня библиотеки для строк, как в том языке, на котором я кодил раньше, нет.Пофиксил.
Вылезай! С++20 : std::u8string
>systemЧто мешало через тот же which сделать ресолвер для exec*?
Debian уже пофиксил