From: Dominique Brezinski Date: 2005-03-05T13:29:45+09:00 Subject: Patch for denial of service vulnerability in WEBrick We built a service using WEBrick with SSL enabled, and in the process of testing found a denial of service vulnerability in WEBrick. If connections are terminated during the SSL handsake, an exception is raised that is not properly handled in webrick/server.rb. The result is that there is a leak in the token queue used to limit the number of threads created to handle connections. When the queue leaked to empty, the server sits in the IO::select loop trying to pop a token from the queue, but won't block because there is only the single thread running. The server becomes unavailable, and it creates a nice big log file too (500MB in a minute or two) ;> Here is a patch for 1.8.2 that fixes this and a related leak: *** server.rb.old Sat Mar 5 03:46:33 2005 --- server.rb Sat Mar 5 03:52:12 2005 *************** *** 99,110 **** --- 99,116 ---- rescue Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPROTO => ex # TCP connection was established but RST segment was sent # from peer before calling TCPServer#accept. + # This could cause a leak in the token queue since a token + # was popped between the select and accept, so we push one + @tokens.push(nil) rescue Errno::EBADF, IOError => ex # if the listening socket was closed in GenericServer#shutdown, # IO::select raise it. rescue Exception => ex + # if using SSL, a failed accept will raise an exception that is + # caught here, so we need to push a token to avoid a leak msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" @logger.error msg + @tokens.push(nil) end end *************** *** 168,175 **** @logger.debug "close:
" end sock.close end - @tokens.push(nil) } end --- 174,182 ---- @logger.debug "close:
" end sock.close + # move push inside ensure clause + @tokens.push(nil) end } end