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
This commit is contained in:
parent
747bbd5f0c
commit
68b0ae7829
1 changed files with 13 additions and 1 deletions
|
@ -25,6 +25,7 @@ import Control.Monad.Trans.Except
|
||||||
import Control.Monad.Trans.Maybe
|
import Control.Monad.Trans.Maybe
|
||||||
import Crypto.Error (CryptoFailable (..))
|
import Crypto.Error (CryptoFailable (..))
|
||||||
import Crypto.PubKey.Ed25519 (PublicKey, publicKey, signature, verify)
|
import Crypto.PubKey.Ed25519 (PublicKey, publicKey, signature, verify)
|
||||||
|
import Data.Char
|
||||||
import Data.Either (isRight)
|
import Data.Either (isRight)
|
||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
import Data.Maybe (fromJust)
|
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 Data.HashMap.Strict as M (lookup, insert)
|
||||||
import qualified Yesod.Core.Unsafe as Unsafe
|
import qualified Yesod.Core.Unsafe as Unsafe
|
||||||
--import qualified Data.CaseInsensitive as CI
|
--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 qualified Data.Text.Encoding as TE
|
||||||
|
|
||||||
import Network.HTTP.Signature hiding (Algorithm (..))
|
import Network.HTTP.Signature hiding (Algorithm (..))
|
||||||
|
@ -621,6 +622,7 @@ instance YesodHttpSig App where
|
||||||
toSeconds = toTimeUnit
|
toSeconds = toTimeUnit
|
||||||
httpVerifySig (Verification malgo (KeyId keyid) input (Signature signature)) = fmap HttpSigVerResult $ runExceptT $ do
|
httpVerifySig (Verification malgo (KeyId keyid) input (Signature signature)) = fmap HttpSigVerResult $ runExceptT $ do
|
||||||
(host, luKey) <- f2l <$> parseKeyId keyid
|
(host, luKey) <- f2l <$> parseKeyId keyid
|
||||||
|
checkHost host
|
||||||
mluActorHeader <- getActorHeader host
|
mluActorHeader <- getActorHeader host
|
||||||
manager <- getsYesod appHttpManager
|
manager <- getsYesod appHttpManager
|
||||||
(inboxOrVkid, vkd) <- do
|
(inboxOrVkid, vkd) <- do
|
||||||
|
@ -702,6 +704,16 @@ instance YesodHttpSig App where
|
||||||
case parseFedURI =<< (first displayException . decodeUtf8') k of
|
case parseFedURI =<< (first displayException . decodeUtf8') k of
|
||||||
Left e -> throwE $ "keyId in Sig header isn't a valid FedURI: " ++ e
|
Left e -> throwE $ "keyId in Sig header isn't a valid FedURI: " ++ e
|
||||||
Right u -> return u
|
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
|
getActorHeader host = do
|
||||||
bs <- lookupHeaders hActivityPubActor
|
bs <- lookupHeaders hActivityPubActor
|
||||||
case bs of
|
case bs of
|
||||||
|
|
Loading…
Reference in a new issue