Skip to content

Commit

Permalink
Stop base64 encoding encryption keys. Copy rails for request forgery
Browse files Browse the repository at this point in the history
  • Loading branch information
swlkr committed Feb 12, 2020
1 parent d9a8462 commit 649d567
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 50 deletions.
2 changes: 1 addition & 1 deletion project.janet
Expand Up @@ -4,7 +4,7 @@
:dependencies [{:repo "https://github.com/janet-lang/json" :tag "fc59d46f06501569c21d18fff3df15e1494bf144"}
{:repo "https://github.com/janet-lang/sqlite3" :tag "a3a254003c605cf4e048963feda70a60537057d9"}
{:repo "https://github.com/janet-lang/path" :tag "d8619960d428c45ebb784600771a7c584ae49431"}
{:repo "https://github.com/joy-framework/cipher" :tag "87fc9bc38b335d0f31c93d6c95f35b8a6abce6af"}
{:repo "https://github.com/joy-framework/cipher" :tag "0.2.0"}
{:repo "https://github.com/joy-framework/codec" :tag "f50c00462b9d048034ee8bdd2f6af6e67bc5aff4"}
{:repo "https://github.com/joy-framework/halo" :tag "fd34201fee41b372314aede9e72044d711510afa"}
{:repo "https://github.com/andrewchambers/janet-uri" :tag "d191ed238dc7c4966f121f9f4c40b19cc75e34ee"}
Expand Down
2 changes: 1 addition & 1 deletion src/joy/cli/projects.janet
Expand Up @@ -24,6 +24,6 @@

(helper/with-file [f (path/join project-name ".env") :r]
(set tmp (->> (file/read f :all)
(string/replace-all "%encryption-key%" (-> (cipher/password-key) (codec/encode))))))
(string/replace-all "%encryption-key%" (cipher/encryption-key)))))
(helper/with-file [f (path/join project-name ".env") :w]
(file/write f tmp))))
5 changes: 3 additions & 2 deletions src/joy/form-helper.janet
@@ -1,4 +1,5 @@
(import ./router :as router)
(import ./middleware :as middleware)


(defn- field [kind val key & attrs]
Expand Down Expand Up @@ -79,8 +80,8 @@
action (apply router/action-for (drop 1 action-args))]
[:form action
body
(when (truthy? (request :csrf-token))
(hidden-field request :csrf-token))
(when (get request :csrf-token)
[:input {:type "hidden" :name "__csrf-token" :value (middleware/form-csrf-token request)}])
(when (truthy? (action :_method))
(hidden-field action :_method))]))

Expand Down
92 changes: 46 additions & 46 deletions src/joy/middleware.janet
Expand Up @@ -60,18 +60,15 @@
(http/cookie-string cookie-name cookie-value options)))))


(defn- deserialize-session [decrypted]
(when (and (not (nil? decrypted))
(not (empty? decrypted)))
(unmarshal decrypted)))
(defn- safe-unmarshal [val]
(unless (or (nil? val) (empty? val))
(unmarshal val)))


(defn- decrypt-session [key str]
(when (string? str)
(try
(as-> str ?
(base64/decode ?)
(cipher/decrypt key ?))
(cipher/decrypt key str)
([err]
(unless (= err "decryption failed")
(error err))))))
Expand All @@ -82,15 +79,14 @@
(truthy? key))
(as-> str ?
(decrypt-session key ?)
(deserialize-session ?))))
(safe-unmarshal ?))))


(defn- encode-session [val key]
(when (truthy? key)
(->> (marshal val)
(string)
(cipher/encrypt key)
(base64/encode))))
(cipher/encrypt key))))


(defn- session-from-request [key request]
Expand All @@ -101,67 +97,71 @@


(defn session [handler]
(let [key (base64/decode (env/env :encryption-key))]
(let [key (env/env :encryption-key)]
(fn [request]
(let [request-session (or (session-from-request key request)
@{})
response (handler (merge request request-session))
session-value (or (get response :session)
(get request-session :session))
session-id (or (get request-session :session-id)
(base64/encode (cipher/password-key)))]
(let [joy-session {:session session-value :session-id session-id :csrf-token (get response :csrf-token)}]
(get request-session :session))]
(let [joy-session {:session session-value :csrf-token (get response :csrf-token)}]
(when (truthy? response)
(put-in response [:headers "Set-Cookie"]
(http/cookie-string "id" (encode-session joy-session key)
{"SameSite" "Strict" "HttpOnly" "" "Path" "/"}))))))))


(defn session-id [request]
(when-let [id (get request :session-id)]
(base64/decode id)))
(defn xor-byte-strings [str1 str2]
(let [arr @[]
bytes1 (string/bytes str1)
bytes2 (string/bytes str2)]
(loop [i :range [0 32]]
(array/push arr (bxor (get bytes1 i) (get bytes2 i))))
(string/from-bytes ;arr)))


(defn decode-token [token session-id]
(when (truthy? token)
(try
(->> (base64/decode token)
(cipher/decrypt session-id))
([err]
(unless (= err "decryption failed")
(error err))))))
(defn mask-token [request]
(let [pad (os/cryptorand 32)
csrf-token (get request :csrf-token)
masked-token (xor-byte-strings pad csrf-token)]
(base64/encode (string pad masked-token))))


(defn session-csrf-token [request]
(or (get request :csrf-token)
(os/cryptorand 32)))


(defn form-csrf-token [request]
(decode-token (get-in request [:body :csrf-token])
(session-id request)))
(mask-token request))


(defn session-token [request]
(decode-token (get request :csrf-token)
(session-id request)))
(defn csrf-tokens-equal? [form-token session-token]
(cipher/secure-compare form-token session-token))


(defn new-csrf-token [session-id]
(when (truthy? session-id)
(->> (rand-str 20) (cipher/encrypt session-id) (base64/encode))))
(defn unmask-token [request]
(let [masked-token (get-in request [:body :__csrf-token])
_ (when (nil? masked-token)
(error "Required parameter __csrf-token not found"))
token (base64/decode masked-token)
pad (string/slice token 0 32)
csrf-token (string/slice token 32)]
(xor-byte-strings pad csrf-token)))


(defn csrf-token [handler]
(fn [request]
(let [session-id (session-id request)
new-csrf-token (new-csrf-token session-id)]
(let [session-token (session-csrf-token request)]
(if (or (head? request) (get? request))
(let [response (handler (put request :csrf-token new-csrf-token))]
(when (truthy? response)
(put response :csrf-token new-csrf-token)))
(let [session-token (session-token request)
form-csrf-token (form-csrf-token request)]
(if (= form-csrf-token session-token)
(let [response (handler request)]
(when (truthy? response)
(put response :csrf-token new-csrf-token)))
(responder/render :text "Invalid CSRF Token" :status 403)))))))
(when-let [response (handler request)]
(put response :csrf-token session-token))
(let [form-token (unmask-token request)]
(if (csrf-tokens-equal? form-token session-token)
(when-let [response (handler request)]
(put response :csrf-token session-token))
(-> (responder/render :text "Invalid CSRF Token" :status 403)
(put :csrf-token session-token))))))))


(defn x-headers [handler &opt options]
Expand Down

0 comments on commit 649d567

Please sign in to comment.