lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

I've been working on a simple HTTP server using LuaSocket. I wanted to
defend against "fuzzing" attacks, where an attacker sends endless
streams of junk (often at very slow rates) as HTTP headers, never
ending the line or request header, thus tying up the server's
resources as it sits endlessly waiting for/buffering header strings
for a request that never completes.

For example, an attacker might send an endless request line:
sock:send('GET /'); while true do sock:send('x') end
or a request with some endless header line:
sock:send('GET / HTTP/1.0\r\nX-Endless-String: '); while true do
sock:send('x') end

The obvious way to defend against this attack would be to reject the
request and close the connection if any line is too long.
Unfortunately LuaSocket doesn't appear to provide any way to do this,
other than (slowly!) reading one byte at a time. It provides only
three receive options:
1) Read until connection is closed (or timeout). Not useful for HTTP,
since the connection needs to remain open to send the response.
2) Read until an end-of-line character. Not helpful in this scenario,
since the line never ends.
3) Read a specified number of bytes.

Option 3 seems like the answer, but there's no way to read *up to* a
certain number of bytes. If I specify 32, and the client only sends
16, the read will block forever or time out (and will *not* return
those 16 bytes). So, the server would have to read one byte at a time,
or else fail to accept legitimate requests. Of course this is terrible
for performance.

To properly defend against this attack, the server needs to be able to either:
1) Peek into the receive buffer, and don't actually read the data
(removing it from the buffer) until a line break appears, rejecting
the connection if too much data is buffered without a line break, or:
2) Read all data received in the next x seconds or the next n bytes,
whichever comes first. (Bonus if "or until the next line break" is
also an option.) The server can then buffer lines in the same manner
as option 1.

Unfortunately, LuaSocket doesn't seem to offer methods to do either of
these, thus leaving every server using it vulnerable to such attacks.

Sent from my toaster.