Commit 30a4910d authored by Devon Kearns's avatar Devon Kearns

Imported Upstream version 1.0

parents
*.pyc
*.tmp
*.bak
*.cfg
Copyright 2012, BBQSQL All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the distribution.
* Neither the name of BBQSQL nor the names of its contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The above licensing was taken from the BSD licensing and is applied to BBQSQL as well.
Note that the BBQSQL is provided as is, and is a royalty free open-source application.
Feel free to modify, use, change, market, do whatever you want with it as long as you give the appropriate credit where credit is due (which means giving the authors the credit they deserve for writing it).
\ No newline at end of file
This diff is collapsed.
'''
bbbbbbbb bbbbbbbb
b::::::b b::::::b SSSSSSSSSSSSSSS QQQQQQQQQ LLLLLLLLLLL
b::::::b b::::::b SS:::::::::::::::S QQ:::::::::QQ L:::::::::L
b::::::b b::::::b S:::::SSSSSS::::::S QQ:::::::::::::QQ L:::::::::L
b:::::b b:::::b S:::::S SSSSSSSQ:::::::QQQ:::::::QLL:::::::LL
b:::::bbbbbbbbb b:::::bbbbbbbbb qqqqqqqqq qqqqqS:::::S Q::::::O Q::::::Q L:::::L
b::::::::::::::bb b::::::::::::::bb q:::::::::qqq::::qS:::::S Q:::::O Q:::::Q L:::::L
b::::::::::::::::b b::::::::::::::::b q:::::::::::::::::q S::::SSSS Q:::::O Q:::::Q L:::::L
b:::::bbbbb:::::::bb:::::bbbbb:::::::bq::::::qqqqq::::::qq SS::::::SSSSS Q:::::O Q:::::Q L:::::L
b:::::b b::::::bb:::::b b::::::bq:::::q q:::::q SSS::::::::SS Q:::::O Q:::::Q L:::::L
b:::::b b:::::bb:::::b b:::::bq:::::q q:::::q SSSSSS::::S Q:::::O Q:::::Q L:::::L
b:::::b b:::::bb:::::b b:::::bq:::::q q:::::q S:::::SQ:::::O QQQQ:::::Q L:::::L
b:::::b b:::::bb:::::b b:::::bq::::::q q:::::q S:::::SQ::::::O Q::::::::Q L:::::L LLLLLL
b:::::bbbbbb::::::bb:::::bbbbbb::::::bq:::::::qqqqq:::::q SSSSSSS S:::::SQ:::::::QQ::::::::QLL:::::::LLLLLLLLL:::::L
b::::::::::::::::b b::::::::::::::::b q::::::::::::::::q S::::::SSSSSS:::::S QQ::::::::::::::Q L::::::::::::::::::::::L
b:::::::::::::::b b:::::::::::::::b qq::::::::::::::q S:::::::::::::::SS QQ:::::::::::Q L::::::::::::::::::::::L
bbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbb qqqqqqqq::::::q SSSSSSSSSSSSSSS QQQQQQQQ::::QQLLLLLLLLLLLLLLLLLLLLLLLL
q:::::q Q:::::Q
q:::::q QQQQQQ
q:::::::q
'''''''''
__title__ = 'bbqsql'
__version__ = '1.1'
__author__ = 'Ben Toews (mastahyeti)'
__license__ = 'MIT'
__copyright__ = 'Copyright 2012 Ben Toews (mastahyeti)'
from lib import *
from menu import bbqMenu
import api
from api import *
__all__ = ['BlindSQLi']
\ No newline at end of file
from .query import Query
from .pretty_print import PrettyTable
from .technique import *
from .requester import *
from bbqsql import utilities
from bbqsql import settings
from urllib import quote
from traceback import print_exc
import re
__all__ = ['Query','BlindSQLi']
techniques = {'binary_search':BooleanBlindTechnique,'frequency_search':FrequencyTechnique}
#mappings from response attributes to Requester subclasses
response_attributes = {\
'status_code':Requester,\
'url':Requester,\
'time':LooseNumericRequester,\
'size':LooseNumericRequester,\
'text':LooseTextRequester,\
'content':LooseTextRequester,\
'encoding':LooseTextRequester,\
'cookies':LooseTextRequester,\
'headers':LooseTextRequester,\
'history':LooseTextRequester
}
class BlindSQLi:
'''
This object allows you to do a blind sql injection attack.
'''
def __init__(self,\
query = "row_index=${row_index:1}&character_index=${char_index:1}&character_value=${char_val:0}&comparator=${comparator:>}&sleep=${sleep:0}",\
comparison_attr = "size",
technique = "binary_search",\
concurrency = 50,**kwargs):
'''
Initialize the BlindSQLi with query, comparison_attr, technique, and any Requests
parameters you would like (url,method,headers,cookies). For more details on these,
check out the documentation for the Requests library at https://github.com/kennethreitz/requests .
:param query
This should be a bbqsql.Query object that specified arguments such as
row_index, char_index, character_value, comparator, sleep and so on.
Every time a request is made, this Query gets rendered and put into
the request. You can specify where it gets put into the request by
making one or more of the request parameters a Query object with
an argument called "injection". For example, if the SQL injection
is in the query string of a HTTP GET request, you might set the following:
url = bbqsql.Query('http://127.0.0.1:8090/error?${injection}')
query = bbqsql.Query("row_index=${row_index:1}&character_index=${char_index:1}\\
&character_value=${char_val:0}&comparator=${comparator:>}&sleep=${sleep:0}",encoder=quote)
bsqli = bbqsql.BlindSQLi(query=query,url=url)
:param comparison_attribute
This specifies what part of the HTTP response we are looking at to determing
if your request was evaluated as true or as false. This can be any of the
following response attributes:
-status_code
-url
-time
-size
-text
-content
-encoding
-cookies
-headers
-history
:param technique
This specifies what method we will use for doing the blind SQLi. The available options
are 'binary_search' and 'frequency_search'.
:param concurrency
This is the number of eventlets (evented threads) to use for our requests. This will
rate limit our attack and prevent us from DOSing the server. This should be set close
to the number of worker threads on the server.
:param method: method for the new :class:`Request` object.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
:param data: (optional) Dictionary or bytes to send in the body of the :class:`Request`.
:param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
:param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
:param files: (optional) Dictionary of 'name': file-like-objects (or {'name': ('filename', fileobj)}) for multipart encoding upload.
:param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
:param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed.
:param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
:param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided.
'''
self.concurrency = concurrency
self.error = False
try:
self.technique_type = techniques[technique]
except KeyError:
raise Exception("You are trying to use the %s technique, which is not a valid technique. Your options are %s" % (technique,repr(techniques.keys())))
try:
requester_type = response_attributes[comparison_attr]
except KeyError:
print "You tried to use a comparison_attr that isn't supported. Check the docs for a list"
quit()
# convert query string to Query
self.query = Query(query)
# Convert a string or dict to Query if it matches the necessary syntax.
for key in kwargs:
if type(kwargs[key]) == str and re.match(u'.*\$\{.+\}.*',kwargs[key]):
kwargs[key] = Query(kwargs[key],encoder=quote)
elif type(kwargs[key]) == dict:
for k in kwargs[key]:
if type(k) == str and re.match(u'\$\{.+\}',k):
kwargs[key][Query(k,encoder=quote)] = kwargs[key][k]
del(kwargs[key][k])
if type(kwargs[key][k]) == str and re.match(u'\$\{.+\}',kwargs[key][k]):
kwargs[key][k] = Quote(kwargs[key][k],encoder=quote)
#build a Requester object. You can pass this any args that you would pass to requests.Request
self.requester = requester_type(comparison_attr=comparison_attr, **kwargs)
#the queries default options should evaluate to True in whatever application we are testing. If we flip the comparator it should evauluate to false.
#here, we figure out what the opposite comparator is.
opp_cmp = settings.OPPOSITE_COMPARATORS[self.query.get_option('comparator')]
#set all the indicies back to 0
self.query.set_option('char_index','1')
self.query.set_option('row_index','0')
print "\n"*100
try:
#setup some base values
#true
for i in xrange(settings.TRUTH_BASE_REQUESTS):
self.requester.make_request(value=self.query.render(),case='true',rval=True,debug=(i==settings.TRUTH_BASE_REQUESTS-1))
#false
self.query.set_option('comparator',opp_cmp)
for i in xrange(settings.TRUTH_BASE_REQUESTS):
self.requester.make_request(value=self.query.render(),case='false',rval=False,debug=(i==settings.TRUTH_BASE_REQUESTS-1))
except utilities.TrueFalseRangeOverlap:
self.error = "The response values for true and false are overlapping. Check your configuration.\n"
self.error += "here are the cases we have collected:\n"
self.error += str(self.requester.cases)
'''
#error
self.query.set_option('char_index','1000')
for i in xrange(settings.TRUTH_BASE_REQUESTS):
self.requester.make_request(value=self.query.render(),case='error',rval=False,debug=(i==settings.TRUTH_BASE_REQUESTS-1))
'''
@utilities.debug
def run(self):
'''
Run the BlindSQLi attack, returning the retreived results.
'''
# DEBUGGING
print "lib.api.BlindSQLi.run"
try:
#build our technique
if not settings.QUIET and not settings.PRETTY_PRINT: print "setting up technique"
tech = self.technique_type(requester=self.requester,query=self.query)
if settings.PRETTY_PRINT and not settings.QUIET:
#setup a PrettyTable for curses like printing
pretty_table = PrettyTable(get_table_callback=tech.get_results,get_status_callback=tech.get_status,update=settings.PRETTY_PRINT_FREQUENCY)
#run our technique
if not settings.QUIET and not settings.PRETTY_PRINT: print "starting technique"
techgl = tech.run(concurrency=self.concurrency,row_len=5)
if settings.PRETTY_PRINT and not settings.QUIET:
#start printing the tables
pretty_table.start()
#wait for the technique to finish
techgl.join()
if not settings.QUIET and not settings.PRETTY_PRINT: print "technique finished"
if settings.PRETTY_PRINT and not settings.QUIET:
#kill the pretty tables
pretty_table.die()
results = tech.get_results()
if not settings.QUIET and not settings.PRETTY_PRINT:
print results
return results
except KeyboardInterrupt:
print "stopping attack"
# going to try to retreive the partial results. this could go badly
results = tech.get_results()
return results
# file: pretty_print.py
from bbqsql import utilities
import sys
import re
import gevent
from gevent.event import Event
from subprocess import Popen,PIPE,STDOUT
@utilities.debug
def len_less_color(line):
'''return the length of a string with the color characters stripped out'''
return len(re.sub(u'\033\[[0-9]+m','',line))
class PrettyTable:
def __init__(self,get_table_callback=None,get_status_callback=None,update=.2,row_filter=None):
self.update = update
#function to call to get new tables
self.get_table_callback = get_table_callback
#function to call to get technique status
self.get_status_callback = get_status_callback
# find the terminal size
self._find_screen_size()
self.row_filter = row_filter
@utilities.debug
def start(self):
self._printer_glet = gevent.spawn(self._table_printer)
@utilities.debug
def die(self):
self._printer_glet.kill()
def _find_screen_size(self):
if self._is_linux():
self.sizey,self.sizex = Popen(['stty','size'],stdout=PIPE,stderr=STDOUT,stdin=None).stdout.read().replace('\n','').split(' ')
self.sizex = int(self.sizex)
self.sizey = int(self.sizey)
else:
self.sizey,self.sizex = 40,150
def _is_linux(self):
return 'linux' in sys.platform or 'darwin' in sys.platform
def _table_printer(self):
'''
pretty prints a 1-d list.
'''
i = 0
while True:
table = self.get_table_callback(color=True)
#table = self.get_table_callback()
# keep it short
if len(table)>100: table = table[-100:]
table = filter(self.row_filter,table)
#figure out how many new lines are needed to be printed before the table data
tlen = len(table)
new_lines_needed = self.sizey - tlen - reduce(lambda x,row: x + len_less_color(row) // self.sizex,table,0) - 3
#start building out table,
str_table = "\n"
str_table += "\n".join(table)
str_table += "\n"*new_lines_needed
if self.get_status_callback:
str_table += "\n" + str(self.get_status_callback())
str_table += "\n"
sys.stdout.write(str_table)
# sleep for a bit
gevent.sleep(self.update)
\ No newline at end of file
# file: query.py
from bbqsql import utilities
class Query(object):
'''
A query is a string that can be rendered (think prinf).
query syntax is "SELECT ${blah:default_blah}, ${foo:default_foo} from ${asdf:default_asdf}".
Anything inside ${} will be settable and will be rendered based on value set. For example:
>>> q = bbqsql.Query("hello ${x:world}")
>>> print q.render()
hello world
>>> q.set_option('x','Ben')
>>> print q.render()
hello Ben
'''
def __init__(self,q_string,options=None,encoder=None):
'''
q_string syntax is "SELECT ${blah:default_blah}, ${foo:default_foo} from ${asdf:default_asdf}".
The options are specified in ${}, with the value before the ':' being the option name
and the value after the ':' being the default value.
There is an optional options parameter that allows you to set the option values manually rather than
having them be parsed.
'''
self.encoder = encoder
self.q_string = q_string
if options:
self.options = options
else:
self.options = self.parse_query(q_string)
@utilities.debug
def get_option(self,ident):
'''
Get the option value whose name is 'ident'
'''
return self.options.get(ident,False)
@utilities.debug
def set_option(self,ident,val):
'''
Set the value of the option whose name is 'ident' to val
'''
if self.has_option(ident):self.options[ident] = val
@utilities.debug
def has_option(self,option):
return option in self.options
@utilities.debug
def get_options(self):
'''
Get all of the options (in a dict) for the query
'''
return self.options
@utilities.debug
def set_options(self,options):
'''
Set the queries option (dict).
'''
self.options = options
@utilities.debug
def parse_query(self,q):
'''
This is mostly an internal method, but I didn't want to make it private.
This takes a query string and returns a options dict.
'''
options = {}
section = q.split("${")
if len(section) > 1:
for section in section[1:]:
inside = section.split("}")[0].split(":")
ident = inside[0]
if len(inside) > 1:
default = inside[1]
else:
default = ""
options[ident] = default
return options
@utilities.debug
def render(self):
'''
This compiles the queries options and the original query string into a string.
See the class documentation for an example.
'''
section = self.q_string.split("${")
output = section[0]
if len(section) > 1:
for section in section[1:]:
split = section.split('}')
left = split[0]
#in case there happens to be a rogue } in our query
right = '}'.join(split[1:])
ident = left.split(':')[0]
val = self.options[ident]
if self.encoder != None:
val = self.encoder(val)
output += val
output += right
return output
def __repr__(self):
return self.q_string
def __str__(self):
return self.__repr__()
\ No newline at end of file
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
Copyright 2011, The Social-Engineer Toolkit (SET)
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the distribution.
* Neither the name of Social-Engineer Toolkit nor the names of its contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The above licensing was taken from the BSD licensing and is applied to Social-Engineer Toolkit as well.
Note that the Social-Engineer Toolkit is provided as is, and is a royalty free open-source application.
Feel free to modify, use, change, market, do whatever you want with it as long as you give the appropriate credit where credit
is due (which means giving the authors the credit they deserve for writing it).
\ No newline at end of file
from bbq_menu import bbqMenu
__all__ = ['bbqMenu']
#
# Centralized classes, work in progress
#
import re
import os
# used to grab the true path for current working directory
class bcolors:
PURPLE = '\033[95m'
CYAN = '\033[96m'
DARKCYAN = '\033[36m'
BLUE = '\033[94m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BOLD = '\033[1m'
UNDERL = '\033[4m'
ENDC = '\033[0m'
backBlack = '\033[40m'
backRed = '\033[41m'
backGreen = '\033[42m'
backYellow = '\033[43m'
backBlue = '\033[44m'
backMagenta = '\033[45m'
backCyan = '\033[46m'
backWhite = '\033[47m'
def disable(self):
self.PURPLE = ''
self.CYAN = ''
self.BLUE = ''
self.GREEN = ''
self.YELLOW = ''
self.RED = ''
self.ENDC = ''
self.BOLD = ''
self.UNDERL = ''
self.backBlack = ''
self.backRed = ''
self.backGreen = ''
self.backYellow = ''
self.backBlue = ''
self.backMagenta = ''
self.backCyan = ''
self.backWhite = ''
self.DARKCYAN = ''
#
# Class for colors
#
def ExitBBQ(exitcode=0):
print "\n"*100
print "\n\nGoodbye " + bcolors.RED + os.getlogin() + bcolors.ENDC+", and enjoy a hot plate of ribs on the house.\n"
quit()
def show_graphics():
print bcolors.YELLOW + r"""
_______ _______ ______ ______ ______ __
| \ | \ / \ / \ / \ | \
| $$$$$$$\| $$$$$$$\| $$$$$$\| $$$$$$\| $$$$$$\| $$
| $$__/ $$| $$__/ $$| $$ | $$| $$___\$$| $$ | $$| $$
| $$ $$| $$ $$| $$ | $$ \$$ \ | $$ | $$| $$
| $$$$$$$\| $$$$$$$\| $$ _| $$ _\$$$$$$\| $$ _| $$| $$
| $$__/ $$| $$__/ $$| $$/ \ $$| \__| $$| $$/ \ $$| $$_____
| $$ $$| $$ $$ \$$ $$ $$ \$$ $$ \$$ $$ $$| $$ \
\$$$$$$$ \$$$$$$$ \$$$$$$\ \$$$$$$ \$$$$$$\ \$$$$$$$$
\$$$ \$$$ """ + bcolors.ENDC
print bcolors.RED + r"""
_.(-)._
.' '.
/ 'or '1'='1 \
|'-...___...-'|
\ '=' /
`'._____.'`
/ | \
/.--'|'--.\
[]/'-.__|__.-'\[]
|
[] """ + bcolors.ENDC
return
def show_banner():
print "\n"*100
show_graphics()
print bcolors.BLUE + """
BBQSQL injection toolkit ("""+bcolors.YELLOW+"""bbqsql"""+bcolors.BLUE+""")
Lead Development: """ + bcolors.RED+"""Ben Toews"""+bcolors.BLUE+"""("""+bcolors.YELLOW+"""mastahyeti"""+bcolors.BLUE+""")
Development: """ + bcolors.RED+"""Scott Behrens"""+bcolors.BLUE+"""("""+bcolors.YELLOW+"""arbit"""+bcolors.BLUE+""")
Menu modified from code for Social Engineering Toolkit (SET) by: """ + bcolors.RED+"""David Kennedy """+bcolors.BLUE+"""("""+bcolors.YELLOW+"""ReL1K"""+bcolors.BLUE+""")
SET is located at: """ + bcolors.RED+"""http://www.secmaniac.com"""+bcolors.BLUE+"""("""+bcolors.YELLOW+"""SET"""+bcolors.BLUE+""")
Version: """+bcolors.RED+"""%s""" % ('1.0') +bcolors.BLUE+"""
""" + bcolors.GREEN+""" The 5 S's of BBQ:
Sauce, Spice, Smoke, Sizzle, and """ + bcolors.RED+"""SQLi
"""
print bcolors.ENDC + '\n'
def setprompt(category=None, text=None):
'''helper function for creating prompt text'''
#base of prompt
prompt = bcolors.UNDERL + bcolors.DARKCYAN + "bbqsql"
#if they provide a category
if category:
prompt += ":"+category
prompt += ">"
#if they provide aditional text
if text:
prompt += " "+ text + ":"
prompt += bcolors.ENDC + " "
return prompt
def about():
'''define help, credits, and about'''
print "\n"*100
show_graphics()
print "\n"*5
print bcolors.BOLD + """ Help\n""" + bcolors.ENDC + """
For help, please view the Readme.MD file for usage examples
and detailed information on how the tool works
If you are still running into issues, have ideas for improvements,
or just feature requests you can submit here:
""" + bcolors.BOLD + """https://github.com/Neohapsis/bbqsql/issues\n\n""" + bcolors.ENDC
print bcolors.BOLD + """ Credits\n""" + bcolors.ENDC + """
Special thanks to David Kennedy, Kenneth Reitz, Neohapsis, Wikipedia, and
everyone who has helped file bug fixes. Oh, and ribs. Mmmm ribs! \n\n"""
print bcolors.BOLD + """ About\n""" + bcolors.ENDC + """
BBQSQL version 1.0
https://github.com/Neohapsis/bbqsql
\n\n"""
raw_input("Press any key to continue")
class CreateMenu:
def __init__(self, text, menu):
self.text = text
self.menu = menu
print text
#print "\nType 'help' for information on this module\n"
for i, option in enumerate(menu):
menunum = i + 1
# Check to see if this line has the 'return to main menu' code
match = re.search("0D", option)
# If it's not the return to menu line:
if not match:
if menunum < 10:
print(' %s) %s' % (menunum,option))
else:
print(' %s) %s' % (menunum,option))
else:
print '\n 99) Return to Main Menu\n'
return
import bbqsql
from bbq_core import bcolors
from config import RequestsConfig,bbqsqlConfig
import text
import bbq_core
import time
import os
import sys
import argparse
from ConfigParser import RawConfigParser,NoSectionError,MissingSectionHeaderError
from copy import copy
# config params that are only used in the menu and shouldn't be passed along to BlindSQLi or other parts of bbqsql
exclude_parms = ['csv_output_file','hooks_file']
# main menu
class bbqMenu():
def __init__(self, run_config=None):
# default name for config file
self.config_file = 'attack.cfg'
try:
requests_config = RequestsConfig()
bbqsql_config = bbqsqlConfig()
results = None
error = None
valid = False
# intitial user menu
choice = ''
while choice not in ['99',99,'quit','exit']:
bbq_core.show_banner()
show_main_menu = bbq_core.CreateMenu(text.main_text, text.main_menu)
# special case of list item 99
print '\n 99) Exit the bbqsql injection toolkit\n'
rvalid = requests_config.validate()
bvalid = bbqsql_config.validate()
valid = rvalid and bvalid
# Big results? throw that in a csv file!
if results and len(results) <= 100:
print results
elif results:
print '\n\nbbqsql recieved ' + str(len(results)) + ' rows of data, results truncated to last 100'
print results[-100:]
print '\n\nplease provide a filename so we can save all the results for you'
try:
import readline
readline.parse_and_bind('tab: complete')
except ImportError:
print 'readline module not found'
pass
try:
readline.parse_and_bind('tab: complete')
fname = raw_input('CSV file name [./results.csv]: ')
except:
print "something went wrong, didn't write results to a file"
pass
if fname is not None: