added first methods to interact with sqlmap core, it is now possible to launch a scan from the API, hurray! (issue #297)

This commit is contained in:
Bernardo Damele 2012-12-14 14:51:01 +00:00
parent f52d81c834
commit 27906f388f
2 changed files with 82 additions and 16 deletions

View File

@ -45,6 +45,7 @@ from lib.core.testing import smokeTest
from lib.core.testing import liveTest from lib.core.testing import liveTest
from lib.parse.cmdline import cmdLineParser from lib.parse.cmdline import cmdLineParser
from lib.utils.restapi import restAPIrun from lib.utils.restapi import restAPIrun
from lib.utils.restapi import restAPIsetup
def modulePath(): def modulePath():
""" """
@ -58,13 +59,14 @@ def restApiServe():
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
cmdLineOptions.batch = True cmdLineOptions.batch = True
cmdLineOptions.disableColoring = True cmdLineOptions.disableColoring = True
restAPIrun(port=cmdLineOptions.restApiPort or RESTAPI_SERVER_PORT) restAPIsetup(port=cmdLineOptions.restApiPort or RESTAPI_SERVER_PORT)
def emit(self, record): def emit(self, record):
message = stdoutencode(FORMATTER.format(record)) message = stdoutencode(FORMATTER.format(record))
sys.stdout.write("%s\n" % message.strip('\r')) sys.stdout.write("%s\n" % message.strip('\r'))
LOGGER_HANDLER.emit = types.MethodType(emit, LOGGER_HANDLER, type(LOGGER_HANDLER)) LOGGER_HANDLER.emit = types.MethodType(emit, LOGGER_HANDLER, type(LOGGER_HANDLER))
sys.stdout = StringIO.StringIO() sys.stdout = StringIO.StringIO()
sys.stderr = StringIO.StringIO() #sys.stderr = StringIO.StringIO()
restAPIrun(port=cmdLineOptions.restApiPort or RESTAPI_SERVER_PORT)
def main(): def main():
""" """

View File

@ -18,7 +18,6 @@ except ImportError:
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "..")) sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", ".."))
from extra.bottle.bottle import abort from extra.bottle.bottle import abort
from extra.bottle.bottle import debug
from extra.bottle.bottle import error from extra.bottle.bottle import error
from extra.bottle.bottle import get from extra.bottle.bottle import get
from extra.bottle.bottle import hook from extra.bottle.bottle import hook
@ -41,7 +40,8 @@ from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import RESTAPI_SERVER_PORT from lib.core.settings import RESTAPI_SERVER_PORT
# Local global variables # Local global variables
options = AttribDict() options = {}
output = ""
adminid = "" adminid = ""
tasks = [] tasks = []
@ -51,8 +51,6 @@ def jsonize(data):
def is_admin(taskid): def is_admin(taskid):
global adminid global adminid
#print "[INFO] Admin ID: %s" % adminid
#print "[INFO] Task ID: %s" % taskid
if adminid != taskid: if adminid != taskid:
return False return False
else: else:
@ -103,7 +101,8 @@ def task_new():
Create new task ID Create new task ID
""" """
global tasks global tasks
taskid = hexencode(os.urandom(32)) taskid = hexencode(os.urandom(16))
options[taskid] = AttribDict(cmdLineOptions)
tasks.append(taskid) tasks.append(taskid)
return jsonize({"taskid": taskid}) return jsonize({"taskid": taskid})
@ -144,22 +143,63 @@ def task_flush(taskid):
################################## ##################################
# sqlmap core interact functions # # sqlmap core interact functions #
################################## ##################################
@get("/option/<taskid>/list")
def option_list(taskid):
"""
List options for a certain task ID
"""
global options
if taskid not in tasks:
abort(500, "Invalid task ID")
return jsonize(options[taskid])
@post("/option/<taskid>/get")
def option_get(taskid):
"""
Get the value of an option (command line switch) for a certain task ID
"""
global options
if taskid not in tasks:
abort(500, "Invalid task ID")
option = request.json.get("option", "")
if option in options[taskid]:
print {option: options[taskid][option]}
return jsonize({option: options[taskid][option]})
else:
return jsonize({option: None})
@post("/option/<taskid>/set")
def option_set(taskid):
"""
Set an option (command line switch) for a certain task ID
"""
global options
if taskid not in tasks:
abort(500, "Invalid task ID")
for key, value in request.json.items():
options[taskid][key] = value
return jsonize({"success": True})
@post("/scan/<taskid>") @post("/scan/<taskid>")
def scan(taskid): def scan(taskid):
""" """
Mount a scan with sqlmap Launch a scan
""" """
global options global options
if taskid not in tasks: if taskid not in tasks:
abort(500, "Invalid task ID") abort(500, "Invalid task ID")
# Initialize sqlmap engine's options with user's provided options # Initialize sqlmap engine's options with user's provided options
# within the JSON request # within the JSON request
for key, value in request.json.items(): for key, value in request.json.items():
if key != "taskid": options[taskid][key] = value
options[key] = value init(options[taskid], True)
init(options, True)
# Launch sqlmap engine in a separate thread # Launch sqlmap engine in a separate thread
thread = threading.Thread(target=start) thread = threading.Thread(target=start)
@ -168,6 +208,29 @@ def scan(taskid):
return jsonize({"success": True}) return jsonize({"success": True})
@get("/scan/<taskid>/status")
def scan_status(taskid):
"""
Verify if sqlmap core is currently running
"""
if taskid not in tasks:
abort(500, "Invalid task ID")
return jsonize({"busy": kb.get("busyFlag")})
@get("/scan/<taskid>/output")
def scan_output(taskid):
"""
Read the standard output of sqlmap core execution
"""
if taskid not in tasks:
abort(500, "Invalid task ID")
global output
sys.stdout.seek(len(output))
output = sys.stdout.read()
return jsonize({"output": output})
@post("/download/<taskid>/<target>/<filename:path>") @post("/download/<taskid>/<target>/<filename:path>")
def download(taskid, target, filename): def download(taskid, target, filename):
""" """
@ -182,18 +245,19 @@ def download(taskid, target, filename):
else: else:
abort(500) abort(500)
def restAPIrun(host="0.0.0.0", port=RESTAPI_SERVER_PORT): def restAPIsetup(host="0.0.0.0", port=RESTAPI_SERVER_PORT):
""" """
Initiate REST-JSON API Initiate REST-JSON API
""" """
global adminid global adminid
global options
global tasks global tasks
adminid = hexencode(os.urandom(32)) adminid = hexencode(os.urandom(16))
options[adminid] = AttribDict(cmdLineOptions)
tasks.append(adminid) tasks.append(adminid)
options = AttribDict(cmdLineOptions)
logger.info("Running REST-JSON API server at '%s:%d'.." % (host, port)) logger.info("Running REST-JSON API server at '%s:%d'.." % (host, port))
logger.info("The admin task ID is: %s" % adminid) logger.info("The admin task ID is: %s" % adminid)
def restAPIrun(host="0.0.0.0", port=RESTAPI_SERVER_PORT):
run(host=host, port=port) run(host=host, port=port)
def client(host, port): def client(host, port):