views:

55

answers:

2

I'm coding a tool, that, given any URL, would periodically fetch its output. The problem is that an output could be not a simple and lightweight HTML page (expected in most cases), but some heavy data stream (i.e. straight from /dev/urandom, possible DoS attack).

I'm using java.net.URL + java.net.URLConnection, setting connection and read timeouts to 30sec. Currently input is being read by java.io.BufferedReader, using readLine().

Possible solutions:

  1. Use java.io.BufferedReader.read() byte by byte, counting them and closing connection after limit has been reached. The problem is that an attacker may transmit one byte every 29sec, so that read/connection timeout would almost never occur (204800B * 29sec = 68 days)
  2. Limit Thread execution to 1-5min and use java.io.BufferedReader.readLine(). Any problems here?

I feel like trying to reinvent the wheel and the solution is very straightforward, just doesn't come to my mind.

Thanks in advance.

A: 

There seems to be a number of avenues for denial of service here.

A huge big line that gobbles memory. Probably the easiest is to use a MeteredInputStream before even hitting the character decoding. Reading char by char will be extremely slow in any circumstance. You could read a long char[] at a time, but that will likely over complicate the code.

Dealing with an adversary (or bug) keeping many connections alive at once. You probably want non-blocking I/O reading the whole message, and then proceed normally.

Tom Hawtin - tackline
+1  A: 

You could encapsulatebhhis by writing yourself a FilterInputStream that enforces whatever you want to enforce and placing it at the bottom of the stack, around the connection output stream

However this and the remedies you suggest only work if the output is arriving in chunked transfer mode. Otherwise HttpURLConnection can buffer the entire response before you read any of it. The usual solution to this is a filter in the firewall.

EJP
Wrote LimitedInputStream extending FilterInputStream with overriden read() methods, which return -1 (fake input stream end) when limit has been reached. Thanks!
ljank