Comments 31
ideone.com/VR2B8W
Я, конечно, слышал, что рандомность Random весьма условна, но чтоб настолько...
The System.Random class and thread safety
Instead of instantiating individual Random objects, we recommend that you create a single Random instance to generate all the random numbers needed by your app. However, Random objects are not thread safe. If your app calls Random methods from multiple threads, you must use a synchronization object to ensure that only one thread can access the random number generator at a time. If you don't ensure that the Random object is accessed in a thread-safe way, calls to methods that return random numbers return 0.
Смотрим на InternalSample (есть в статье).
Вангую, что из-за доступа из разных потоков к переменным inext и inextp может происходить рассинхронизация и расстояние между ними не всегда будет постоянным. Если так вдруг случилось, что inext и inextp совпали, то за 55 вызовов массив SeedArray весь обнулится. Далее все «случайные» числа будут высчитываться как 0 — 0.
Поскольку функция была не особо часто используемой, но нужной для инфраструктурной совместимости, родилось public static int GetHashCode11 (string str), и чтобы особо не париться, сделано это было через вызов StringGetHashCode11.exe.
И на всех серверах стоит .NET 1 для этого :)
Ужосы какие, наверное про изменение хеша в общем тоже кто-то где-то статью написал. А с рандомом вот решили не делать.
Что увидительно, и про GetHashCode, и про Random написано одинаково, что их реализация от платформы к платформе может отличаться.
Note that the example may produce different sequences of random numbers if run on different versions of the .NET Framework.
я просто с уважением отношусь к legacy коду, его к сожалению очень много накапливается за года, но если он хорошо работает, то часто лучше адаптироваться
я просто с уважением отношусь к legacy коду, его к сожалению очень много накапливается за года, но если он хорошо работает, то часто лучше адаптироваться
То есть если код нарушает спецификации, его все равно можно считать хорошо работающим? Просто интересно, как вы использовали GetHashCode, что смена его реализации для вас оказалась критичной.
Ну это очень странный случай поперек всех современных гайдлайнов, да, но когда это писалось, программирование так в целом по индустрии было несколько в другом состоянии, и у меня в частности тоже.
Вообще много таких примеров на самом деле. Зависит от того, дорог ли вам как память код 20-летней давности. Я не сторонник рефакторинга раз в 5 лет, если он и так отлично работает. До определенного предела конечно.
Но такие вот особо одаренные случаи как результат тоже неизбежны.
Переписывать это — трудозатраты часто совершенно не оправданы.
Это всё только взгляд с перспективы десятков лет, конечно. Так вот сев подумав, «да я всё перепишу», но когда кода реально много, иногда переписывать — это просто полная дурь.
Спасибо, интересно видеть, как на практике это можно взломать.
При использовании Random нужно не забывать о синхронизации доступа либо использовать ThreadStatic-экземпляры. При создании нескольких экземпляров, необходимо позаботиться о seed, чтобы не получить множество одинаково инициализированных объектов.
Не понимаю. Т.е. рекомендация такая. Делай один уникальный Random для каждого потока (ThreadStatic). Т.к. если один Random для многих потоков, то его легче предсказать. А как о seed заботиться? Количество тиков из DateTime по какому-нибудь модулю брать или как?
не раскрывать лишнюю информацию об окружении.
Плохой совет, на мой вкус. Security through obscurity же.
Хотя, как мне кажется, это вполне нормальная информация, которая может быть частью Public-api, и использоваться например для клиентской балансировки.
Секундочу, но ведь security through obscurity — не про то! Принцип не говорит, что нужно дать атакующему всю информацию об устройстве [криптографической] системы, кроме условного «закрытого ключа». Он говорит, что не нужно полагаться на неосведомлённость атакующего как на главную защитную меру. А как на дополнительную — конечно же, можно и нужно полагаться.
Управление рисками, в том числе безопасности, подчиняется экономическим законам. Если затраты на атаку превышают выгоду от неё, нарушитель трижды подумает. Особенно если за ним не стоит большое государство или корпорация с, условно, неограниченными ресурсами. Именно поэтому раскрытие лишней информации о системе вредно — снижаются затраты на атаку, возрастает её вероятность.
Но что же я такое говорю! Конечно же, нужно передавать в HTTP-заголовках все названия и версии используемых языков программирования, фреймворков, middleware и операционных систем, сделать доступной из браузера папку .git, закоммитить node_modules, опубликовать Dockerfile-ы, а лучше сразу выкладывать списки уязвимостей с cve.mitre.org, которые ещё не закрыты, чтобы атакующие не подумали, что от них что-то скрывают (:
А как на дополнительную — конечно же, можно и нужно полагаться.
1)
Меня, если честно, очень эта фраза цепляет. Давайте рассмотрим криптографическую систему с закрытым ключом. Эта система устойчива до тех пор, пока:
1) Не доказано, что P == NP — en.wikipedia.org/wiki/P_versus_NP_problem
2) Закрытый ключ не скомпрометирован.
3) Вычислительные мощности находятся на примерно таком же уровне. Например, никто не построил себе кластер из миллиарда машин, либо квантовые компьютеры не стали стабильными, или ещё что-то.
Вы гововрите: «можно скрывать информацию о системе, для того чтобы использовать это, как дополнительный уровень зищиты». Я не очень понимаю, что бы это могло значить. Ваша система уже секьюрна, пока выполняются эти 3 условия. Либо мы пытаемся играть в: «наша система не секьюрна, но сломать её экономически дорого, так как ни у кого нет доступа до кода из вне, и т.д.».
2)
Честно, я немного не понял про версии софта в заголовках, и публичные Dockerfile.
a) Если ваш сервис работает на Некотором Софте, и в этой версии Софта нашли уязвимость, ваша система может быть взломана, вопрос лишь времени (ну да, если наша позиция — не сделать секьюрную систему, а сделать дорого взламываемую систему — это ок).
b) Что секретного в ваших Dockerfile? Вы храните там Secrets? Ну, в этом случае вы не следуете общепринятым практикам, и вина на вас. Это как хранить пароли в базке.
В разговоре про системы из реального мира, которые реализуют эти модели, — неуместно. Потому что в реальном мире любое условие может быть нарушено и будет нарушено, если это экономически выгодно. Например, любой закрытый ключ, имеющий физическое представление (в виде байт на диске или клеток в мозге), может быть скомпрометирован, если имеющие к ключу доступ приобретут должную мотивацию.
Поэтому писать на сайте компании «наш сисадмин Вася живёт по такому-то адресу, у него больные родители, заурядная зарплата и грабительский процент по ипотеке» — можно, но неосмотрительно. Это упростит реализацию атаки по некоторым из возможных векторов.
Неслучайная случайность, или Атака на ГПСЧ в .NET