Escape/sanitize ввод пользователя в Clojure/Compojure

Я использую Clojure/Ring/Compojure-0.4/Enlive stack для создания веб-приложения.

Существуют ли функции в этом стеке, которые будут либо помещать строки HTML или HTML-кодировки (то есть <a> в &lt;a&gt;), предоставленные пользователем, чтобы предотвратить атаки XSS?

Ответы

Ответ 1

Оказывается, Enlive действительно удаляет HTML по умолчанию, если вы используете net.cgrand.enlive-html/content для размещения текста в HTML-элементе.

(sniptest "<p class=\"c\"></p>" [:.c] (content "<script></script>"))
"<p class=\"c\">&lt;script&gt;&lt;/script&gt;</p>"

Ответ 2

hiccup.util/escape-html в hiccup. Эта функция использовалась в самой Compojure (поскольку все функции в hiccup были частью Compojure). Это достаточно простая функция, которую вы могли бы легко написать сами, хотя.

(defn escape-html
  "Change special characters into HTML character entities."
  [text]
  (.. #^String (as-str text)
    (replace "&" "&amp;")
    (replace "<" "&lt;")
    (replace ">" "&gt;")
    (replace "\"" "&quot;")))

Здесь также clojure.contrib.string/escape, который берет отображение строк и строки и избегает его для вас.

user> (clojure.contrib.string/escape {\< "&lt;" \> "&gt;"} "<div>foo</div>")
"&lt;div&gt;foo&lt;/div&gt;"

Мне кажется, что это не так полезно, как могло бы быть, потому что вам может понадобиться избежать многосимвольных последовательностей, и это не позволит вам. Но это может сработать для ваших потребностей в HTML-экранах.

И, конечно, для этого есть много библиотек Java. Вы можете использовать StringEscapeUtils от Apache Commons:

(org.apache.commons.lang.StringEscapeUtils/escapeHtml4 some-string)

Это поражает меня как немного тяжеловеса для этой цели, хотя.

Ответ 3

Обновление: я знал, что должно быть больше...

ring.util.codec из ring-core имеет функции, которые работают так:

user> (require '[ring.util.codec :as c])
nil
user> (c/url-encode "<a>")
"%3Ca%3E"
user> (c/url-decode "<a>")
"<a>"

Это обертки вокруг java.net.URLEncoder и java.net.URLDecoder. Такое же пространство имен предоставляет функции для обработки кодировки Base64, основанные на классе от Apache Commons.


Далее следует исходный ответ.

Я не уверен, есть ли для этого публичная функция, но Enlive имеет две частные функции, называемые xml-str и attr-str, которые делают это:

(defn- xml-str
 "Like clojure.core/str but escapes < > and &."
 [x]
  (-> x str (.replace "&" "&amp;") (.replace "<" "&lt;") (.replace ">" "&gt;")))

(attr-str также выходит из ".)

Вы можете получить эту функцию с помощью @#'net.cgrand.enlive-html/xml-str (Clojure не имеет тенденций делать вещи действительно закрытыми...) или просто скопировать ее в собственное пространство имен.