#!/usr/bin/env ruby require "XSpear" XOptions = Struct.new(:url, :data, :headers, :params, :options) class Parser def self.parse(options) args = XOptions.new('xspear') args.options = {} if options.empty? banner puts 'please ' + "'-h'".yellow + ' option' exit end opt_parser = OptionParser.new do |opts| opts.banner = "Usage: xspear -u [target] -[options] [value]\n[ e.g ]\n$ xspear -u 'https://www.hahwul.com/?q=123' --cookie='role=admin' -v 1 -a \n$ xspear -u 'http://testphp.vulnweb.com/listproducts.php?cat=123' -v 2\n$ xspear -u 'http://testphp.vulnweb.com/listproducts.php?cat=123' -v 0 -o json\n\n[ Options ]" opts.on('-u', '--url=target_URL', '[required] Target Url') do |n| args.url = n end opts.on('-d', '--data=POST Body', '[optional] POST Method Body data') do |n| args.options['data'] = n end opts.on('-a','--test-all-params', '[optional] test to all params(include not reflected)') do args.options['all'] = true end opts.on('--headers=HEADERS', '[optional] Add HTTP Headers') do |n| args.options['headers'] = n end opts.on('--cookie=COOKIE', '[optional] Add Cookie') do |n| args.options['cookie'] = 'Cookie: ' + n end opts.on('--raw=FILENAME', '[optional] Load raw file(e.g raw_sample.txt)') do |n| args.options['raw'] = n end opts.on('-p', '--param=PARAM', '[optional] Test paramters') do |n| args.options['params'] = n end opts.on('-b', '--BLIND=URL', '[optional] Add vector of Blind XSS',' + with XSS Hunter, ezXSS, HBXSS, etc...',' + e.g : -b https://hahwul.xss.ht') do |n| args.options['blind'] = n end opts.on('-t', '--threads=NUMBER', '[optional] thread , default: 10') do |n| args.options['thread'] = n end opts.on('-o', '--output=FORMAT', '[optional] Output format (cli , json)') do |n| args.options['output'] = n end opts.on('-c', '--config=FILENAME', '[optional] Using config.json') do |n| args.options['config'] = n end opts.on('-v', '--verbose=0~3', '[optional] Show log depth', ' + v=0 : quite mode(only result)', ' + v=1 : show scanning status(default)', ' + v=2 : show scanning logs', ' + v=3 : show detail log(req/res)') do |n| args.options['verbose'] = n end opts.on('-h', '--help', 'Prints this help') do banner puts opts exit end opts.on('--version', 'Show XSpear version') do puts XSpear::VERSION exit end opts.on('--update', 'Show how to update') do puts "[RubyGem user] : $ gem update XSpear" puts "[Soft | Developer & Git clone user] : $ git pull -v " puts "[Hard | Developer & Git clone user] : $ git reset --hard HEAD; git pull -v " exit end end opt_parser.parse!(options) args end end options = Parser.parse ARGV if !options.options['raw'].nil? begin method = "" path = "" headers_hash = {} headers = "" data = "" switch = true file = File.open options.options['raw'] r = file.read file.close r.each_line do |line| if switch temp = line.split(" ") method = temp[0] path = temp[1] switch = false else if line.include? ": " temp = line.split(": ") hn = temp[0] hd = line.sub(hn+": ", "") headers_hash[hn] = hd headers = headers + "#{hn}: #{hd}\n" elsif line.size > 2 # data data = line else # blank end end end # Burp or ZAP # http, https로 시작하면 zap 아니면 burp 포맷 url = "" if (path.index('http://') == 0 || path.index('https://') == 0) url = path else url = "http://"+headers_hash['Host'].to_s.chomp!+"/"+path end options.url = url if headers.length > 0 options.options['headers'] = headers end if method == "POST" && data.size options.options['data'] = data end rescue => e puts "RAW file Error #{e}" exit end end exit unless options.url options.options['thread'] = 10 unless options.options['thread'] options.options['verbose'] = 1 unless options.options['verbose'] options.options['thread'] = options.options['thread'].to_i if !options.options['config'].nil? f = File.open(options.options['config']) buf = f.read cjson = JSON.parse buf cjson.each do |key,value| if value.to_s.size > 0 options.options[key] = value end end end if options.options['verbose'].to_i != 0 banner end s = XspearScan.new options.url, options.options s.run