Skip to content

Commit

Permalink
adds sql injection protection
Browse files Browse the repository at this point in the history
  • Loading branch information
mylesmegyesi committed Sep 15, 2012
1 parent 01316cd commit 7435ca1
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 9 deletions.
17 changes: 16 additions & 1 deletion mysql/spec/hyperion/mysql_spec.clj
Expand Up @@ -2,7 +2,7 @@
(:use [speclj.core]
[hyperion.sql.spec-helper]
[hyperion.dev.spec :only [it-behaves-like-a-datastore]]
[hyperion.api :only [*ds* new-datastore]]
[hyperion.api :only [*ds* new-datastore save find-by-key]]
[hyperion.sql.jdbc :only [execute-mutation]]
[hyperion.sql.query]
[hyperion.mysql :only [new-mysql-datastore]]))
Expand Down Expand Up @@ -57,5 +57,20 @@

(it-behaves-like-a-datastore)

(context "SQL Injection"
(it "sanitizes strings to be inserted"
(let [evil-string "my evil string' --"
record (save {:kind :testing :name evil-string})]
(should= evil-string (:name (find-by-key (:key record))))))

(it "sanitizes table names"
(error-msg-contains?
"Table 'hyperion.my_evil_name`___' doesn't exist"
(save {:kind "my-evil-name` --" :name "test"})))

(it "sanitizes column names"
(error-msg-contains?
"Unknown column 'my_evil_name`___' in 'field list'"
(save {:kind :testing (keyword "my-evil-name` --") "test"}))))
)
)
29 changes: 24 additions & 5 deletions postgres/spec/hyperion/postgres_spec.clj
Expand Up @@ -2,11 +2,12 @@
(:use [speclj.core]
[hyperion.sql.spec-helper]
[hyperion.dev.spec :only [it-behaves-like-a-datastore]]
[hyperion.api :only [*ds*]]
[hyperion.api :only [*ds* save find-by-key]]
[hyperion.sql.jdbc :only [execute-mutation]]
[hyperion.sql.connection :only [connection]]
[hyperion.sql.query]
[hyperion.postgres :only [new-postgres-datastore]]))
[hyperion.postgres :only [new-postgres-datastore]])
(:import [speclj SpecFailure]))

(def create-table-query
"CREATE TABLE %s (
Expand All @@ -21,25 +22,27 @@
(execute-mutation
(make-query (format create-table-query table-name))))

(def connection-url "jdbc:postgresql://localhost:5432/hyperion")

(describe "Postgres Datastore"

(context "creation"

(it "with a string as the only param"
(let [ds (new-postgres-datastore "jdbc:postgresql://localhost:5432/hyperion")]
(let [ds (new-postgres-datastore connection-url)]
(should= false (.isClosed (.connection ds)))
(.close (.connection ds))))

(it "with a kv pairs as params"
(let [ds (new-postgres-datastore :connection-url "jdbc:postgresql://localhost:5432/hyperion")]
(let [ds (new-postgres-datastore :connection-url connection-url)]
(should= false (.isClosed (.connection ds)))
(.close (.connection ds))))

)

(context "live"

(with-connection-and-rollback "jdbc:postgresql://localhost:5432/hyperion")
(with-rollback connection-url)

(around [it]
(create-table "testing")
Expand All @@ -48,5 +51,21 @@
(it)))

(it-behaves-like-a-datastore)

(context "SQL Injection"
(it "sanitizes strings to be inserted"
(let [evil-string "my evil string' --"
record (save {:kind :testing :name evil-string})]
(should= evil-string (:name (find-by-key (:key record))))))

(it "sanitizes table names"
(error-msg-contains?
"relation \"my_evil_name\"___\" does not exist"
(save {:kind "my-evil-name\" --" :name "test"})))

(it "sanitizes column names"
(error-msg-contains?
"column \"my_evil_name\"___\" of relation \"testing\" does not exist"
(save {:kind :testing (keyword "my-evil-name\" --") "test"}))))
)
)
4 changes: 2 additions & 2 deletions sql/src/hyperion/sql/format.clj
@@ -1,10 +1,10 @@
(ns hyperion.sql.format
(:use [chee.string :only [snake-case spear-case]]
(:use [chee.string :only [snake-case spear-case gsub]]
[hyperion.sql.key :only [compose-key decompose-key]])
(:require [clojure.string :as str]))

(defn- add-quotes [s quote]
(str quote s quote))
(str quote (.replaceAll s quote (str quote quote)) quote))

(defprotocol FormattableForDatabase
(table->db [this quote])
Expand Down
25 changes: 24 additions & 1 deletion sql/src/hyperion/sql/spec_helper.clj
Expand Up @@ -2,7 +2,30 @@
(:use
[speclj.core]
[hyperion.sql.connection :only [with-connection-url]]
[hyperion.sql.jdbc :only [rollback]]))
[hyperion.sql.jdbc :only [rollback]])
(:import [speclj SpecFailure]))

(defn str-contains? [s sub]
(not= -1 (.indexOf s sub)))

(defmacro error-msg-contains? [msg form]
`(try
~form
(throw (SpecFailure. (str "Expected and exception with a message containing " ~msg " but no exception was thrown")))
(catch Exception e#
(let [message# (.getMessage e#)]
(cond
(.isInstance SpecFailure e#)
(throw e#)
(not (str-contains? (.getMessage e#) ~msg))
(throw (SpecFailure. (str "Expected and exception with a message containing \"" ~msg "\" but got: \"" message# "\"")))
:else e#)))))

(defn with-rollback [url]
(around [it]
(with-connection-url url
(rollback
(it)))))

(defn with-connection-and-rollback [url]
(around [it]
Expand Down

0 comments on commit 7435ca1

Please sign in to comment.