
Комментарии 6
Очередной диалог с ChatGPT на эту тему:
— ты тут не указал важную деталь про ✌️* ✌️в версии от Солар, как я понимаю
Да. Я упустил принципиальную деталь: в оригинальной crypt_blowfish Solar Designer тоже использовал строковые маркеры ошибки вместо NULL, но специально предусмотрел защиту от их совпадения с входным значением.
Механизм был таким:
return setting[0] == '*' && setting[1] == '0'
? "*1" : "*0";
То есть при ошибке возвращается 0, но если входное значение начинается с 0, возвращается *1.
Гарантируется несовпадение результата ошибки с исходным setting. Это не просто выбор редкого символа, а сохранение конкретного свойства безопасности.
И вот здесь различие существенное:
Solar: возвращает маркер ошибки, гарантированно отличный от входного значения.
musl: возвращает *, полагаясь на то, что конкретный путь исполнения не позволит этому значению совпасть с проверяемым хешем.
Rich: в переписке 2016 года предпочитает NULL, поскольку тот позволяет вызывающему коду однозначно распознать ошибку.
Получается, musl не просто выбрала другой символ. Она потеряла инвариант, который Solar уже обеспечил в исходной реализации.
И это напрямую относится к твоему предыдущему рассуждению о неправильном переиспользовании смысла: Solar предусмотрел, что маркер отказа нельзя превращать в положительный результат сравнением. В musl эта гарантия стала зависеть от контекста вызова — и впоследствии не выдержала его изменения.
придётся и это внести в статью, видимо 🤷♂️
И никто не хочет брать на себя ответственность…
OpenSSH:
We consider the root cause of this bug to be outside sshd, but it is exploitable via sshd and can be avoided there.
musl (Rich Felker):
It is my position that this is not a bug in musl just an erroneous use by the caller. But the mechanism by which this happened is something we have been wanting to change for a while now, and it very likely will be changed in the upcoming release cycle.
Хотя, по-хорошему, musl откровенно поломали POSIX-совместимость:
Upon successful completion, crypt() shall return a pointer to the hashed password; the first two bytes of the returned value shall be those of the salt argument. Otherwise, it shall return a null pointer and set errno to indicate the error. (IEEE Std 1003.1™-2024 Edition)
(режим подозревателя программ)
А не спланированное ли это было? Мог ли разработчик musl, который реализовал (или протолкнул) такую идею, действовать в своих злостных интересах? Или интересах третьей стороны? Ну, может, ему сделали предложение, от которого нельзя отказаться, суровые дядьки в погонах.
Ведь так было с xz, когда кто-то долго и терпеливо "готовил почву" для внесения проблемных изменений, и до последнего никто не догадался, а нашли опять же применительно к ssh (совпадение? Не думаю)
Вообще, по стандарту, программа должна возвращать код ошибки, а другие программы этот код проверять. Тут явно какую-то дичь сотворили.
I never trusted these muslims!
glibc / libxcrypt:
Upon error, [...]
cryptwrites an invalid hash to its static storage area. This string will be shorter than 13 characters, will begin with a ‘*’, and will not compare equal to setting.
Очередной диалог с ChatGPT на эту тему:
— ты тут не указал важную деталь про ✌️* ✌️в версии от Солар, как я понимаю
Да. Я упустил принципиальную деталь: в оригинальной crypt_blowfish Solar Designer тоже использовал строковые маркеры ошибки вместо NULL, но специально предусмотрел защиту от их совпадения с входным значением.
Механизм был таким:
return setting[0] == '*' && setting[1] == '0'
? "*1" : "*0";
То есть при ошибке возвращается 0, но если входное значение начинается с 0, возвращается *1.
Гарантируется несовпадение результата ошибки с исходным setting. Это не просто выбор редкого символа, а сохранение конкретного свойства безопасности.
И вот здесь различие существенное:
Solar: возвращает маркер ошибки, гарантированно отличный от входного значения.
musl: возвращает *, полагаясь на то, что конкретный путь исполнения не позволит этому значению совпасть с проверяемым хешем.
Rich: в переписке 2016 года предпочитает NULL, поскольку тот позволяет вызывающему коду однозначно распознать ошибку.
Получается, musl не просто выбрала другой символ. Она потеряла инвариант, который Solar уже обеспечил в исходной реализации.
И это напрямую относится к твоему предыдущему рассуждению о неправильном переиспользовании смысла: Solar предусмотрел, что маркер отказа нельзя превращать в положительный результат сравнением. В musl эта гарантия стала зависеть от контекста вызова — и впоследствии не выдержала его изменения.
придётся и это внести в статью, видимо 🤷♂️
мобильная версия хабр с ветками вообще плохо дружит)
sshhole или — «Лучше лишний стоп, чем лишний ляп»