1. PHP / Говнокод #17118

    +167

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    function advancedMD5($parol) {
     $zashita = 50;
     for( $i = 0; $i < $zashita; $i++ ) {
      $parol = md5($parol); 
     }
     return $parol;
    }

    Неповторимый инновационный алгоритм шифрования паролей...

    Запостил: alexxkur, 16 Ноября 2014

    Комментарии (43) RSS

    • Почти PBKDF2... Только соль и xor забыли.
      Ответить
      • и на сколько я помню, безь соли этот код не особенно эффективен.

        с другой стороны, повторять md5 не имеет большого смысла - хэш уже давно сломан.
        Ответить
        • > хэш уже давно сломан
          Он взломан только по основному назначению, т.к. научились создавать вполне осмысленные файлы с одинаковыми хешами. А необратимость, емнип, не пострадала.

          А для хеширования паролей любая одиночная хеш-функция не имеет большого смысла, т.к. вычисляется слишком быстро. Ради этого и мутили все эти PBKDF2 да bcrypt'ы с scrypt'ами.
          Ответить
          • P.S. Но даже кошерная KDF никак не спасёт юзера с паролем 123456. Впрочем... ССЗБ. Его даже SRP не спасёт.
            Ответить
            • Идея: при регистрации запрещать пароль 123456, а при смене пароля разрешать. Тогда хакер будет думать, что пароля 123456 ни у кого нет.
              Ответить
              • 1) Много ли людей додумается менять пароль на 123456, если им изначально не дали его вбить?
                2) Если об этом написано в доке или доступны исходники - хакер будет думать иначе.

                Не айс ;)
                Ответить
                • 2) Не писать в доке, а на боевом сервере вероломно выложить скрипты, отличающиеся от опубликованных исходников.
                  Ответить
                  • Если уж тупые* юзеры догадаются, что можно юзать 123456, то хакер - тем более.

                    * т.к. не тупые не будут менять пароль на 123456
                    Ответить
                    • А вдруг это дырка для админа? Ну не ставить же на админку сложный пароль, который легко забыть!
                      Ответить
    • Кстати, а может ли получиться так, что при большом значении параметра $zashita все пароли определённой длины отобразятся на одно значение?
      Ответить
      • Ну длина пароля тут точно ни на что не повлияет. Если существует x = f(x), то там хуева туча рандомных паролей в одну точку сойдется... А если не существует - будут просто бегать по кругу.
        Ответить
        • Действительно, длина ни при чём. Она только немного ограничивает набор стартовых значений.

          Кстати, в php есть уникальные грабли: если потом контрольную сумму, хранящуюся в string, сравнивать через == вместо ===, то столкновений будет ещё больше!
          Ответить
          • Из-за 0e? В последних пыхах вроде бы пофиксили этот косяк со сравнениями...

            http://ideone.com/qTdAO2
            Ответить
            • php -r"echo strval('123456789012345678901234567890'=='123456789012345678900000000000');"


              В PHP 5.4 действительно пофиксили. Но во всё ещё популярном 5.3 всё плохо.
              Ответить
              • >123456789012345678901234567890==1234567 89012345678900000000000
                Это ж плавпитух, от него в разных местах страдают многие (и не только скриптовые) языки, например тот же js.
                Ответить
                • Если бы я сравнивал числа, я бы ожидал, что плавпитух подкрадётся сзади и клюнет. Но я сравнивал строки. А пых решил, что он лучше знает, что мне нужно, и сравнил их как числа.
                  Ответить
                  • А. В этом плане. Как-то проморгал кавычки.
                    Но как можно в динамически типизированном языке быть 100% уверенным что сравниваешь строки???
                    Никто ж не пишет перед каждой операцией конверсию переменных в нужный тип — тогда весь смысл языка теряется.

                    Вот жс строку с интом тоже говняет:
                    '123456789012345678901234567890' == 123456789012345678900000000000 //true
                    Ответить
                    • Ну вон тот же питон пинает неуверенных по яйцам... И надо руками приводить в нужную сторону. И это хорошо.

                      В перле тоже направление каста однозначно и определяется оператором.
                      Ответить
                    • Именно поэтому нужно:
                      1. Отменить ==, а вместо него использовать ===. Всегда.
                      2. Если нужно сравнивать значения (предположительно) разных типов, то использовать явное преобразование:
                      intval('0e12') === intval('0e13')
                      floatval('0e12') === floatval('0e13')
                      strval('0e12') === strval('0e13')
                      и так далее.
                      3. Наконец, и от безумных intval/strval отказаться в пользу более явных. Вместо strval использовать что-то типа sprintf, где можно указать желаемый формат. Вместо intval — функции округления, как предлагает Борманд.
                      Ответить
                      • > 1. Отменить ==, а вместо него использовать ===. Всегда.
                        Может лучше выпилить ===, а == пусть работает как ===? Зачем лишнюю палку то писать?

                        А вообще, с такими переделками, проще послать пыху нахуй и уйти на какой-нибудь питон.
                        Ответить
            • php -r"echo strval('0e12' == '0e13');"


              Чёрт! В 5.6 та же питушня, и даже в экспериментальном 5.7/7.0 тоже.
              Ответить
              • А багофича то и правда живее всех живых... http://ideone.com/nricO4

                В пёрле все же лучше сделали - отдельные операторы для сравнения чисел и строк. Всегда понятно, что именно произойдет.
                Ответить
                • Увы, не только для коротких. Удалено модератором.

                  И в PHP 5.6 то же самое. Поэтому только ===, только хардкор.
                  Ответить
                  • Я обновил код, сорри, посмотри еще раз ;)
                    Ответить
                    • Жесть ваще.
                      Ответить
                      • Ну собственно в этом и заключалась уязвимость - все хеши, которые начинаются на 0e равны 0e<куча ноликов>. Поэтому 0e<куча ноликов> канает с вероятностью 1/256, а не 2^(-128), как ожидали наивные пыхеры.
                        Ответить
                      • Косяк в мускуле тоже был связан с кастом и 1/256.

                        P.S. Предлагаю запретить "преобразование типов" и вообще выпилить нахуй это бессмысленное и ни о чем не говорящее понятие.
                        Ответить
                        • Причем выпилить как неявное, так и явное. Разве что неявный upcast ссылок на объекты оставить, как самое непорочное проявление сего феномена. А все остальные "преобразования" - функциями.
                          Ответить
                          • Я тоже за функции, ибо не существует однозначного способа преобразовать число в строку или наоборот. Какая система счисления? По какому алфавиту представление шестнадцатеричных чисел? Нужна ли дробная часть? Сколько знаков брать? Какой разделитель? Нужна ли экспоненциальная форма? Да там сплошные вопросы, на которые неявное преобразование отвечает случайным образом.
                            Ответить
                            • >>Я тоже за функции, ибо не существует однозначного способа преобразовать число в строку или наоборот.
                              А сравнения?
                              Сравнивать строковой вид объектов, сравнить с глубоким/неглубоким обходом, просто сравнивать ссылки/указатели, сравнивать плавающие с эпсилоном, без? Сколько таких штук =, ==, ===, ====, ===== надо ввести в язык?

                              Причем это я молчу о сравнениях с преобразованиями типов.
                              Ответить
                          • >Причем выпилить как неявное, так и явное.
                            А ну это именно то о чем так долго говорили Тарас и большевики.
                            Лично я ненавижу сишкоблядские касты, о чем говорил неоднократно.
                            Во-первых это невозможно быстро нагуглить, если не знаешь слова cast, а когда неявно преобразуется, то и вовсе без прочтения половины доки/стандарта языка не поймешь как же оно работает.
                            Гораздо понятнее было бы типа аналог конструктора int(2.0), чем (int) 2.0, ну или функция toInt(2.0).

                            PS> А можно поподробнее про баг в мускуле, помню тред тут проскакивал, но детали совершенно выветрились из моей памяти.
                            Ответить
                            • Там, за неимением настоящего, замутили свой бул с блекджеком и шлюхами. Само собой из чара. А затем сдуру кастанули результат мемцмп в него. Это работало, т.к. мемцмп всегда возвращал маленькое число. Но потом мемцмп, перформанса ради, оптимизнули, и оно стало возвращать настоящий инт (согласно ману - всегда имело право). Как результат - каст в "бул" просто обрезал его, и с вероятностью 1/256 можно было получить нолик, который трактовался как совпадение.
                              Ответить
                            • Int(2.0) и toInt(2.0) тоже впизду, т.к. семантика неочевидна. Надо оставить только round, floor, ceil и прочие явные операции.

                              Ведь мы думаем об округлении, взятии целой части и.т.п. а не о неведомом приведении флота к инту...
                              Ответить
                              • > Ведь мы думаем об округлении, взятии целой части и.т.п.
                                Придётся тогда тащить вывод типов в каждый язык с floor и его товарищами или плодить неведомые конструкции.

                                Хочу я, например, округлить число и сохранить его в переменную.
                                Сейчас: double x = round(3.5); int x = round(3.5);
                                С крайне полезными floor/ceil с очевиднейшей семантикой без вывода типов:
                                double x = round<double>(3.5); int x = round<int>(3.5);

                                Или придётся оставить касты, но привинтить много новых интересных типов:
                                struct Double {
                                  operator int() { throw "лакни мои типы"; }
                                private:
                                  double value;
                                };
                                
                                struct IntegralDouble {
                                  operator int(){ return int(value); }
                                private:
                                  double value;
                                };
                                
                                template<typename T>
                                IntegralDouble round(const T& number){ ... }
                                
                                template<>
                                IntegralDouble round<Double>(const Double& number){ ... }


                                P.S. Ещё шаг - и автоматическое доказательство корректности программ придёт к нам.
                                Ответить
      • Статейку по теме нагуглил: https://davidlyness.com/post/fixed-points-of-hash-functions

        63%, что существует такое x, что x = f(x).
        Ответить
        • Существует != можно найти за приемлемое время.
          Ответить
          • Тут запахло бездоказательным утверждением что P!=NP. Хотя я тоже придерживаюсь гипотезы что они не равны.
            Ответить
    • Se posent sur ma bouche mais jamais sur mon coeur
      Une parole encore.
      Paroles, paroles, paroles
      Écoute-moi.
      Paroles, paroles, paroles
      Je t'en prie.
      Paroles, paroles, paroles
      Je te jure.
      Paroles, paroles, paroles, paroles, paroles
      Encore des paroles que tu sèmes au vent
      Voilà mon destin te parler....
      Ответить
    • В платной версии zashita = 60, так что система получается более секурной и ее можно использовать в интерпрайзпе
      Ответить

    Добавить комментарий