Предположим, что я беру пользовательскую предоставленную строку, userstring, и вызов (ключевое слово userstring) на нем.
Есть ли какие-либо проблемы безопасности о выполнении этого? И если так, каков был бы лучший способ смягчить их?
Согласно http://clojure.org/reader , существуют правила, по которым символы допустимы в символах и ключевых словах. (На данный момент буквенно-цифровые символы и *
, +
, !
, -
, _
и ]?
.) Никогда не создавайте символ, содержащий какие-либо другие символы. Однако сейчас эти правила полностью не соблюдаются компилятором.
В лучшем случае вы можете получить недействительные ключевые слова. В худшем случае вы можете получить злые / опасные, так как
- сказал Михал Марчик. Имейте в виду, что # = ()
можно использовать для запуска произвольного кода во время чтения, поэтому вам даже не нужно оценивать строку, чтобы не произошло плохое, вам нужно только ее прочитать.
(keyword "foo #=(steal-passwords-and-delete-hard-drive)")
(См. (doc * read-eval *)
, чтобы узнать, как отключить это поведение, но чтение-eval включено по умолчанию.)
Я думаю, что здесь применяются общие правила очистки пользовательского ввода. Точно определите, что вы хотите разрешить, и запретите все остальное по умолчанию. Возможно, разрешите что-то вроде регулярного выражения # "[a-zA-Z0-9 * +! -_?] +"
, возможно, с другими буквенно-цифровыми символами в зависимости от языка, на котором вы говорите.
Навскидку:
(ключевое слово s)
создаст ключевое слово без пробелов с именем s
независимо от того, может ли такое ключевое слово быть представлено литералом ключевого слова. Это может стать проблемой безопасности, если вы, скажем, выводите эти ключевые слова как часть какого-нибудь конфигурационного файла, а затем пытаетесь использовать его в качестве доверенного кода:
(with-out-str (println (keyword "foo (println :bar)")))
; => :foo (println :bar)
Также, вот две интересные темы из групп Google (первая - из clojure-dev):
Резюме: интернирование мусорных ключевых слов может привести к утечке памяти, поэтому следует рассмотреть возможность предварительной обработки строк, которые вы можете интернировать, если они приходят из недоверенных источников.