From 68b0ae78299173479c48355a961bd06769a0b18a Mon Sep 17 00:00:00 2001 From: fr33domlover Date: Wed, 20 Mar 2019 12:27:40 +0000 Subject: [PATCH] When receiving HTTP signed request, check the keyId host for weird cases - Exclude hosts without periods, so things like localhost and IPv6 are rejected - Exclude hosts without letters, so things like IPv4 are rejected - Exclude the instance's own host, just in case somehow some fake activity slips in and gets approved, maybe even accidentally when delivered by another server --- src/Vervis/Foundation.hs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Vervis/Foundation.hs b/src/Vervis/Foundation.hs index 8632886..452869b 100644 --- a/src/Vervis/Foundation.hs +++ b/src/Vervis/Foundation.hs @@ -25,6 +25,7 @@ import Control.Monad.Trans.Except import Control.Monad.Trans.Maybe import Crypto.Error (CryptoFailable (..)) import Crypto.PubKey.Ed25519 (PublicKey, publicKey, signature, verify) +import Data.Char import Data.Either (isRight) import Data.HashMap.Strict (HashMap) import Data.Maybe (fromJust) @@ -52,7 +53,7 @@ import qualified Data.ByteString.Lazy as BL (ByteString) import qualified Data.HashMap.Strict as M (lookup, insert) import qualified Yesod.Core.Unsafe as Unsafe --import qualified Data.CaseInsensitive as CI -import Data.Text as T (pack, intercalate, concat) +import qualified Data.Text as T --import qualified Data.Text.Encoding as TE import Network.HTTP.Signature hiding (Algorithm (..)) @@ -621,6 +622,7 @@ instance YesodHttpSig App where toSeconds = toTimeUnit httpVerifySig (Verification malgo (KeyId keyid) input (Signature signature)) = fmap HttpSigVerResult $ runExceptT $ do (host, luKey) <- f2l <$> parseKeyId keyid + checkHost host mluActorHeader <- getActorHeader host manager <- getsYesod appHttpManager (inboxOrVkid, vkd) <- do @@ -702,6 +704,16 @@ instance YesodHttpSig App where case parseFedURI =<< (first displayException . decodeUtf8') k of Left e -> throwE $ "keyId in Sig header isn't a valid FedURI: " ++ e Right u -> return u + checkHost h = do + unless (T.any (== '.') h) $ + throwE "Host doesn't contain periods" + unless (T.any isAsciiLetter h) $ + throwE "Host doesn't contain ASCII letters" + home <- getsYesod $ appInstanceHost . appSettings + when (h == home) $ + throwE "Received HTTP signed request from the instance's host" + where + isAsciiLetter c = isAsciiLower c || isAsciiUpper c getActorHeader host = do bs <- lookupHeaders hActivityPubActor case bs of