Пользователь
250,2
рейтинг
20 мая 2012 в 01:19

Разработка → Массовая уязвимость в проектах на Ruby

Опубликовано сообщение о массовой уязвимости в проектах на Ruby. Речь идёт об использовании ^ в начале строки и $ в конце строки регулярных выражений вместо \A и \z.

Дело в том, что ^ и $ в таких случаях воспринимается Ruby как новые строки (\n), что открывает двери для инъекций.



Хотя официальное руководство по безопасности Ruby on Rails предупреждает об этой опасности, но всё равно подобная небрежность встречается в 90% проектов на Ruby, в доказательство чего приводятся примеры на Github, Scribd, Tumblr и других сервисах.

Как и в прошлый раз c Rails, здесь можно спорить, баг это или «ожидаемое поведение» системы. Но если большинство разработчиков делают ошибку из-за такой «особенности», так почему бы не исправить правила обработки строк в Ruby?
Анатолий Ализар @alizar
карма
739,5
рейтинг 250,2
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (65)

  • +11
    «Ruby uses a slightly different approach than many other languages to match the end and the beginning of a string.»

    Стандарт для современных регулярных выражений — это Perl-совместимые. Почему они не поддерживались при проектировании языка — непонятно, но те самые 90% программистов об этом наверно и не подозревали.
    Из-за в частности таких придумок Ruby я избегаю насколько возможно. К сожалению, хорошие программы на нём есть, и не использовать их не удаётся.
    • 0
      > К сожалению, хорошие программы на нём есть, и не использовать их не удаётся.
      А вот это уже интересное заявление. Можно примеры таких программ на Ruby от которых Вам не хотелось бы отказываться или заменять на аналоги? Если не ошибаюсь, то лично я не пользуюсь ни одной Ruby программой.
      • 0
        homebrew?
        • 0
          Это как я понял некое подобие checkinstall с закосом под порты? Извините, но с OS'X не довелось пообщаться.
          • 0
            Просто source-based менеджер. Как порты только нет категорий и часть ставиться из пакетов, а часть из сорцев (можно все из сорцев)
            • 0
              GitLab
              • 0
                Причем тут GitLab? GitLab это сервис хостинга git репозиторией.
                • 0
                  … написанный на Ruby, от которого мы в нашей компании не можем отказаться в силу отсутствия достойной конкуренции

                  это был ответ Alukardd-у, просто случайно как продолжение ветки запостил

                  интересно, кстати, заминусовали ответ или сам GitLab как продукт?
                  • 0
                    Я не знаю, я GitlLab использую.
      • +4
        Зачем заменять на аналоги то, что работает? Зачем отказываться от того, что изящно? Зачем переходить на заведомо более слабые языки с более сильных? Разумеется, речь не идёт о Си. Пожалуй, это единственный язык, от которого нельзя отказаться.
        • +1
          Даже если уйти от споров на тему «что лучше», т.к. это бесконечный разговор, то почему Вы решили что нету такого понятия как «приязнь»? Для программиста ЯП это инструмент, для пользователя это материал, а эти вещи весьма субъективны. Почему я не могу сказать, что я не люблю Java как пользователь т.к. на машине надо держать какую-то ВМ, что бы она что-то запускала?.. (это просто пример)
          • +2
            А для руби или пхп этого уже не надо? Они уже в ядре? ;)
            • +1
              Вот у меня Ruby и не стоит, просто для примера написал Java. Как я уже заметил выше, я не использую ни одной программы на Ruby и соответственно его интерпретатор у меня не стоит.
          • 0
            почему Вы решили что нету такого понятия как «приязнь»?

            Почему Вы решили, что я так решил?
            Комментарий был к фразе
            Можно примеры таких программ на Ruby от которых Вам не хотелось бы отказываться или заменять на аналоги?

            которая звучит так, будто руби — чудовищный язык, от которого любой нормальный человек должен хотеть отказаться и как можно скорее заменить на аналоги.
            • 0
              Ну, мой комментарий вполне логичен, если прочитать предыдущий:
              К сожалению, хорошие программы на нём есть, и не использовать их не удаётся.
              Вот и хотелось услышать что «не удаётся не использовать».
      • +16
        Redmine
        • 0
          Весьма специфичное приложение. Однако, пример засчитан.
          p.s. ответ сразу всем 4-м комментаторам.
      • 0
        Redmine
      • +3
        Redmine? ))))
      • +1
        Redmine!
      • +1
        Chef, Vagrant
        • 0
          Вот! Спасибо. Я дождался ответа, важного лично для меня. Chef, puppet — две вполне годные программы и написаны на Ruby. И пусть в виду неких прений с начальством на прошлой работе мне так и не удалось попользоваться puppet'ом, я всё равно считаю его удобной программой.
        • 0
          Salt весьма хорошая альтернатива, написана на python. Имхо, понятнее и проще чем puppet,
          • 0
            puppet вообще зло.
      • +1
        Capistrano
      • 0
        Redmine, Chef, Puppet
    • +8
      > Стандарт для современных регулярных выражений — это Perl-совместимые. Почему они не поддерживались при проектировании языка — непонятно, но те самые 90% программистов об этом наверно и не подозревали.

      Согласен, что всегда надо разрабатывать по принципу «наименьшего удивления». Т.е. делать именно ожидаемое поведение системы/модулей/классов/функций и т.д.
    • +2
      Складывается впечатление, что в Ruby многострочный режим в регулярках включен по-умолчанию, отсюда и такое поведение. Хотя это по-моему неправильно, иначе зачем тогда модификатор 'm'? Поведение '^' описанное в проблеме как раз подходит под описание работы в многострочном режиме.
      • 0
        извиняюсь, не в той ветке написал
    • 0
      Моя бабушка так-же отказывается использовать новый утюг когда мы ей его подарили, говорит слишком сложно и непредсказуемо выпускает пар при нажатии на кнопку
  • +18
    Как прославиться:
    1. Читаем guides.rubyonrails.org
    2.…
    3. PROFIT!
    • +3
      да.
      • +5
        омг, снова ваша работа?)
  • +4
    ну вообще в posix-regex ^ — это поиск по линиям(по каждой строке в отдельности), \A — поиск по всей строке целиком.
  • +1
    да и в perl-regex собственно тоже
    • 0
      Нет, в perl это поведение включает специальный ключ, который надо писать у каждого выражения.

      Единственная особенно по-умолчанию в Perl — что $ допускает перевод строки после него (и только перевод строки, после него ничего уже не должно быть).
      • 0
        да, такое тоже бывает — \Z позволяет перевод, \z уже нет.

        в руби банально нет ключа чтобы заставить ^ матчить начало строки. Надо просто заменять на \A. Так сказала партия.
  • НЛО прилетело и опубликовало эту надпись здесь
    • –2
      ммм цель немножко другая, исправить неочевидное поведение языка. Y U NO тут причем )
      • НЛО прилетело и опубликовало эту надпись здесь
        • –2
          пожалуйста. правда не совсем понятен смысл мемо пикч — сарказм или что это? в любом случае я поржал, за что вам спасибо.
        • 0
          есть некая грань между ленивыми растяпами и github/tumblr/scribd, этому и посвещен пост. если все ошибаются может стоит «изменить систему» лол
          • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              Да, это весомый аргумент :) Проблема существует и ее нужно решать.
    • +2
      большинство кодеров невнимательны, не читают документацию и не знакомы с best practicles и ключевыми рекомендациями по своему языку.

      Обычно это приводится в качестве недостатка PHP :)
    • +1
      Непонятно только, кто писал ГитХаб — лентяи или самоучки? А может лентяи самоучки?
  • 0
    Пойду на всякий случай проверю…
  • НЛО прилетело и опубликовало эту надпись здесь
    • –7
      SO MUCH LOL'D.
      • НЛО прилетело и опубликовало эту надпись здесь
  • +10
    Попробуйте brakemanscanner.org — он отлично находит подобные ошибки в rails-приложения.
    • –7
      людям кто знает эти вещи сканеры не нужны. а кто незнает — незнают о сканерах в том числе. Хотя проект хороший
    • +3
      Отличный инструмент, спасибо!
    • 0
      Огромное спасибо за ссылку
  • 0
    Складывается впечатление, что в Ruby многострочный режим в регулярках включен по-умолчанию, отсюда и такое поведение. Хотя это по-моему неправильно, иначе зачем тогда модификатор 'm'? Поведение '^' описанное в проблеме как раз подходит под описание работы в многострочном режиме.
    • –2
      Честно говоря, до сих пор не понимаю use-case для многострочного режима в регулярных выражениях (по крайней мере на PHP).
      • 0
        С ключом g легко писать циклы по строкам внутри длинного текста (вместо split):

        $_ = "1st\n2nd\n3rd\n";
        
        while(/^(.*)$/gm) {
            say $1;
        }
        
  • +3
    Написал о проблеме разработчикам Ruby, и вот ответ:

    «In Ruby there is no multiline flag, regexps in Ruby are always in multiline mode. See advogato.org/person/fxn/diary/498.html for some gotchas regarding regexp flags in Perl vs Ruby.

    In Ruby, you need to use \A and \z (or \Z) to match start and end of string.



    Ruby won't prevent you shooting your foot.»

    Как я и предполагал, в Ruby просто всегда по-умолчанию многострочный режим, поэтому надо пользоваться \A \z.
    • 0
      И еще вдогонку из документации:

      ^ — Matches beginning of line
      $ — Matches end of line
      \A — Matches beginning of string.
      \Z — Matches end of string. If string ends with a newline, it matches just before newline
      \z — Matches end of string

      И описания хорошо видно, что работает с полной строкой (даже многострочной), а что с line в строке.

      Хотя на самом деле с непривычки это несколько обескураживает, но привыкнуть можно. По крайней мере я после прочтения книги о Ruby как-то сразу для себя уяснил это и использовал в первом же regexp именно \A и \z. Но, согласен, что по невнимательности это может привести к проблеме.
      • –3
        спасибо! Да, разумеется руби по умолчанию в этом режиме. Но это огромный фейл «Ruby won't prevent you shooting your foot» это был сильный промах руби изначально пойти по такому пути. Я не думаю что реально поднять уровень знания об этой проблеме достаточно высоко. Куда проще было бы принять свой фейл и выйти из мультилайн режима.
        А так да, конечно, «you need to use \A and \z (or \Z) to match start and end of string» мы это и так знаем. Эдакое «тайное» знание
        • +3
          Дело не в тайных знаниях. Дело в привычке. Те, кто не привык к тому, что многострочный режим НЕ используется по-умолчанию, при переходе на Ruby будут ошибаться.
          Ну а по-хорошему, наверное, чтобы писать на Ruby надо внимательно читать документацию и просто писать правильно. Как ни крути, а есть отличия…
      • –3
        ссылочку не дашь пожалуйста на ответ руби?
  • +4
    хомяков снова открывает америку, в следующий раз напиши плиз о шифровании паролей или настройки файрвола

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.