Skip to content

Instantly share code, notes, and snippets.

@jokimaki
Created April 19, 2014 15:37
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jokimaki/11087906 to your computer and use it in GitHub Desktop.
Save jokimaki/11087906 to your computer and use it in GitHub Desktop.
(defproject parser-vuln-test "1.0" :dependencies [[org.clojure/clojure "1.6.0"]])
(ns vuln-test
(:require [clojure.xml :as xml]
[clojure.string :as s]
[clojure.test :refer :all]))
;; See https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing
(spit "target/xxe-attack.xml" "<?xml version=\"1.0\"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM \"../project.clj\" >]>
<foo>&xxe;</foo>")
;; See http://msdn.microsoft.com/en-us/magazine/ee335713.aspx
;; Processed XML will expand to 100 fold. Increase these values to blow up your JVM.
(def ent-times 100)
(def ent-len 64000)
(def bomb-yield (* ent-len ent-times))
(spit "target/bomb.xml" (str "<?xml version=\"1.0\"?>
<!DOCTYPE foo [ <!ENTITY a \"" (s/join (repeat ent-len "a")) "\">]>
<foo>" (s/join (repeat ent-times "&a;")) "</foo>"))
(deftest default-impl
(testing "clojure.xml/parse default implementation is vulnerable to XXE attacks"
(is (.startsWith
(-> (xml/parse "target/xxe-attack.xml") xml/content first)
"(defproject")))
(testing "clojure.xml/parse default implementation is vulnerable to XML bombs"
(is (=
(-> (xml/parse "target/bomb.xml") xml/content first)
(s/join (repeat bomb-yield"a"))))))
;; Luckily, mitigation is easy
;; Safer version of clojure.xml/startparse-sax
(defn startparse-sax-no-doctype [s ch]
(..
(doto (javax.xml.parsers.SAXParserFactory/newInstance)
(.setFeature javax.xml.XMLConstants/FEATURE_SECURE_PROCESSING true)
(.setFeature "http://apache.org/xml/features/disallow-doctype-decl" true))
(newSAXParser)
(parse s ch)))
(deftest disallow-doctype-decl
(testing "Disallowing DOCTYPE declaration disables external entity processing"
(is (thrown-with-msg? org.xml.sax.SAXParseException #"DOCTYPE is disallowed"
(xml/parse "target/xxe-attack.xml" startparse-sax-no-doctype))))
(testing "Disallowing DOCTYPE declaration defuses XML bombs"
(is (thrown-with-msg? org.xml.sax.SAXParseException #"DOCTYPE is disallowed"
(xml/parse "target/bomb.xml" startparse-sax-no-doctype)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment