Ignore messages with too high clock-value and prevent stored messages to pollute the database

Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrea Maria Piana 2018-10-09 08:41:16 +02:00
parent 17053019e3
commit 84151ea996
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
5 changed files with 28 additions and 11 deletions

View File

@ -3,6 +3,7 @@
[cljs.core.async :as async]
[re-frame.core :as re-frame]
[status-im.utils.ethereum.core :as utils.ethereum]
[status-im.utils.clocks :as utils.clocks]
[status-im.data-store.realm.core :as core]))
(defn remove-empty-vals
@ -49,15 +50,16 @@
:message :chat-id chat-id)
(core/sorted :clock-value :desc)
(core/single-clj :message)
:clock-value))
:clock-value
(utils.clocks/safe-timestamp)))
(defn- normalize-chat [{:keys [chat-id] :as chat}]
(let [last-clock-value (get-last-clock-value chat-id)]
(-> chat
(update :admins #(into #{} %))
(update :contacts #(into #{} %))
(update :membership-updates (partial unmarshal-membership-updates chat-id))
(assoc :last-clock-value (or last-clock-value 0)))))
(-> chat
(update :admins #(into #{} %))
(update :contacts #(into #{} %))
(update :membership-updates (partial unmarshal-membership-updates chat-id))
;; We cap the clock value to a safe value in case the db has been polluted
(assoc :last-clock-value (get-last-clock-value chat-id))))
(re-frame/reg-cofx
:data-store/all-chats

View File

@ -3,6 +3,7 @@
(:require-macros [status-im.utils.db :refer [allowed-keys]])
(:require [cljs.spec.alpha :as spec]
status-im.ui.screens.contacts.db
[status-im.utils.clocks :as utils.clocks]
[clojure.string :as s]))
;; required
@ -60,7 +61,8 @@
(spec/def ::content-type #{"text/plain" "command" "command-request"})
(spec/def ::message-type #{:group-user-message :public-group-user-message :user-message})
(spec/def ::clock-value (spec/nilable pos-int?))
(spec/def ::clock-value (spec/and pos-int?
utils.clocks/safe-timestamp?))
(spec/def ::timestamp (spec/nilable pos-int?))
(spec/def :message/id string?)

View File

@ -5,6 +5,7 @@
[taoensso.timbre :as log]
[status-im.utils.config :as config]
[status-im.chat.core :as chat]
[status-im.utils.clocks :as utils.clocks]
[status-im.transport.db :as transport.db]
[status-im.transport.message.core :as message]
[status-im.transport.message.v1.core :as transport]
@ -110,8 +111,9 @@
:from signature
:js-obj (:js-obj cofx))]})
(validate [this]
(when (spec/valid? :message/message this)
this)))
(if (spec/valid? :message/message this)
this
(log/warn "failed to validate Message" (spec/explain :message/message this)))))
(defrecord MessagesSeen [message-ids]
message/StatusMessage

View File

@ -75,6 +75,8 @@
(defn- ->timestamp-bid []
(* (utils.datetime/timestamp) post-id-digits))
(defn max-timestamp []
(* (+ one-month-in-ms (utils.datetime/timestamp)) post-id-digits))
; The timestamp has an upper limit of Number.MAX_SAFE_INTEGER
; A malicious client could send a crafted message with timestamp = Number.MAX_SAFE_INTEGER
; which effectively would DoS the chat, as any new message would get
@ -83,7 +85,10 @@
; then now + 20s.
; We cap the timestamp to time now + 1 month to give some room for trusted peers
(defn- safe-timestamp [t]
(min t (* (+ one-month-in-ms (utils.datetime/timestamp)) post-id-digits)))
(min t (max-timestamp)))
(defn safe-timestamp? [t]
(<= t (max-timestamp)))
(defn send [local-clock]
(inc (max local-clock (->timestamp-bid))))

View File

@ -92,6 +92,12 @@
(is (< (clocks/receive js/Number.MAX_SAFE_INTEGER 0)
js/Number.MAX_SAFE_INTEGER))))
(deftest safe-timestamp?-test
(testing "it returns false for a high number"
(is (not (clocks/safe-timestamp? js/Number.MAX_SAFE_INTEGER))))
(testing "it returns true for a normal timestamp number"
(is (clocks/safe-timestamp? (clocks/send 0)))))
;; Debugging
;;(println "******************************************")
;;(println "A's POV :foo" (format-thread (thread a :foo)))