Serializable: add read-quarantined-serializable-object-unsafe! util

This commit is contained in:
Peter Taoussanis 2020-09-10 13:47:23 +02:00
parent db2c22eed8
commit 057e2f1cd1
2 changed files with 41 additions and 10 deletions

View file

@ -321,7 +321,9 @@
If `thaw` encounters an unwhitelisted Serialized class: If `thaw` encounters an unwhitelisted Serialized class:
- `thaw` will throw if it's not possible to safely quarantine. - `thaw` will throw if it's not possible to safely quarantine.
- Otherwise the object will be thawed as: - Otherwise the object will be thawed as:
`{:nippy/unthawable {:class-name _ :content <quarantined-ba> ...}}`. `{:nippy/unthawable {:class-name <> :content <quarantined-ba> ...}}`.
- Objects thus quarantined may be manually unquarantined with
`read-quarantined-serializable-object-unsafe!`.
This is a security measure to prevent Remote Code Execution (RCE). This is a security measure to prevent Remote Code Execution (RCE).
@ -1381,6 +1383,27 @@
:content nil :content nil
:exception e}}))) :exception e}})))
(defn read-quarantined-serializable-object-unsafe!
"Given a quarantined Serializable object like
{:nippy/unthawable {:class-name <> :content <quarantined-ba>}}, reads and
returns the object WITHOUT regard for `*serializable-whitelist*`.
**MAY BE UNSAFE!** Don't call this unless you absolutely trust the payload
to not contain any malicious code.
See `*serializable-whitelist*` for more info."
[m]
(when-let [m (get m :nippy/unthawable)]
(let [{:keys [class-name content]} m]
(when (and class-name content)
(read-object
(DataInputStream. (ByteArrayInputStream. content))
class-name)))))
(comment
(read-quarantined-serializable-object-unsafe!
(thaw (freeze (java.util.concurrent.Semaphore. 1)))))
(defn- read-serializable-q (defn- read-serializable-q
"Quarantined => object serialized to ba, then ba written to output stream. "Quarantined => object serialized to ba, then ba written to output stream.
Has length prefix => can skip `readObject` in event of whitelist failure." Has length prefix => can skip `readObject` in event of whitelist failure."

View file

@ -276,16 +276,24 @@
"Can freeze and thaw Serializable object if approved by whitelist") "Can freeze and thaw Serializable object if approved by whitelist")
(is (let [sem (java.util.concurrent.Semaphore. 1)
(= :quarantined ba (nippy/freeze sem #_{:serializable-whitelist "*"})
(get-in thawed (nippy/thaw ba {:serializable-whitelist #{}})]
(nippy/thaw
(nippy/freeze (java.util.concurrent.Semaphore. 1)
#_{:serializable-whitelist "*"})
{:serializable-whitelist #{}})
[:nippy/unthawable :cause]))
"Thaw will quarantine Serializable objects approved when freezing.") (is
(= :quarantined (get-in thawed [:nippy/unthawable :cause]))
"Serializable objects will be quarantined when approved for freezing but not thawing.")
(is
(instance? java.util.concurrent.Semaphore
(nippy/read-quarantined-serializable-object-unsafe! thawed))
"Quarantined Serializable objects may still be manually force-read.")
(is
(instance? java.util.concurrent.Semaphore
(nippy/read-quarantined-serializable-object-unsafe!
(nippy/thaw (nippy/freeze thawed))))
"Quarantined Serializable objects are themselves safely transportable."))
(is (is
(instance? java.util.concurrent.Semaphore (instance? java.util.concurrent.Semaphore