on master help sign in
Limit the maximum header line length to 8190 chars.
55d7cceHans-Christian Esperer
wai-extra/Network/Wai/Parse.hs+10−5
@@ -289,24 +289,29 @@ conduitRequestBodyEx o backend (Multipart bound) rbody add =
289 parsePiecesEx o backend (S8.pack "--" `S.append` bound) rbody add
289 parsePiecesEx o backend (S8.pack "--" `S.append` bound) rbody add
290
290
291
291
292+-- | Take one header or subheader line.
293+-- It makes sense to limit the maximum line length.
294+-- Apache's default is 8190 (http://httpd.apache.org/docs/2.2/mod/core.html#limitrequestline)
295+-- so we're using that here as well.
292takeLine :: Source -> IO (Maybe S.ByteString)
296takeLine :: Source -> IO (Maybe S.ByteString)
293takeLine src =
297takeLine src =
294− go id
298+ go ""
295 where
299 where
296 go front = do
300 go front = do
297 bs <- readSource src
301 bs <- readSource src
302+ when (S.length front + S.length bs > 8190) $ error "Header line length exceeds allowed maximum."
298 if S.null bs
303 if S.null bs
299 then close front
304 then close front
300 else push front bs
305 else push front bs
301
306
302− close front = leftover src (front S.empty) >> return Nothing
307+ close front = leftover src front >> return Nothing
303 push front bs = do
308 push front bs = do
304− let (x, y) = S.break (== 10) $ front bs -- LF
309+ let (x, y) = S.break (== 10) bs -- LF
305 in if S.null y
310 in if S.null y
306− then go $ S.append x
311+ then go $ front `S.append` x
307 else do
312 else do
308 when (S.length y > 1) $ leftover src $ S.drop 1 y
313 when (S.length y > 1) $ leftover src $ S.drop 1 y
309− return $ Just $ killCR x
314+ return $ Just $ killCR $ front `S.append` x
310
315
311takeLines :: Source -> IO [S.ByteString]
316takeLines :: Source -> IO [S.ByteString]
312takeLines src = do
317takeLines src = do
wai-extra/test/Network/Wai/ParseSpec.hs+14
@@ -131,6 +131,10 @@ caseParseRequestBody = do
131 SRequest req4 bod4 <- toRequest'' ctype2 content2
131 SRequest req4 bod4 <- toRequest'' ctype2 content2
132 (parseRequestBodyEx (def { prboMaxHeaderLines = 1 } ) lbsBackEnd req4) `shouldThrow` anyErrorCall
132 (parseRequestBodyEx (def { prboMaxHeaderLines = 1 } ) lbsBackEnd req4) `shouldThrow` anyErrorCall
133
133
134+ it "exceeding header line size" $ do
135+ SRequest req4 bod4 <- toRequest'' ctype2 content4
136+ (parseRequestBodyEx def lbsBackEnd req4) `shouldThrow` anyErrorCall
137+
134 where
138 where
135 content2 =
139 content2 =
136 "--AaB03x\n"
140 "--AaB03x\n"
@@ -154,6 +158,16 @@ caseParseRequestBody = do
154 <> "Content-Type: application/octet-stream\r\n\r\n"
158 <> "Content-Type: application/octet-stream\r\n\r\n"
155 <> "Photo blog using Hack.\n\r\n"
159 <> "Photo blog using Hack.\n\r\n"
156 <> "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh--\r\n"
160 <> "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh--\r\n"
161+ content4 =
162+ "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh\r\n"
163+ <> "Content-Disposition: form-data; name=\"yaml\"; filename=\"README\"\r\n"
164+ <> "Content-Type: application/octet-stream\r\n\r\n"
165+ <> "Photo blog using Hack.\n\r\n"
166+ <> "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh\r\n"
167+ <> "Content-Disposition: form-data; name=\"bla\"; filename=\"riedmie\"\r\n"
168+ <> "Content-Type: application/octet-stream=TOOLONG=" <> S8.replicate 8192 '=' <> "\r\n\r\n"
169+ <> "Photo blog using Hack.\n\r\n"
170+ <> "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh--\r\n"
157
171
158caseMultipartPlus :: Assertion
172caseMultipartPlus :: Assertion
159caseMultipartPlus = do
173caseMultipartPlus = do