lua-users home
lua-l archive

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


On Tue, Oct 11, 2011 at 12:37 AM, HyperHacker <hyperhacker@gmail.com> wrote:
> To properly defend against this attack, the server needs to be able to either:
...
> 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.

If you :settimeout(t>0), then call receive(n/"*l"), and the timeout
occurs before n bytes/a line
has been read, you should get

  nil, "timeout", partial

as the result.

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

I think luasocket provides the required functionality, though you
might not be able to take advantage
of some of its high-level buffering.

If you can reliably reproduce it not behaving as documented or
describe why it is impossible to use, I might have time to fix it (I'm
collecting patches at https://github.com/sam-github/luasocket).

luasocket's buffering is convenient, but not necessarily what you want
for a server. And a multiplexing
server will need to set the timeouts to 0 on all sockets, and to use select().

If you do that, you will need to buffer the data yourself, and
evaluate your conditions for determining when a peer is misbehaving.
You'll have to track time associated with each connection, and buffer
the data for each connection yourself.

Apache, as I recall, has  a short timeout in which it requires seeing
some data, then a longer one to recv the complete head of the request.

Your buffering scheme can use the prefix argument to :receive(), if it
wishes, or use a table as a queue of segments, and concat them with
table.concat().

You might find the code below useful to explore some of these
behaviours, though it doesn't multiplex using select. As a start, try
calling it like:

./read-safely 4567 "*l" 4

with a client:

(sleep 10; echo -n helo; sleep 10; echo bye; sleep 10) | nc localhost 4567

Cheers,
Sam

------ read-safely -----
#!/usr/bin/env lua

require"socket"

if arg[1] == "-h" then
    print("usage: "..arg[0].." port pattern timeout")
    os.exit(1)
end

port = tonumber(arg[1]) or 0
pattern = arg[2] or 1024
timeout = arg[3] or 10

print("port", port, "pattern", pattern, "timeout", timeout)

serv = assert(socket.tcp())
assert(serv:setoption("reuseaddr", true))
assert(serv:bind("*", port))
assert(serv:listen())

print("at", serv:getsockname())

sock = assert(serv:accept())

print("from", sock:getpeername())

assert(sock:settimeout(timeout))

while true do
    mesg, emsg, part = sock:receive(pattern)

    if emsg then print("error", emsg) end

    assert(mesg or emsg == "timeout", emsg)

    if mesg then
        print("recv mesg", #mesg, "<"..mesg..">")
    elseif #part > 0 then
        print("recv part", #part, "<"..part..">")
    end
end