Фёдор Индутный (Fedor Indutny), автор платформы Io.js (форк Node.js), входящий в технический комитет, управляющий разработкой Node.js, попытался привлечь внимание к проблеме с назначением CVE-идентификаторов некорректным отчётам об уязвимостям, не соответствующим действительности или неадекватно представляющим уровень опасности. Номер CVE, применяемый для идентификации уязвимости, присваивается без должной проверки и без консультации с разработчиками уязвимых программ, что приводит к появлению злоупотреблений, в которых под видом опасных уязвимостей преподносятся несущественные ошибки, на деле не представляющие угрозу безопасности...Подробнее: https://www.opennet.dev/opennews/art.shtml?num=61466
фёдор не прав, неизвемстно откуда будут данные, не ему судить как применяется библа
Проверять корректность данных должно приложение, а не библиотека. То что при обращении к библиотечному вызову не была использована функция приведения IP к нормальной форме - проблема разработчика приложения.
И зачем такая библиотека, которая может вернуть что-то не предсказуемое?
для того чтобы люди, умеющие валидировать юзерские данные на стадии их ввода - могли пользоваться этой библиотекой. Им-то она вернет - предсказуемое.(опционально - а альтернативно-одаренные, считающие что сопельки им должны вытирать все окружающие - страдали)
> люди, умеющие валидировать юзерские данные на стадии их ввода - могли пользоваться этой библиотекой. Им-то она вернет - предсказуемоеЧел, айпишники вида "0x7f.1", и "127.1" валидны согласно RFC. Что ты собрался валидировать?
И вот функции isPublic() из статьи *буквально* возвращают разные результаты в зависимости от представления одного и того же IP. Это и есть чистая непредсказуемость, о которой писал человек выше.
> Чел, айпишники вида "0x7f.1", и "127.1" валидны согласно RFC.но я не буду тратить время на написание предупреждения пользователю "оно конечно валидно согласно рфц, но я не уверен что ты просто не крошишь батон на клавиатуру - поэтому введи нормальную dotted-decimal запись". И тем более не буду такое передавать в библиотечную функцию в режиме "авось прокатит".
Чего и всем желаю. Не все стандарты (и тем более - "rfc") надо соблюдать побуквенно.
> но я не буду тратить время на написание предупреждения пользователю [...]. И тем более не буду такое передавать в библиотечную функцию в режиме "авось прокатит".К счастью, таких горе-программистов, как ты - меньшинство. А необучаемые бракоделы продолжают лепить дырени из-за болта, забитого на проверку входящих строк:
необучаемы те кто не фильтруют все эти прекрасные ../../.. на этапе получения ввода и только там. И наивно пытаются "соблюдать стандарты" там где этого делать вообще не надо.(например нормальный вебсервер на такой url должен отвечать чем-то вроде нгинксова 444 [который никакому стандарту не соответствует, между нами] и пинком blacklistd если есть, а не "безопастно обрабатывать")
> на этапе получения ввода и только там.П - производительность. Не, не слышали...
> Не все стандарты (и тем более - "rfc") надо соблюдать побуквенно.Да что ты? А как, по твоему, нужно соблюдать стандарты?
>> Не все стандарты (и тем более - "rfc") надо соблюдать побуквенно.
> Да что ты? А как, по твоему, нужно соблюдать стандарты?повторяю - там где у тебя есть untrusted input - никак их не нужно соблюдать.
А как ты проводишь валидность e-mail адреса ? По RFC 822, 5321, 5322 ? Или тупо на наличие @ и домена в MX записи ?
А то ведь uucp адреса никто не отменял ... А ещё кроме !, там есть и % и [] в валидных адресах.
Незнание закона не смягчает вины. Вроде всем известная ещё с детства фраза. Вполне переносима на любую сферу деятельности и правила/стандарты, которые в ней установлены.
В данной ситуации не прав Федор, поскольку правила определены, а он им не следует.
Нет таких правил принимать значение в любых нотациях. Достаточно в док-ции к функции написать допустимый формат. И желательно давать отлуп, если передано неожиданное значение.
> валидны согласно RFCИ что с того? RFC - это для взаимодействия чужого с чужим. Внутри софтины никто соблюдать RFC не обязан. Если автор либы прописал в мануале, что адрес IPv4 принимается только в формате N1.N2.N3.N4, где Nn - десятичные числа от 0 до 255, то либо автор использующей софтины должен озаботиться приведением IP-адреса к этому формату, либо искать другую либу.
> И что с того? RFC - это для взаимодействия чужого с чужим.Библиотека буквально принимает чужие IP извне.
> Если автор либы прописал в мануале, что адрес IPv4 принимается только в формате N1.N2.N3.N4,
Нет, не прописал.
Первое что должна сделать любая функция - убедитьсячто ей переданны корректные данные.
Тот кто не понимает зачем это нужно - необходимо запретить птсать код под угрлзой расстрела
Это если нет статической типизации. Если библа принимала "любую строку", то проверять должна. Если библа принимала свой же тип IPv4Address и явно прописывала это в доках или в d.ts, то проверять уже не должна. Второе предпочтительнее, так как рантайм-проверки небесплатные.
Так он сделает тип string и скажет, что валидация не его проблема.
> Первое что должна сделать любая функцияНе любая, в нормальных проектах две функции одна для использования из вне (условно ping(ip)), и она содержит всякие проверки, а вторая (условно _pingReal(ip)) которая не делает ничего кроме того что должна, в ооп для этого есть специальный функционал, чтобы нельзя было вызвать из вне, то что для этого не предназначено.
Хотя, если нам нужны более точные проверки, например, мы проверяем соотвествие ip тому что указан в бд, Тогда штатная проверка нафиг не нужна
В ещё более нормальных проектах не нужны эти костыли с двумя функциями и контракты можно описать системой типов и проверить на этапе клмпиляции
> контракты можно описать системой типов и проверить на этапе клмпиляцииКак ты проверишь на этапе компиляции IP, который известен только в рантайме?
Слышал звон, да не знаю, где он?
Жабаскриптер в треде? Система типов как раз и нужна, чтобы большинство рантаймовых проверок делать проверками при компиляции. Единственная рантаймовая проерка нужна во время создания объекта, а дальше всё уже проверено компилятором.
Робастная функция.Робастность подразумевает накладные умственные и организационные расходы и деградацию производительности.
А с вашей логикой, надо все языки с динамической типизацией запретить, иначе а вдруг в библиотеку придет объект не того типа. И сериализацию до кучи.
> То что при обращении к библиотечному вызову не была использована функция приведения IP к нормальной форме - проблема разработчика приложения.IP в виде "0x7f.1" - это нормальная форма согласно RFC.
> IP в виде "0x7f.1" - это нормальная форма согласно RFC.В документации к библиотеке написано, что она на 100% поддерживает rfc? Если нет, то причём тут rfc? Этак можно и какой-нибудь Microsotf Coding Guidelines отыскать, где ip-ареса задаются текстом на хинди, и жаловаться, что она их не поддерживает.
> Проверять корректность данных должно приложение, а не библиотека.Что проверять, если в буквально в статье написано, что у одного IP может быть разные представления? И все корректные.
127.1 — это (сюрприз!) корректный адрес. попробуйте его пингануть, например.
С открытием Вас!
> В CVЕ проблеме был присвоен критический уровеньБольше всего проблема в этом.
И что в этом смущает? Поведение библиотеки не может быть названо предсказуемым, если для одного и того же адреса в разной нотации будет возвращен различный результат проверки.
Нет, прав. Если требование функций библиотеки - "очищенные" данные на входе, то незачем нагружать данные функции дополнительными проверками, раздувающими код и снижающими быстродействие.
> Нет, прав. Если требование функций библиотеки - "очищенные" данные на входе, то незачем нагружать данные функциНет, не прав. "0x7f.1" - это валидное представление IP, здесь не нужно ничего "очищать".
Ну, напишем в документации, например
<IP4>::=<IP4_num>.<IP4_num>.<IP4_num>.<IP4_num>
<IP4_num>::=<first_digit><digit><digit>
<first_digit>::=0|1|2
<digit>::=0|1|2|3|4|5|6|7|8|9
И дальше сами,все сами
299.299.299.299
> фёдор не прав, неизвемстно откуда будут данные, не ему судить как применяется библаСори, чел, это Опеннет, поэтому тебе налепят минусов.
Местных комментаторов не волнует, что у одного и того же IP может быть разное представление, и г*код Федора работает только с одним из них, ибо стандарты для дураков.
их минусы проходят сквозь меня и не могут мне навредить
Обиделся, но исправил, лол
Смузи не поперхнитесь там
Глянул код, это в целом смузи-библиотечка, строчечки петушатся регэкспами на каждом шагу.Вон цикл конверта ipv6 в строку, добавить туда условие для свёртки повторяющихся нулей? Нет, лучше потом прогреть проц регекспами. Кто-то, бедный, потом будет логгировать айпишники и спрашивать почему LA зашкаливает.
} else if (length === 16) {
// IPv6
for (let i = 0; i < length; i += 2) {
result.push(buff.readUInt16BE(offset + i).toString(16));
}
result = result.join(':');
result = result.replace(/(^|:)0(:0)*:0(:|$)/, '$1::$3');
result = result.replace(/:{3,4}/, '::');
}return result;
};
А потом ещё жалуются, что для сборки фронтового приложения i7 нужен и собирается дольше, чем с++ с шаблонами. Короче, типичное js-программирование.
const ipv4Regex = /^(\d{1,3}\.){3,3}\d{1,3}$/;
const ipv6Regex = /^(::)?(((\d{1,3}\.){3}(\d{1,3}){1})?([0-9a-f]){0,4}:{0,2}){1,8}(::)?$/i;
...return /^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/
.test(addr)
|| /^0177\./.test(addr)
|| /^0x7f\./i.test(addr)
|| /^fe80::1$/i.test(addr)
|| /^::1$/.test(addr)
|| /^::$/.test(addr);
};
Вы вот прям уверены, что в жс развилка в цикле будет быстрее регекспа? Или у вас прувы есть?
Будут ли быстрее три ифа чем движок регэкспов?
Надеюсь это был юмор...
Так и ифы не нужны, когда case/switch ещё быстрее пройдет ветвление.
Мы всё ещё про яваскрипт говорим? Можете как-то подтвердить, что парсинг, интерпретация и выполнение вложенного ифа физически сводится только к трём ифам в бинарном коде?
Теперь я понимаю, что это был не юмор, но от этого менее смешно не становится))
Не поленитесь хоть раз написать тестовый код и с регексом и с ветлением, и самостоятельно убедиться насколько медленный первый.
Да понятно же, что "писать" он умеет только ручкой на бумаге. Сравнивать работу движка регэкспов который по сложности О-большое (если брать самую существенную операцию для этого алгоритма - сравнение символов) переплюнет любые ифы в цикле уже на этапе парсинга самого регэкспа - это даже для троллинга слишком толсто.
справедливости ради — современные движки обычно препарзят это всё на горячем пути.что, конечно, не отменяет тормозов даже зажитованой nfa.
> 0x7f.1, и 127.1 вместо 127.0.0.1Спасибо дидам за эту приколюху в спеках.
это да, рофлец.> $ ping 1234567890
> PING 1234567890 (73.150.2.210) 56(84) bytes of data.
> ...
> --- 1234567890 ping statistics ---
> 3 packets transmitted, 3 receivedсто лет назад так прятали бэкдоры в пхп скриптах, чтобы регексп [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} не нашёл
А что мешает использовать ([0-9]{1,3}\.){3}[0-9]{1,3}, сугубо незнание или любовь к гуавно-коду
этот регексп тоже не найдёт IP 1234567890
"Диды" для людей писали и заботились об удобстве. Они не думали, что спустя годы появится целая индустрия уродов, павнящихся друг с другом в бэкдоры за деньги и портящих всем жизнь. А общество будет их разрушительную деятельность терпеть и вознаграждать.
> заботились об удобствеДа, я прям преисполняюсь удобством, когда вместо 127.0.0.1 пишу 0x7f.1. А еще это удобно сопровождать. IPv4Address.parseFromString(), который вместо простого split('.').map(parseInt), assert(len == 4) превращается в простыню на несколько экранов — это же так удобно!
> Они не думали
Ты прав: они не думали. Не думали, что когда айпишник имеет более чем одно валидное строковое представление, это придется сопровождать вообще везде. Разработчик сделал поле ввода айпишника с предзаполненными точками, осталось лишь ввести четыре числа? [ ___ . ___ . ___ . ___ ] ? Дурак этот разработчик. Он что, не понимает, что пользователю гораздо удобнее вводить 16843009 вместо 1.1.1.1?
Бывают случаи, когда ip адрес должен быть записан в decimal без разделителей. Бывают и когда требуется heximal формат. Как пример, кодировка в ASN.1 для дальней космической связи. Октальная запись в таком случае оказывается избыточной. Деды с академическим подходом, то как раз молодцы, что предусмотрели многое. Проблема в смузи-поколении, что ограничены знаниями не дальше собственного носа.
Деды с академическим подходом, как раз думали о многом. В том числе о том, что может потребоваться десятичная запись без разделителей. И что может потребоваться шестнадцатиричная. И может быть выполнена оптимизация путем удаления назначимой части. Как пример, кодировка в ASN.1 для дальней космической связи. Где октальная запись избыточна.
Проблема в поколении, которое ограничено знаниями, не уходящими дальше собственного носа.
И о том, что потомки могут один раз написать конвертер , чем переписывать поддержку всех форматов , во всех функциях, всех библиотек.
> Деды с академическим подходом, как раз думали о многом. В том числе
> о том, что может потребоваться десятичная запись без разделителей. И что
> может потребоваться шестнадцатиричная. И может быть выполнена оптимизация путем удаления
> назначимой части. Как пример, кодировка в ASN.1 для дальней космической связи.
> Где октальная запись избыточна.
> Проблема в поколении, которое ограничено знаниями, не уходящими дальше собственного носа.а нахрена в дальней космической связи IPv4? впихивание его туда как раз и показывает, что это разрабатывали диды-олимпиадники.
выше — отличный пример того, почему современный софт весь гуано.
> загружалась примерно 30 млн раз в неделюИнтересно, сколько денег пожертвовали Фёдору за его труд все эти прекрасные люди.
Они нехило законтрибьютили в его резюме своей статистикой скачиваний. Эйчары точно текут с таких чисел.
Да нифига. Тут где-то была новость про чувака-автора подобной либы с миллионами скачиваний, который полгода сидел и не мог работу найти.
Чего-то он недоговаривает. Может он на собесы в шортах приходил? Иметь неплохое резюме -- лишь пол-дела. В любом случае, скинь ссыль.
>Может он на собесы в шортах приходил?А что, ныне надо в юбке приходить, назвавшись трансформером?
Попробуй в сторону цветных слово публично скажи ты и год ничего не найдешь.
Вот и я как-то прихожу как-то на собес в Apple, а там на ресепшене этот... Трансформатор, да ещё и в цвете. Стоит такой на каблуках, мускулами играет, серёжки аж потрясываются. Он меня спрашивает: вы кудааамммм? Я задумался куда, сдержал улыбку и говорю: я автор ядра linux, меня тут парнишка такой, русый онлайн собеседовал. Видимо в этот момент сработал regexp в голове у красотки, потому что следующее что я увидел - это струю из баллончика... А я так старался, писал для вас линукс
Нынче толерантность - можешь хоть в шортах. Главное чтоб все знали что ты этот...трансформер, во.
>>Может он на собесы в шортах приходил?
> А что, ныне надо в юбке приходить, назвавшись трансформером?Может он шотландец.
>с миллионами скачиванийЭто же скриптота. Там любая библиотека из трёх строчек может собрать миллионы скачиваний. Это ничего не говорит о квалификации веб гребцы.
Эйчары не знают о такой статистики, пока ты сам явно не пропишешь в резюме. Впрочем, при первичном отборе резюме, всё зависит только от того, чешется левая пятка у эйчара или правая. Изредка смотрят смузихлёб или нет, вторых не берут.
> Они нехило законтрибьютили в его резюме своей статистикой скачиваний. Эйчары точно текут
> с таких чисел.В какой вселенной? В нашей вселенной большая часть не особо знает что такое гитхаб, а остальная: "я проверила, у него много проектов на гитхаб" - которые в реале какая-то каша из форков известных либ с парочкой коммитов в README.md и те без PR.
> Они нехило законтрибьютили в его резюме своей статистикой скачиваний. Эйчары точно текут с таких чисел.Лол, с точностью до наоборот: эйчары видят безработного неудачника, батрачущего годами за бесплатно - и обходят его десятой дорогой, ибо понимают, что с ним что-то не так.
Собственно, история того чела - красноречивое тому подтверждение.
А потом 17 млн в неделю...
т.е. 13 млн - она была нафиг не нужна? что за цифры такие?
> А потом 17 млн в неделю...
> т.е. 13 млн - она была нафиг не нужна? что за цифры
> такие?да банально - эти 13 миллионов сами были никому не нужны - это автоматические пайплайны, которые ойпаламалася из-за того что в них сами не знают зачем засунули npm audit.
А ты думал, это 13 миллионов живых м@к@керов быстренько переписали код на другую (или, о б-жечки, самостоятельно написанную) версию этого лефтпада?!
Судя по первому комментарию Анонима(1), еще и облаяли, указав, что не ему решать и т.п.
> Суть уязвимость в использовании по умолчанию настройки libCurl (CURLOPT_SSL_VERIFYPEER=0), отключающей проверку сертификатов при загрузке внешних ресурсов по HTTPS, например, указанных в документе внешних изображений.Задолбали с этим HTTPS.
А браузерах точно так же, если трафик подписан сертификатом прокси, это не будет показано нигде. А вот курл при включённой этой опции выдаёт ошибку. Я отключал только потому, что значительно увеличивает время каждого запроса (или пользовался "впн", подглядывающими в трафик).
> Ложные CVEА я говорил, что большинство "уязвимостей" - это шлак, который плодят "безопасники", лишь бы свои чудо-продукты продавать.
"CVE" можно рассматривать всерьёз, если есть пруф, показывающий что и как мжно взломать / станять данные / заддосить и т. д.
Всё помнят как несколько лет назад стада бегали из-за log4shell в одном Java-логгере ? Никто, блжад, не ужосужился проверить насколько реально что-то с этим исполнить на конкретном проекте...
Ты прав в том что у настоящих уязвимостей которые в использовании нет никаких све и о них никто кроме специальных людей не знает и не узнает. А све присваивают всякому шлаку потому что на них есть план или надо отчитаться перед начальством.
Все правильно ему указали.То что он не валидирует входные данные в публичных методах апи - это баг.
Или делал бы методы приватными недоступными для импорта, или делай валидацию
Ну да, то что альтернативно-одаренный разработчик любую хрень из юзеринпут (потому что больше ей такой неоткуда браться - системные вызовы ТАК не работают) сует в эти методы - это безусловно не баг. Это фича.Разумеется библиотеки должны тратить миллионы циклов процессора на проверку того что ты должен был проверить еще при вводе. А то вдруг.
> Разумеется библиотеки должны тратить миллионы циклов процессора на проверку того что ты должен был проверить еще при вводе. А то вдруг.Разумеется. Это js, детка. Динамический язык, который не позволяет статически запретить передавать в функцию что-то кроме валидного ip-адреса. Все динамические языки из-за этого вынуждены тратить миллионы циклов процессора на многократные проверки одного и того же. Компилируемые с умными компиляторами иногда могут срезать количество проверок в ситуации, когда тип значения был проверен перед вызовом функции и потом внутри функции он снова проверяется, так зачем вторая проверка? Можно скомпилировать специальный вариант функции с выкинутой проверкой, и предпочитать её в тех случаях, когда значение заведомо проходит проверку. Как там все эти v8 поступают, я не знаю, но это не избавляет программиста от необходимости втыкать многократные проверки в сорцы.
Если тебя это не устраивает, пиши на языках со статической типизацией.
А он валидный. Согласно реэфсям.Отдельный привет как ты собираешься в своей статической типизации утрамбовать dotted decimal, partial dotted decimal и integer варианты в один тип. И как отличать потом ситуацию "юзер кульхаксор и всегда айпишники записывает integer'ами" от "у юзера слишком длинный хрен задевает клавиатуру"
> Отдельный привет как ты собираешься в своей статической типизации утрамбовать dotted decimal, partial dotted decimal и integer варианты в один тип.Элементарно, Ватсон:
struct IPv4Addr(u32);
impl IPv4Addr {
pub fn try_from_str(ip_str: &str) -> Result<Self, Error> { ... }
pub fn try_from_u32(ip: u32) -> Result<Self, Error> { ... }
// в зависимости от твоих нужд, ты можешь добавить методы типа:
pub fn try_from_dotted_decimal(ip_str: &str) -> Result<Self, Error> {...}
...
// когда закончил с этим, пишешь методы типа:
pub fn is_public(&self) -> bool { ... }
...
// и на тот случай, если этот ip-адрес надо засунуть в какой-нибудь внешний код, не знающий про данный тип:
pub fn as_u32(self) -> u32 { ... }
}Всё это уходит в модуль, значение u32 хранящееся в IPv4Addr недоступно никому, кроме кода в этом модуле, и этот модуль позволяет создавать значения типа IPv4Addr только через конструкторы, которые ты выверяешь согласно всем RFC, всей истории уязвимостей вызванных мизинтерпретациями какого-нибудь представления ip адреса, и потом ещё приплачиваешь специалистам за аудит твоего кода. После этого, если клиентский код выстроил невалидный IPv4Addr, например посредством принудительного приведения типа от [u8; 4] заполненного рандомом к IPv4Addr, то это проблемы клиентского кода, который готов идти на всевозможные исхищрения лишь бы получить баг.
Но забавна постановка вопроса: хранить ip-адрес в текстовом представлении... Подход идиотский (строки !Sized, и их из кучи придётся выделять), но так тоже можно, если очень хочется.
struct IPV4Addr(String);
impl IPv4Addr {
// уже String а не &str: пускай клиентский выделяет память под строку как хочет
pub fn try_from_string(ip_str: String) -> Result<Self, Error> {
// и вот тут мы проверяем ip_str, выясняем какая это репрезентация. Если это валидная
// репрезентация, то мы возвращаем Ok(IPv4Addr(ip_str)), если невалидная, то Err(...).
// Проверка таким образом будет выполнена единожды, и дальше компилятор сможет статически
// нам гарантировать, что любая функция принимающая IPv4Addr в качестве аргумента
// будет принимать IPv4Addr, который прошёл проверку здесь.
}
}> И как отличать потом ситуацию "юзер кульхаксор и всегда айпишники записывает integer'ами" от "у юзера слишком длинный хрен задевает клавиатуру"
Приведённый выше код тоже айпишники записывает интегерами, это единственно вменяемый подход. Сисколлы принимают ip-адреса в виде буферов из u8, в случае ipv4 это буфер из 4 u8, или другими словами u32. Текстовое представление может быть нужно только для вывода на экран, и оно выстраивается элементарно из u32 или из [u8; 4], это вполне можно делать тогда, когда надо. Это гораздо лучше, чем выделять память под строки, парсить эти строки каждый раз, когда хочется какие-либо операции над ip-адресом проделать (за исключением вывода на экран, хотя там я б тоже распарсил и нормализовал, а то мало ли что там за вредоносные esc-последовательности могут быть).
А если программист клиентского случайно клавиши на клавиатуре нажимает, то это не важно: код приведённый выше будет делать именно то, что он должен делать в ответ на тот вход, который он получит. Он решает проблемы _сохранения_результатов_проверок_, чтобы не надо было многократно проверять одну и ту же строку на валидность. Если методы написаны грамотно, то он решает ещё проблемы проверок: он берёт эти реализацию этих проверок на себя. Проблемы же косорукости программиста пишущего клиентский код он не обещает решать и не решает. Эти проблемы тебе придётся решать на своей стороне и свалить их на других у тебя не выйдет.
Единственное чем тут можно тебе помочь - это затолкать try_from_str куда-нибудь пониже, чтобы он в документации не отображался первым методом, и написать к нему подробную документацию с примерами того что этот try_from_str будет готов принять, и как он это будет интерпретировать. Можно ещё варнинг добавить, сказав что этот конструктор лучше не использовать, и он тут присутствует как знак почтения дедам, которые изобрели все эти идиотские способы записывать ip-адреса строками.
> Но забавна постановка вопроса: хранить ip-адрес в текстовом представлении...прости, ты их побитово ключом набираешь или как большие дяди - переключателями на пульте консоли?
А то я-то вот... текстом.
> Он решает проблемы _сохранения_результатов_проверок_, чтобы не надо было многократно проверять
> одну и ту же строку на валидность.тоже нет. В том месте где этот кот вызовется - юзер давно уже уехал с того диалога где вбивал цифирки. И либо ты выкинешь невнятную ошибку или вообще сегфолтнешься, потому что по другому уже некому и некуда. Проверять надо было в том месте откуда этот адрес взялся.
Ну и вот в том месте где он берется из операционной системы,а не левого источника - проверять особо и незачем. Во-первых непонятно что делать с результатом, во-вторых непонятно откуда возьмется.
А хранить в интах не принято из-за inet_ntoa()/aton - внезапно (модные современные программисты, как обычно, нихрена не разбираются ведь в том что они программировать пришли). А iton не предусмотрели, потому что внезапно он никому не нужен и усложняет отладку. Адрес, знаешь ли, удобнее все же иметь в читаемой форме, а не конвертить на калькуляторе каждый раз.
Кстати, забавно что они объявлены нимодно и deprecated, а то что вместо (правда, нигде не используется) ... опачки - НЕ ПОДДЕРЖИВАЕТ дурацкие rfcшные вредные и ненужные форматы.
> прости, ты их побитово ключом набираешь или как большие дяди - переключателями на пульте консоли?А это не проблема разработчика библиотеки. Это вот тот кто user-facing код пишет, вот он пускай и решает в каком виде ему лучше получать ip от пользователя. Библиотека не может и не будет решать эти вопросы, потому что для их решения необходимо знать специфику конкретного приложения.
> тоже нет. В том месте где этот кот вызовется - юзер давно уже уехал с того диалога где вбивал цифирки. И либо ты выкинешь невнятную ошибку или вообще сегфолтнешься, потому что по другому уже некому и некуда. Проверять надо было в том месте откуда этот адрес взялся.
В каком месте? Если мы выдаём пользователю диалог для ввода ip адреса, он нажимает кнопку submit, мы получаем какую-то строку и выстраиваем из неё IPv4Addr, если нам не удалось выстроить его, мы снова рисуем пользователю его диалог, подсвечивая поле ip адреса жырным красным цветом, мол, проверь свои кривые пальцы. Если же у нас IPv4Addr выстроился, значит он успешно распарсился, значит больше проверок валидности ввода нам уже не надо проводить, можно просто пользоваться этим адресом.
Или ты про какое-то другое место? Ты пил сегодня что ли? У тебя голова вообще не варит, не способна на элементарное логическое умозаключение: статическая типизация позволяет иметь одну проверку, эта проверка будет в одном из тех множественных мест, где эту проверку пришлось бы выполнять с динамической типизацией, и если динамическая типизация может во всех этих местах осмысленно обработать ошибку парсинга ip, то статическая типизация тоже сможет обработать эту ошибку в том одном месте, где она парсит. Видишь как всё просто? Бросай пить, вставай на лыжи.
> А хранить в интах не принято из-за inet_ntoa()/aton - внезапно
В js не принято хранить в int'ах, потому что там с int'ами надо очень аккуратно, в нём int запросто может быть 28 бит, или ещё что-нибудь такое интересное из-за бит, выделенных для сборщика мусора. В C я ни разу не видел, чтобы кто-то использовал бы основным форматом представления ip адреса строку. Исходные введённые строки иногда не выбрасывают, а хранят, чтобы пользователю можно было бы в лицо швырнуть айпишником в том виде, в котором он его ввёл, без всяких нормализаций, но и это я видел по-моему один раз.
Все эти функции нужны только потому, что диды со времён Гулливера никак не могли определиться с какого конца правильно инты писать, и на разных системах надо было в разном порядке байты ip адреса раскладывать, чтобы получалось одно и то же. Времена хаоса ушли, остроконечники победили, теперь у нас везде little-endian.
> Адрес, знаешь ли, удобнее все же иметь в читаемой форме, а не конвертить на калькуляторе каждый раз.
А ты конвертишь на калькуляторе? std::net::SocketAddr реализует Debug и Display, таким образом ничего конвертать не надо. Оно само.
Локалхостный код какой-то. Мне что, надо ещё как-то заранее угадать, что айпишник v4, а не v6? Спасибо, мне тпкие библиотеки даром не натть и за деньги не нать. Вот фигня, которая должна быть айпи-адресом, ты её проверь, разбери, и верни мне в удобоваримом виде, либо кидай исключение. И смотри не вывались нигде за границы массивов, а то знаю я вас!
> Локалхостный код какой-то. Мне что, надо ещё как-то заранее угадать, что айпишник v4, а не v6?да, ты не поверишь - надо. Потому что это два разных AF_ и два разных набора вызовов.
Нифига не взаимозаменяемых.
Какой AF_, дорогой? Я пользовательский ввод пытаюсь разобрать, мне туда «умудрённые» «опытом» «системные» «администраторы» и «программисты» не могут с первого раза валидный CIDR из циски скопировать.А там, где AF_, там уже заведомо валидные данные в правильной стуркутре. За две строчки до открытия сокета уже поздновато валидировать.
> Локалхостный код какой-то. Мне что, надо ещё как-то заранее угадать, что айпишник v4, а не v6?Охх, тебя не интересует теория как это работает, тебе надо сразу готовый код? Тогда тебе сюда: std::net::SocketAddr https://doc.rust-lang.org/std/net/enum.SocketAddr.html
Меня теория интересует только в контексте практики. Без практики — это всё болтовня в пользу бедных. Как говорится, talk is cheap.
> который не позволяет статически запретить передавать в функциюНи один язык не позволяет что-то статически запретить. Всегда можно в unsafe присвоить ежику зайчика. Поэтому максимум, что можно (в любом языке, в любом, узбагойся) -- это просто в документации сказать, что "я ожидаю в этой функции свой собственный тип IPv4Address, а если вы туда суете что-то свое -- это ваши проблемы, undefined behavior". В расте можно усложнить (но не запретить) передачу неверного типа через его явное указание: &self. В тайпскрипте тоже, addr: IPv4Address. Всё. Какой бы ни была статическая типизация, она лишь усложняет неверные действия, но не запрещает их полностью. В рантайме всё что угодно может произойти.
Да и ты не рассмотрел ситуацию, когда клиент библиотеки уже гарантированно знает, что валидировать ничего не надо, потому что он получает айпишники например из БД, из колонки с типом "ipv4-адрес". Нахрена библиотеке дополнительно проверять? Чтобы увеличить время обработки всех записей в БД?
> Разумеется библиотеки должны тратить миллионы циклов процессора на проверку того что ты должен был проверить еще при вводе.Нн поверишь, но сабж тоже тратит: все функции этой либы бросают исключение при невалидном IP. Все, кроме упомянутых isPublic() и isPrivate() - они написаны с ошибкой, и поэтому проверки не происходит.
Никто не утверждал, что это не баг.Утверждается, что это не уязвимость. Не всякий баг является уязвимостью.
Что правильно? Почитай новость внимательнее, там не юзеринпут юзается,а результат сисколов.
Грубо говоря, допустим есть ф-я SomeSysCall() которая по спеке выдает 0 или 1. Допустим ты используешь ее в своем проекте. И тут появляется какой-то мутный тип, который начинает вещать: "А вдруг она вернет 3, а вдруг она вернет кубический корень из 42,а вдруг она вернет колбасный обрезок или банановую кожурку" и лепит раздутый CVE помеченный как "супер-мега-критический-мы-все-умрем". Другой дебил не особо вдаваясь в содержание этой простыни подтверждает ее и все, коллеги смотрят на тебя косо и думают:"эээ друк, так ты оказывается рукожоп".Так ситуация стала более понятной?
> Что правильно? Почитай новость внимательнее, там не юзеринпут юзается,а результат сисколовИзвини, но нет. Там нигде не юзается результат сисколов - это автор либы *предполагает*, что айпишник ты поучишь из этих самых сисколов.
А если из другого места - то сорян: г*код из его либы будет возвращать разные результаты для одного и того же айпишника в разных представления.
> "эээ друк, так ты оказывается рукожоп".
Именно так по факту и оказалось.
Честная конкуренция? Это только в теории...
А на практике любая конкуренция - это процесс угнетения конкурента, а не саморазвития.
Противоположность конкуренции - взаимопомощь.
Читай внимательнее. Зарепортивший -- не конкурент, а просто хотел по-быстрому срубить баблишка за выявленный CVE.
Мог бы джва года писать такую библиотеку, а захотел по-быстрому. Вполне "конкурент".
На какой такой практике? В универе что ли?
Пора заводить черные (ок, сомнительные) списки для таких "репортеров", которые за баблишко людей отвлекают от работы. И как только такой спец нашел "уязвимость" сразу мордой его об черный список.
Затрахать мозг разработчику -> стать мейнтейнером проекта -> внедрить троян. Что-то такое недавно было.
Вообще-то у автора библиотеки классическая уязвимость: сделано допущение ошибки, в расчёте, что третья сторона никогда не вернёт неверные данные.Что в общем случае не так.
И это глобальная причина у многих ленивых. Чтобы меньше напрягаться, быстрее написать. Но зато с проблемой под капотом. Обыкновенная халтура.
Классика кодинга: проверяй данный, которые получаешь из другого кода, иначе пришлют эксплойт в конце концов.
А если будешь проверять, то подгрузят руткит по LD_PRELOAD в конце концов. А если соберёшь статически, то... ;)
Не нравится - пиши всё своё.
Вообще-то речь про другое.Пиши нормально или - отваливай. Что и сказали автору из новости, создав CVE.
Там фикс одна строчка в реадми: подавайте на вход IP адреса в виде как они получаются на выходе системных функций.
Большие конторы подобные баги "устраняют" проще:
Это не баг, это фича! ;)
Насколько помню/понимаю, такой подходд вообще характерен для репов Ноды, и ещё раньше - для Пипа.Это именно одна из причин в критике JS и Питона. Питон выправляется понемногу, видны хотябы следы работы по чистке. Про JS совсем не в курсе...
Для любые репов даже для репы дистра.
Эти-то выделялись своей культурой. На фоне остальных.
Ты за каждый васянодистр говоришь или за все?
Смысл у слова "остальные" однозначно отвечает на твой вопрос.
Так там все плохо лучше нпм и пупи.
NPM и PyPi выделялись своей культурой в худшую сторону. На фоне остальных.
> но за 5 месяцев число загрузок снизилось до 17 млн в неделюТо есть разработчика волнуют в первую очередь звездочки на гитхабе, а не безопасность? Ну это типичный представитель жс мирка. Ещё и напоследок ножкой топнул^W^W остановил разработку. Стыдно должно быть за такое инфантильное поведение.
>В частности, для совершения атаки необходимо добиться передачи своего значения в функции isPublic() и isPrivate(), в то время как информацию об IP-адресе подключающегося клиента, как правило, получают из системных функций или переменной окружения web-сервера, которые изначально выдают только корректные значения.Это не Фёдору Индутному решать, как пользователям его либы эту либу использовать. Может они списки IP-адресов из файла читают. Либа безусловно нарушила контракт, и это нарушение контракта может привести к опасным последствиям, напр. при использовани либы для анализа логов в системах IDS. Вместо того, чтобы достойно признать наличие уязвимости, автор либы повёл себя как истеричка, расстроенная ударом по своему эго, которое нанесло падение популярности либы. Но то что популярность упала, репозиторий переведёт в режим read-only, и пользователи перейдут на другую либу, от более адекватных разрабов - это хорошо.
Да болт с вами, не нравится - присылайте пулл регвесты с фиксами.
действительно. ишь, хам какой: работает бесплатно и не хочет при этом по щелчку пальцев подпрыгивать. он Обязан Же!
Так он психанул и полностью снес свою разработку в стиле "Пошил вы все на"?
> Так он психанул и полностью снес свою разработку в стиле "Пошил вы
> все на"?нет, просто на время заблочил возможность сыпать ненужные очень важные (нет) автогенеренные issues и верещать в чятике.
> на время заблочилЕсли нельзя завести issue, то их нет (с) black smart guy
Автор несколько уныл.Надо было или забить и добавить автофильтр на мыло чтобы само им отвечало "not a bug!" или открыть краудсорсинговую компанию по сбору 1м$ на исправление проблемы.
А сколько там загрузок в месяц/год - не важно, пока это никак не конвертируется в доход.
Почему вообще в nodejs в стандартной бибилиотеке нет этого функционала?
потому что «функционал» — это функция, заданная на произвольном множестве и имеющая числовую область значений.