on master help sign in
preventing response splitting attack.
commitfe519c69a03d2798c72852b634f0c3f070ec2ca1 authorKazu Yamamoto <kazu@iij.ad.jp> dateTue 15 Sep 2015, 16:16 (11 years ago) parent2164105
2 files changed+29−1
warp/Network/Wai/Handler/Warp/Response.hs+20−1 warp/test/ResponseSpec.hs+9
warp/Network/Wai/Handler/Warp/Response.hs+20−1
@@ -143,7 +143,26 @@ sendResponse :: ByteString -- ^ default server value
143143 -> IO ByteString -- ^ source from client, for raw response
144144 -> Response -- ^ HTTP response including status code and response header.
145145 -> IO Bool -- ^ Returing True if the connection is persistent.
146−sendResponse defServer conn ii req reqidxhdr src response = do
146+sendResponse defServer conn ii req reqidxhdr src response =
147+ sendResponse' defServer conn ii req reqidxhdr src response'
148+ where
149+ doesContainCRLF :: [ByteString] -> Bool
150+ doesContainCRLF = or . map (S.any (\w -> w == 10 || w == 13))
151+ hsv = map snd $ responseHeaders response
152+ response'
153+ | doesContainCRLF hsv = response400
154+ | otherwise = response
155+ response400 = responseLBS H.badRequest400 [(H.hContentType, "text/plain; charset=utf-8")] "Bad Request"
156+
157+sendResponse' :: ByteString -- ^ default server value
158+ -> Connection
159+ -> InternalInfo
160+ -> Request -- ^ HTTP request.
161+ -> IndexedHeader -- ^ Indexed header of HTTP request.
162+ -> IO ByteString -- ^ source from client, for raw response
163+ -> Response -- ^ HTTP response including status code and response header.
164+ -> IO Bool -- ^ Returing True if the connection is persistent.
165+sendResponse' defServer conn ii req reqidxhdr src response = do
147166 hs <- addServerAndDate hs0
148167 if hasBody s then do
149168 -- HEAD comes here even if it does not have body.
warp/test/ResponseSpec.hs+9
@@ -14,6 +14,8 @@ import RunSpec (withApp)
1414import System.IO (hClose, hFlush)
1515import Test.Hspec
1616
17+import HTTP
18+
1719main :: IO ()
1820main = hspec spec
1921
@@ -82,6 +84,13 @@ testFileRange desc s rsphdr file mPart mRange ans = it desc $ do
8284
8385spec :: Spec
8486spec = do
87+ describe "preventing response splitting attack" $ do
88+ it "returns 400 if reponse headers contain illegal characters" $ do
89+ let app _ f = f $ responseLBS status200 [("content-length", "20"),("foo", "foo\r\n\r\nbar\r\n")] "Hello"
90+ withApp defaultSettings app $ \port -> do
91+ res <- sendGET $ "http://127.0.0.1:" ++ show port
92+ rspCode res `shouldBe` (4,0,0)
93+
8594 describe "range requests" $ do
8695 testRange "2-3" "23" $ Just "2-3/16"
8796 testRange "5-" "56789abcdef" $ Just "5-15/16"