mirror of https://github.com/OWASP/Nettacker.git
update code based docs #1
This commit is contained in:
parent
101224efe4
commit
48fdd9a5fc
|
|
@ -19,11 +19,15 @@ from core import compatible
|
||||||
|
|
||||||
|
|
||||||
def create_connection(language):
|
def create_connection(language):
|
||||||
'''
|
"""
|
||||||
a function to create sqlite3 connections to db, it retries 100 times if connection returned an error
|
a function to create sqlite3 connections to db, it retries 100 times if connection returned an error
|
||||||
:param language: language
|
|
||||||
:return: sqlite3 connection if success otherwise False
|
Args:
|
||||||
'''
|
language: language
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
sqlite3 connection if success otherwise False
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
# retries
|
# retries
|
||||||
for i in range(0, 100):
|
for i in range(0, 100):
|
||||||
|
|
@ -38,13 +42,17 @@ def create_connection(language):
|
||||||
|
|
||||||
|
|
||||||
def send_submit_query(query, language):
|
def send_submit_query(query, language):
|
||||||
'''
|
"""
|
||||||
a function to send submit based queries to db (such as insert and update or delete), it retries 100 times if
|
a function to send submit based queries to db (such as insert and update or delete), it retries 100 times if
|
||||||
connection returned an error.
|
connection returned an error.
|
||||||
:param query: query to execute
|
|
||||||
:param language: language
|
Args:
|
||||||
:return: True if submitted success otherwise False
|
query: query to execute
|
||||||
'''
|
language: language
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if submitted success otherwise False
|
||||||
|
"""
|
||||||
conn = create_connection(language)
|
conn = create_connection(language)
|
||||||
if not conn:
|
if not conn:
|
||||||
return False
|
return False
|
||||||
|
|
@ -65,12 +73,16 @@ def send_submit_query(query, language):
|
||||||
|
|
||||||
|
|
||||||
def send_read_query(query, language):
|
def send_read_query(query, language):
|
||||||
'''
|
"""
|
||||||
a function to send read based queries to db (such as select), it retries 100 times if connection returned an error.
|
a function to send read based queries to db (such as select), it retries 100 times if connection returned an error.
|
||||||
:param query: query to execute
|
|
||||||
:param language: language
|
Args:
|
||||||
:return: return executed query otherwise False
|
query: query to execute
|
||||||
'''
|
language: language
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
return executed query otherwise False
|
||||||
|
"""
|
||||||
conn = create_connection(language)
|
conn = create_connection(language)
|
||||||
if not conn:
|
if not conn:
|
||||||
return False
|
return False
|
||||||
|
|
@ -89,24 +101,28 @@ def send_read_query(query, language):
|
||||||
|
|
||||||
def submit_report_to_db(date, scan_id, report_filename, events_num, verbose, api_flag, report_type, graph_flag,
|
def submit_report_to_db(date, scan_id, report_filename, events_num, verbose, api_flag, report_type, graph_flag,
|
||||||
category, profile, scan_method, language, scan_cmd, ports):
|
category, profile, scan_method, language, scan_cmd, ports):
|
||||||
'''
|
"""
|
||||||
this function created to submit the generated reports into db, the files are not stored in db, just the path!
|
this function created to submit the generated reports into db, the files are not stored in db, just the path!
|
||||||
:param date: date and time
|
|
||||||
:param scan_id: scan hash id
|
Args:
|
||||||
:param report_filename: report full path and filename
|
date: date and time
|
||||||
:param events_num: length of events in the report
|
scan_id: scan hash id
|
||||||
:param verbose: verbose level used to generated the report
|
report_filename: report full path and filename
|
||||||
:param api_flag: 0 (False) if scan run from CLI and 1 (True) if scan run from API
|
events_num: length of events in the report
|
||||||
:param report_type: could be TEXT, JSON or HTML
|
verbose: verbose level used to generated the report
|
||||||
:param graph_flag: name of the graph used (if it's HTML type)
|
api_flag: 0 (False) if scan run from CLI and 1 (True) if scan run from API
|
||||||
:param category: category of the modules used in scan (vuln, scan, brute)
|
report_type: could be TEXT, JSON or HTML
|
||||||
:param profile: profiles used in scan
|
graph_flag: name of the graph used (if it's HTML type)
|
||||||
:param scan_method: modules used in scan
|
category: category of the modules used in scan (vuln, scan, brute)
|
||||||
:param language: scan report language
|
profile: profiles used in scan
|
||||||
:param scan_cmd: scan command line if run in CLI otherwise messages(language, 158)
|
scan_method: modules used in scan
|
||||||
:param ports: selected port otherwise None
|
language: scan report language
|
||||||
:return: return True if submitted otherwise False
|
scan_cmd: scan command line if run in CLI otherwise messages(language, 158)
|
||||||
'''
|
ports: selected port otherwise None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
return True if submitted otherwise False
|
||||||
|
"""
|
||||||
info(messages(language, 169))
|
info(messages(language, 169))
|
||||||
return send_submit_query("""
|
return send_submit_query("""
|
||||||
INSERT INTO reports (
|
INSERT INTO reports (
|
||||||
|
|
@ -125,25 +141,33 @@ def submit_report_to_db(date, scan_id, report_filename, events_num, verbose, api
|
||||||
|
|
||||||
|
|
||||||
def remove_old_logs(host, type, scan_id, language):
|
def remove_old_logs(host, type, scan_id, language):
|
||||||
'''
|
"""
|
||||||
this function remove old events (and duplicated) from database based on host, module, scan_id
|
this function remove old events (and duplicated) from database based on host, module, scan_id
|
||||||
:param host: host
|
|
||||||
:param type: module name
|
Args:
|
||||||
:param scan_id: scan id hash
|
host: host
|
||||||
:param language: language
|
type: module name
|
||||||
:return: True if success otherwise False
|
scan_id: scan id hash
|
||||||
'''
|
language: language
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if success otherwise False
|
||||||
|
"""
|
||||||
return send_submit_query("""delete from hosts_log where host="{0}" and type="{1}" and scan_id!="{2}" """
|
return send_submit_query("""delete from hosts_log where host="{0}" and type="{1}" and scan_id!="{2}" """
|
||||||
.format(host, type, scan_id), language)
|
.format(host, type, scan_id), language)
|
||||||
|
|
||||||
|
|
||||||
def submit_logs_to_db(language, log):
|
def submit_logs_to_db(language, log):
|
||||||
'''
|
"""
|
||||||
this function created to submit new events into database
|
this function created to submit new events into database
|
||||||
:param language: language
|
|
||||||
:param log: log event in JSON type
|
Args:
|
||||||
:return: True if success otherwise False
|
language: language
|
||||||
'''
|
log: log event in JSON type
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if success otherwise False
|
||||||
|
"""
|
||||||
if type(log) == str:
|
if type(log) == str:
|
||||||
log = json.loads(log)
|
log = json.loads(log)
|
||||||
return send_submit_query("""
|
return send_submit_query("""
|
||||||
|
|
@ -162,13 +186,17 @@ def submit_logs_to_db(language, log):
|
||||||
|
|
||||||
|
|
||||||
def __select_results(language, page):
|
def __select_results(language, page):
|
||||||
'''
|
"""
|
||||||
this function created to crawl into submitted results, it shows last 10 results submitted in the database.
|
this function created to crawl into submitted results, it shows last 10 results submitted in the database.
|
||||||
you may change the page (default 1) to go to next/previous page.
|
you may change the page (default 1) to go to next/previous page.
|
||||||
:param language: language
|
|
||||||
:param page: page number
|
Args:
|
||||||
:return: list of events in array and JSON type, otherwise an error in JSON type.
|
language: language
|
||||||
'''
|
page: page number
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list of events in array and JSON type, otherwise an error in JSON type.
|
||||||
|
"""
|
||||||
page = int(page * 10 if page > 0 else page * -10) - 10
|
page = int(page * 10 if page > 0 else page * -10) - 10
|
||||||
selected = []
|
selected = []
|
||||||
try:
|
try:
|
||||||
|
|
@ -198,12 +226,16 @@ def __select_results(language, page):
|
||||||
|
|
||||||
|
|
||||||
def __get_result(language, id):
|
def __get_result(language, id):
|
||||||
'''
|
"""
|
||||||
this function created to download results by the result ID.
|
this function created to download results by the result ID.
|
||||||
:param language: language
|
|
||||||
:param id: result id
|
Args:
|
||||||
:return: result file content (TEXT, HTML, JSON) if success otherwise and error in JSON type.
|
language: language
|
||||||
'''
|
id: result id
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
result file content (TEXT, HTML, JSON) if success otherwise and error in JSON type.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
filename = send_read_query("""select report_filename from reports where id=\"{0}\";""".format(id),
|
filename = send_read_query("""select report_filename from reports where id=\"{0}\";""".format(id),
|
||||||
|
|
@ -216,12 +248,16 @@ def __get_result(language, id):
|
||||||
|
|
||||||
|
|
||||||
def __last_host_logs(language, page):
|
def __last_host_logs(language, page):
|
||||||
'''
|
"""
|
||||||
this function created to select the last 10 events from the database. you can goto next page by changing page value.
|
this function created to select the last 10 events from the database. you can goto next page by changing page value.
|
||||||
:param language: language
|
|
||||||
:param page: page number
|
Args:
|
||||||
:return: an array of events in JSON type if success otherwise an error in JSON type
|
language: language
|
||||||
'''
|
page: page number
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
an array of events in JSON type if success otherwise an error in JSON type
|
||||||
|
"""
|
||||||
page = int(page * 10 if page > 0 else page * -10) - 10
|
page = int(page * 10 if page > 0 else page * -10) - 10
|
||||||
data_structure = {
|
data_structure = {
|
||||||
"host": "",
|
"host": "",
|
||||||
|
|
@ -277,12 +313,16 @@ def __last_host_logs(language, page):
|
||||||
|
|
||||||
|
|
||||||
def __logs_by_scan_id(scan_id, language):
|
def __logs_by_scan_id(scan_id, language):
|
||||||
'''
|
"""
|
||||||
select all events by scan id hash
|
select all events by scan id hash
|
||||||
:param scan_id: scan id hash
|
|
||||||
:param language: language
|
Args:
|
||||||
:return: an array with JSON events or an empty array
|
scan_id: scan id hash
|
||||||
'''
|
language: language
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
an array with JSON events or an empty array
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
logs = []
|
logs = []
|
||||||
for log in send_read_query(
|
for log in send_read_query(
|
||||||
|
|
@ -305,12 +345,16 @@ def __logs_by_scan_id(scan_id, language):
|
||||||
|
|
||||||
|
|
||||||
def __logs_to_report_json(host, language):
|
def __logs_to_report_json(host, language):
|
||||||
'''
|
"""
|
||||||
select all reports of a host
|
select all reports of a host
|
||||||
:param host: the host to search
|
|
||||||
:param language: language
|
Args:
|
||||||
:return: an array with JSON events or an empty array
|
host: the host to search
|
||||||
'''
|
language: language
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
an array with JSON events or an empty array
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
logs = []
|
logs = []
|
||||||
for log in send_read_query(
|
for log in send_read_query(
|
||||||
|
|
@ -333,12 +377,16 @@ def __logs_to_report_json(host, language):
|
||||||
|
|
||||||
|
|
||||||
def __logs_to_report_html(host, language):
|
def __logs_to_report_html(host, language):
|
||||||
'''
|
"""
|
||||||
generate HTML report with d3_tree_v2_graph for a host
|
generate HTML report with d3_tree_v2_graph for a host
|
||||||
:param host: the host
|
|
||||||
:param language: language
|
Args:
|
||||||
:return: HTML report
|
host: the host
|
||||||
'''
|
language: language
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
HTML report
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
logs = []
|
logs = []
|
||||||
for log in send_read_query(
|
for log in send_read_query(
|
||||||
|
|
@ -377,13 +425,17 @@ def __logs_to_report_html(host, language):
|
||||||
|
|
||||||
|
|
||||||
def __search_logs(language, page, query):
|
def __search_logs(language, page, query):
|
||||||
'''
|
"""
|
||||||
search in events (host, date, port, module, category, description, username, password, scan_id, scan_cmd)
|
search in events (host, date, port, module, category, description, username, password, scan_id, scan_cmd)
|
||||||
:param language: language
|
|
||||||
:param page: page number
|
Args:
|
||||||
:param query: query to search
|
language: language
|
||||||
:return: an array with JSON structure of founded events or an empty array
|
page: page number
|
||||||
'''
|
query: query to search
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
an array with JSON structure of founded events or an empty array
|
||||||
|
"""
|
||||||
page = int(page * 10 if page > 0 else page * -10) - 10
|
page = int(page * 10 if page > 0 else page * -10) - 10
|
||||||
data_structure = {
|
data_structure = {
|
||||||
"host": "",
|
"host": "",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,15 @@ from core.attack import __go_for_attacks
|
||||||
|
|
||||||
|
|
||||||
def __scan(config):
|
def __scan(config):
|
||||||
|
"""
|
||||||
|
call for attacks with separated config and parse ARGS
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: config in JSON
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if success otherwise False
|
||||||
|
"""
|
||||||
# Setting Variables
|
# Setting Variables
|
||||||
targets = config["targets"]
|
targets = config["targets"]
|
||||||
check_ranges = config["check_ranges"]
|
check_ranges = config["check_ranges"]
|
||||||
|
|
@ -28,7 +37,7 @@ def __scan(config):
|
||||||
profile = config["profile"]
|
profile = config["profile"]
|
||||||
backup_ports = config["backup_ports"]
|
backup_ports = config["backup_ports"]
|
||||||
|
|
||||||
__go_for_attacks(targets, check_ranges, check_subdomains, log_in_file, time_sleep, language, verbose_level, retries,
|
return __go_for_attacks(targets, check_ranges, check_subdomains, log_in_file, time_sleep, language, verbose_level,
|
||||||
socks_proxy, users, passwds, timeout_sec, thread_number, ports, ping_flag, methods_args,
|
retries,
|
||||||
backup_ports, scan_method, thread_number_host, graph_flag, profile, True)
|
socks_proxy, users, passwds, timeout_sec, thread_number, ports, ping_flag, methods_args,
|
||||||
return True
|
backup_ports, scan_method, thread_number_host, graph_flag, profile, True)
|
||||||
|
|
|
||||||
111
api/api_core.py
111
api/api_core.py
|
|
@ -12,6 +12,16 @@ from flask import abort
|
||||||
|
|
||||||
|
|
||||||
def __structure(status="", msg=""):
|
def __structure(status="", msg=""):
|
||||||
|
"""
|
||||||
|
basic JSON message structure
|
||||||
|
|
||||||
|
Args:
|
||||||
|
status: status (ok, failed)
|
||||||
|
msg: the message content
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
a JSON message
|
||||||
|
"""
|
||||||
return {
|
return {
|
||||||
"status": status,
|
"status": status,
|
||||||
"msg": msg
|
"msg": msg
|
||||||
|
|
@ -19,6 +29,16 @@ def __structure(status="", msg=""):
|
||||||
|
|
||||||
|
|
||||||
def __get_value(flask_request, _key):
|
def __get_value(flask_request, _key):
|
||||||
|
"""
|
||||||
|
get a value from GET, POST or CCOKIES
|
||||||
|
|
||||||
|
Args:
|
||||||
|
flask_request: the flask request
|
||||||
|
_key: the value name to find
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
the value content if found otherwise None
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
key = flask_request.args[_key]
|
key = flask_request.args[_key]
|
||||||
except:
|
except:
|
||||||
|
|
@ -30,11 +50,21 @@ def __get_value(flask_request, _key):
|
||||||
except:
|
except:
|
||||||
key = None
|
key = None
|
||||||
if key is not None:
|
if key is not None:
|
||||||
key = key.replace("\"", "").replace("'", "")
|
# fix it later
|
||||||
|
key = key.replace("\\\"", "\"").replace("\\\'", "\'")
|
||||||
return key
|
return key
|
||||||
|
|
||||||
|
|
||||||
def __remove_non_api_keys(config):
|
def __remove_non_api_keys(config):
|
||||||
|
"""
|
||||||
|
a function to remove non-api keys while loading ARGV
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: all keys in JSON
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
removed non-api keys in all keys in JSON
|
||||||
|
"""
|
||||||
non_api_keys = ["start_api", "api_host", "api_port", "api_debug_mode", "api_access_key", "api_client_white_list",
|
non_api_keys = ["start_api", "api_host", "api_port", "api_debug_mode", "api_access_key", "api_client_white_list",
|
||||||
"api_client_white_list_ips", "api_access_log", "api_access_log", "api_access_log_filename",
|
"api_client_white_list_ips", "api_access_log", "api_access_log", "api_access_log_filename",
|
||||||
"show_version", "check_update", "help_menu_flag", "targets_list", "users_list", "passwds_list",
|
"show_version", "check_update", "help_menu_flag", "targets_list", "users_list", "passwds_list",
|
||||||
|
|
@ -47,12 +77,28 @@ def __remove_non_api_keys(config):
|
||||||
|
|
||||||
|
|
||||||
def __is_login(app, flask_request):
|
def __is_login(app, flask_request):
|
||||||
|
"""
|
||||||
|
check if session is valid
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app: flask app
|
||||||
|
flask_request: flask request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if session is valid otherwise False
|
||||||
|
"""
|
||||||
if app.config["OWASP_NETTACKER_CONFIG"]["api_access_key"] == __get_value(flask_request, "key"):
|
if app.config["OWASP_NETTACKER_CONFIG"]["api_access_key"] == __get_value(flask_request, "key"):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def __mime_types():
|
def __mime_types():
|
||||||
|
"""
|
||||||
|
contains all mime types for HTTP request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
all mime types in json
|
||||||
|
"""
|
||||||
return {
|
return {
|
||||||
".aac": "audio/aac",
|
".aac": "audio/aac",
|
||||||
".abw": "application/x-abiword",
|
".abw": "application/x-abiword",
|
||||||
|
|
@ -126,10 +172,25 @@ def __mime_types():
|
||||||
|
|
||||||
|
|
||||||
def root_dir():
|
def root_dir():
|
||||||
|
"""
|
||||||
|
find the root directory for web static files
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
root path for static files
|
||||||
|
"""
|
||||||
return os.path.join(os.path.join(os.path.dirname(os.path.dirname(__file__)), "web"), "static")
|
return os.path.join(os.path.join(os.path.dirname(os.path.dirname(__file__)), "web"), "static")
|
||||||
|
|
||||||
|
|
||||||
def get_file(filename):
|
def get_file(filename):
|
||||||
|
"""
|
||||||
|
open the requested file in HTTP requests
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename: path and the filename
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
content of the file or abort(404)
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
src = os.path.join(root_dir(), filename)
|
src = os.path.join(root_dir(), filename)
|
||||||
return open(src, 'rb').read()
|
return open(src, 'rb').read()
|
||||||
|
|
@ -138,11 +199,30 @@ def get_file(filename):
|
||||||
|
|
||||||
|
|
||||||
def __api_key_check(app, flask_request, language):
|
def __api_key_check(app, flask_request, language):
|
||||||
|
"""
|
||||||
|
check the validity of API key
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app: the flask app
|
||||||
|
flask_request: the flask request
|
||||||
|
language: language
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
200 HTTP code if it's valid otherwise 401 error
|
||||||
|
|
||||||
|
"""
|
||||||
if app.config["OWASP_NETTACKER_CONFIG"]["api_access_key"] != __get_value(flask_request, "key"):
|
if app.config["OWASP_NETTACKER_CONFIG"]["api_access_key"] != __get_value(flask_request, "key"):
|
||||||
abort(401, messages(language, 160))
|
abort(401, messages(language, 160))
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def __languages():
|
def __languages():
|
||||||
|
"""
|
||||||
|
define list of languages with country flag for API
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
HTML code for each language with its country flag
|
||||||
|
"""
|
||||||
languages = [lang for lang in messages(-1, 0)]
|
languages = [lang for lang in messages(-1, 0)]
|
||||||
res = ""
|
res = ""
|
||||||
flags = {
|
flags = {
|
||||||
|
|
@ -174,6 +254,12 @@ def __languages():
|
||||||
|
|
||||||
|
|
||||||
def __graphs():
|
def __graphs():
|
||||||
|
"""
|
||||||
|
all available graphs for API
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
HTML content or available graphs
|
||||||
|
"""
|
||||||
res = """<label><input id="" type="radio" name="graph_flag" value="" class="radio"><a
|
res = """<label><input id="" type="radio" name="graph_flag" value="" class="radio"><a
|
||||||
class="label label-default">None</a></label> """
|
class="label label-default">None</a></label> """
|
||||||
for graph in load_all_graphs():
|
for graph in load_all_graphs():
|
||||||
|
|
@ -183,6 +269,12 @@ def __graphs():
|
||||||
|
|
||||||
|
|
||||||
def __profiles():
|
def __profiles():
|
||||||
|
"""
|
||||||
|
all available profiles for API
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
HTML content or available profiles
|
||||||
|
"""
|
||||||
profiles = _builder(_profiles(), default_profiles())
|
profiles = _builder(_profiles(), default_profiles())
|
||||||
res = ""
|
res = ""
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
|
|
@ -192,6 +284,12 @@ def __profiles():
|
||||||
|
|
||||||
|
|
||||||
def __scan_methods():
|
def __scan_methods():
|
||||||
|
"""
|
||||||
|
all available modules for API
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
HTML content or available modules
|
||||||
|
"""
|
||||||
methods = load_all_modules()
|
methods = load_all_modules()
|
||||||
methods.remove("all")
|
methods.remove("all")
|
||||||
res = ""
|
res = ""
|
||||||
|
|
@ -204,6 +302,17 @@ def __scan_methods():
|
||||||
|
|
||||||
|
|
||||||
def __rules(config, defaults, language):
|
def __rules(config, defaults, language):
|
||||||
|
"""
|
||||||
|
Load ARGS from API requests and apply the rules
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: all user config
|
||||||
|
defaults: default config
|
||||||
|
language: language
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
config with applied rules
|
||||||
|
"""
|
||||||
# Check Ranges
|
# Check Ranges
|
||||||
config["check_ranges"] = True if config["check_ranges"] is not False else False
|
config["check_ranges"] = True if config["check_ranges"] is not False else False
|
||||||
# Check Subdomains
|
# Check Subdomains
|
||||||
|
|
|
||||||
164
api/engine.py
164
api/engine.py
|
|
@ -47,40 +47,101 @@ app.config.from_object(__name__)
|
||||||
|
|
||||||
|
|
||||||
def __language(app=app):
|
def __language(app=app):
|
||||||
|
"""
|
||||||
|
find the language in config
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app: flask app
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
the language in string
|
||||||
|
"""
|
||||||
return app.config["OWASP_NETTACKER_CONFIG"]["language"]
|
return app.config["OWASP_NETTACKER_CONFIG"]["language"]
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(400)
|
@app.errorhandler(400)
|
||||||
def error_400(error):
|
def error_400(error):
|
||||||
|
"""
|
||||||
|
handle the 400 HTTP error
|
||||||
|
|
||||||
|
Args:
|
||||||
|
error: the flask error
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
400 JSON error
|
||||||
|
"""
|
||||||
return jsonify(__structure(status="error", msg=error.description)), 400
|
return jsonify(__structure(status="error", msg=error.description)), 400
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(401)
|
@app.errorhandler(401)
|
||||||
def error_401(error):
|
def error_401(error):
|
||||||
|
"""
|
||||||
|
handle the 401 HTTP error
|
||||||
|
|
||||||
|
Args:
|
||||||
|
error: the flask error
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
401 JSON error
|
||||||
|
"""
|
||||||
return jsonify(__structure(status="error", msg=error.description)), 401
|
return jsonify(__structure(status="error", msg=error.description)), 401
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(403)
|
@app.errorhandler(403)
|
||||||
def error_403(error):
|
def error_403(error):
|
||||||
|
"""
|
||||||
|
handle the 403 HTTP error
|
||||||
|
|
||||||
|
Args:
|
||||||
|
error: the flask error
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
403 JSON error
|
||||||
|
"""
|
||||||
return jsonify(__structure(status="error", msg=error.description)), 403
|
return jsonify(__structure(status="error", msg=error.description)), 403
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
def error_404(error):
|
def error_404(error):
|
||||||
|
"""
|
||||||
|
handle the 404 HTTP error
|
||||||
|
|
||||||
|
Args:
|
||||||
|
error: the flask error
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
404 JSON error
|
||||||
|
"""
|
||||||
return jsonify(__structure(status="error",
|
return jsonify(__structure(status="error",
|
||||||
msg=messages(app.config["OWASP_NETTACKER_CONFIG"]["language"], 162))), 404
|
msg=messages(app.config["OWASP_NETTACKER_CONFIG"]["language"], 162))), 404
|
||||||
|
|
||||||
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def limit_remote_addr():
|
def limit_remote_addr():
|
||||||
|
"""
|
||||||
|
check if IP filtering applied and API address is in whitelist
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None if it's in whitelist otherwise abort(403)
|
||||||
|
"""
|
||||||
# IP Limitation
|
# IP Limitation
|
||||||
if app.config["OWASP_NETTACKER_CONFIG"]["api_client_white_list"]:
|
if app.config["OWASP_NETTACKER_CONFIG"]["api_client_white_list"]:
|
||||||
if flask_request.remote_addr not in app.config["OWASP_NETTACKER_CONFIG"]["api_client_white_list_ips"]:
|
if flask_request.remote_addr not in app.config["OWASP_NETTACKER_CONFIG"]["api_client_white_list_ips"]:
|
||||||
abort(403, messages(__language(), 161))
|
abort(403, messages(__language(), 161))
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
def access_log(response):
|
def access_log(response):
|
||||||
|
"""
|
||||||
|
if access log enabled, its writing the logs
|
||||||
|
|
||||||
|
Args:
|
||||||
|
response: the flask response
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
the flask response
|
||||||
|
"""
|
||||||
if app.config["OWASP_NETTACKER_CONFIG"]["api_access_log"]:
|
if app.config["OWASP_NETTACKER_CONFIG"]["api_access_log"]:
|
||||||
r_log = open(app.config["OWASP_NETTACKER_CONFIG"]["api_access_log_filename"], "ab")
|
r_log = open(app.config["OWASP_NETTACKER_CONFIG"]["api_access_log_filename"], "ab")
|
||||||
# if you need to log POST data
|
# if you need to log POST data
|
||||||
|
|
@ -99,6 +160,15 @@ def access_log(response):
|
||||||
@app.route("/", defaults={"path": ""})
|
@app.route("/", defaults={"path": ""})
|
||||||
@app.route("/<path:path>")
|
@app.route("/<path:path>")
|
||||||
def get_statics(path):
|
def get_statics(path):
|
||||||
|
"""
|
||||||
|
getting static files and return content mime types
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: path and filename
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
file content and content type if file found otherwise abort(404)
|
||||||
|
"""
|
||||||
static_types = __mime_types()
|
static_types = __mime_types()
|
||||||
return Response(get_file(os.path.join(root_dir(), path)),
|
return Response(get_file(os.path.join(root_dir(), path)),
|
||||||
mimetype=static_types.get(os.path.splitext(path)[1], "text/html"))
|
mimetype=static_types.get(os.path.splitext(path)[1], "text/html"))
|
||||||
|
|
@ -106,6 +176,12 @@ def get_statics(path):
|
||||||
|
|
||||||
@app.route("/", methods=["GET", "POST"])
|
@app.route("/", methods=["GET", "POST"])
|
||||||
def index():
|
def index():
|
||||||
|
"""
|
||||||
|
index page for WebUI
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
rendered HTML page
|
||||||
|
"""
|
||||||
filename = _builder(_core_config(), _core_default_config())["log_in_file"]
|
filename = _builder(_core_config(), _core_default_config())["log_in_file"]
|
||||||
return render_template("index.html", scan_method=__scan_methods(), profile=__profiles(),
|
return render_template("index.html", scan_method=__scan_methods(), profile=__profiles(),
|
||||||
graphs=__graphs(), languages=__languages(), filename=filename,
|
graphs=__graphs(), languages=__languages(), filename=filename,
|
||||||
|
|
@ -114,6 +190,12 @@ def index():
|
||||||
|
|
||||||
@app.route("/new/scan", methods=["GET", "POST"])
|
@app.route("/new/scan", methods=["GET", "POST"])
|
||||||
def new_scan():
|
def new_scan():
|
||||||
|
"""
|
||||||
|
new scan through the API
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
a JSON message with scan details if success otherwise a JSON error
|
||||||
|
"""
|
||||||
_start_scan_config = {}
|
_start_scan_config = {}
|
||||||
__api_key_check(app, flask_request, __language())
|
__api_key_check(app, flask_request, __language())
|
||||||
for key in _core_default_config():
|
for key in _core_default_config():
|
||||||
|
|
@ -134,12 +216,24 @@ def new_scan():
|
||||||
|
|
||||||
@app.route("/session/check", methods=["GET"])
|
@app.route("/session/check", methods=["GET"])
|
||||||
def __session_check():
|
def __session_check():
|
||||||
|
"""
|
||||||
|
check the session if it's valid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
a JSON message if it's valid otherwise abort(401)
|
||||||
|
"""
|
||||||
__api_key_check(app, flask_request, __language())
|
__api_key_check(app, flask_request, __language())
|
||||||
return jsonify(__structure(status="ok", msg=messages(__language(), 165))), 200
|
return jsonify(__structure(status="ok", msg=messages(__language(), 165))), 200
|
||||||
|
|
||||||
|
|
||||||
@app.route("/session/set", methods=["GET"])
|
@app.route("/session/set", methods=["GET"])
|
||||||
def __session_set():
|
def __session_set():
|
||||||
|
"""
|
||||||
|
set session on the browser
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
200 HTTP response if session is valid and a set-cookie in the response if success otherwise abort(403)
|
||||||
|
"""
|
||||||
__api_key_check(app, flask_request, __language())
|
__api_key_check(app, flask_request, __language())
|
||||||
res = make_response(jsonify(__structure(status="ok", msg=messages(__language(), 165))))
|
res = make_response(jsonify(__structure(status="ok", msg=messages(__language(), 165))))
|
||||||
res.set_cookie("key", value=app.config["OWASP_NETTACKER_CONFIG"]["api_access_key"])
|
res.set_cookie("key", value=app.config["OWASP_NETTACKER_CONFIG"]["api_access_key"])
|
||||||
|
|
@ -148,6 +242,12 @@ def __session_set():
|
||||||
|
|
||||||
@app.route("/session/kill", methods=["GET"])
|
@app.route("/session/kill", methods=["GET"])
|
||||||
def __session_kill():
|
def __session_kill():
|
||||||
|
"""
|
||||||
|
unset session on the browser
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
a 200 HTTP response with set-cookie to "expired" to unset the cookie on the browser
|
||||||
|
"""
|
||||||
res = make_response(jsonify(__structure(status="ok", msg=messages(__language(), 166))))
|
res = make_response(jsonify(__structure(status="ok", msg=messages(__language(), 166))))
|
||||||
res.set_cookie("key", value="expired")
|
res.set_cookie("key", value="expired")
|
||||||
return res
|
return res
|
||||||
|
|
@ -155,6 +255,12 @@ def __session_kill():
|
||||||
|
|
||||||
@app.route("/results/get_list", methods=["GET"])
|
@app.route("/results/get_list", methods=["GET"])
|
||||||
def __get_results():
|
def __get_results():
|
||||||
|
"""
|
||||||
|
get list of scan's results through the API
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
an array of JSON scan's results if success otherwise abort(403)
|
||||||
|
"""
|
||||||
__api_key_check(app, flask_request, __language())
|
__api_key_check(app, flask_request, __language())
|
||||||
try:
|
try:
|
||||||
page = int(__get_value(flask_request, "page"))
|
page = int(__get_value(flask_request, "page"))
|
||||||
|
|
@ -165,6 +271,12 @@ def __get_results():
|
||||||
|
|
||||||
@app.route("/results/get", methods=["GET"])
|
@app.route("/results/get", methods=["GET"])
|
||||||
def __get_result_content():
|
def __get_result_content():
|
||||||
|
"""
|
||||||
|
get a result HTML/TEXT/JSON content
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
content of the scan result
|
||||||
|
"""
|
||||||
__api_key_check(app, flask_request, __language())
|
__api_key_check(app, flask_request, __language())
|
||||||
try:
|
try:
|
||||||
id = int(__get_value(flask_request, "id"))
|
id = int(__get_value(flask_request, "id"))
|
||||||
|
|
@ -175,6 +287,12 @@ def __get_result_content():
|
||||||
|
|
||||||
@app.route("/logs/get_list", methods=["GET"])
|
@app.route("/logs/get_list", methods=["GET"])
|
||||||
def __get_last_host_logs():
|
def __get_last_host_logs():
|
||||||
|
"""
|
||||||
|
get list of logs through the API
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
an array of JSON logs if success otherwise abort(403)
|
||||||
|
"""
|
||||||
__api_key_check(app, flask_request, __language())
|
__api_key_check(app, flask_request, __language())
|
||||||
try:
|
try:
|
||||||
page = int(__get_value(flask_request, "page"))
|
page = int(__get_value(flask_request, "page"))
|
||||||
|
|
@ -185,6 +303,12 @@ def __get_last_host_logs():
|
||||||
|
|
||||||
@app.route("/logs/get_html", methods=["GET"])
|
@app.route("/logs/get_html", methods=["GET"])
|
||||||
def __get_logs_html():
|
def __get_logs_html():
|
||||||
|
"""
|
||||||
|
get host's logs through the API in HTML type
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
HTML report
|
||||||
|
"""
|
||||||
__api_key_check(app, flask_request, __language())
|
__api_key_check(app, flask_request, __language())
|
||||||
try:
|
try:
|
||||||
host = __get_value(flask_request, "host")
|
host = __get_value(flask_request, "host")
|
||||||
|
|
@ -195,6 +319,12 @@ def __get_logs_html():
|
||||||
|
|
||||||
@app.route("/logs/get_json", methods=["GET"])
|
@app.route("/logs/get_json", methods=["GET"])
|
||||||
def __get_logs():
|
def __get_logs():
|
||||||
|
"""
|
||||||
|
get host's logs through the API in JSON type
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
an array with JSON events
|
||||||
|
"""
|
||||||
__api_key_check(app, flask_request, __language())
|
__api_key_check(app, flask_request, __language())
|
||||||
try:
|
try:
|
||||||
host = __get_value(flask_request, "host")
|
host = __get_value(flask_request, "host")
|
||||||
|
|
@ -205,6 +335,12 @@ def __get_logs():
|
||||||
|
|
||||||
@app.route("/logs/search", methods=["GET"])
|
@app.route("/logs/search", methods=["GET"])
|
||||||
def ___go_for_search_logs():
|
def ___go_for_search_logs():
|
||||||
|
"""
|
||||||
|
search in all events
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
an array with JSON events
|
||||||
|
"""
|
||||||
__api_key_check(app, flask_request, __language())
|
__api_key_check(app, flask_request, __language())
|
||||||
try:
|
try:
|
||||||
page = int(__get_value(flask_request, "page"))
|
page = int(__get_value(flask_request, "page"))
|
||||||
|
|
@ -219,6 +355,20 @@ def ___go_for_search_logs():
|
||||||
|
|
||||||
def __process_it(api_host, api_port, api_debug_mode, api_access_key, api_client_white_list,
|
def __process_it(api_host, api_port, api_debug_mode, api_access_key, api_client_white_list,
|
||||||
api_client_white_list_ips, api_access_log, api_access_log_filename, language):
|
api_client_white_list_ips, api_access_log, api_access_log_filename, language):
|
||||||
|
"""
|
||||||
|
a function to run flask in a subprocess to make kill signal in a better way!
|
||||||
|
|
||||||
|
Args:
|
||||||
|
api_host: host/IP to bind address
|
||||||
|
api_port: bind port
|
||||||
|
api_debug_mode: debug mode flag
|
||||||
|
api_access_key: API access key
|
||||||
|
api_client_white_list: clients while list flag
|
||||||
|
api_client_white_list_ips: clients white list IPs
|
||||||
|
api_access_log: access log flag
|
||||||
|
api_access_log_filename: access log filename
|
||||||
|
language: language
|
||||||
|
"""
|
||||||
app.config["OWASP_NETTACKER_CONFIG"] = {
|
app.config["OWASP_NETTACKER_CONFIG"] = {
|
||||||
"api_access_key": api_access_key,
|
"api_access_key": api_access_key,
|
||||||
"api_client_white_list": api_client_white_list,
|
"api_client_white_list": api_client_white_list,
|
||||||
|
|
@ -232,6 +382,20 @@ def __process_it(api_host, api_port, api_debug_mode, api_access_key, api_client_
|
||||||
|
|
||||||
def _start_api(api_host, api_port, api_debug_mode, api_access_key, api_client_white_list,
|
def _start_api(api_host, api_port, api_debug_mode, api_access_key, api_client_white_list,
|
||||||
api_client_white_list_ips, api_access_log, api_access_log_filename, language):
|
api_client_white_list_ips, api_access_log, api_access_log_filename, language):
|
||||||
|
"""
|
||||||
|
entry point to run the API through the flask
|
||||||
|
|
||||||
|
Args:
|
||||||
|
api_host: host/IP to bind address
|
||||||
|
api_port: bind port
|
||||||
|
api_debug_mode: debug mode
|
||||||
|
api_access_key: API access key
|
||||||
|
api_client_white_list: clients while list flag
|
||||||
|
api_client_white_list_ips: clients white list IPs
|
||||||
|
api_access_log: access log flag
|
||||||
|
api_access_log_filename: access log filename
|
||||||
|
language: language
|
||||||
|
"""
|
||||||
# Starting the API
|
# Starting the API
|
||||||
write_to_api_console(messages(language, 156).format(api_access_key))
|
write_to_api_console(messages(language, 156).format(api_access_key))
|
||||||
p = multiprocessing.Process(target=__process_it,
|
p = multiprocessing.Process(target=__process_it,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
OWASP Nettacker API Files
|
||||||
|
=========================
|
||||||
|
|
||||||
|
OWASP Nettacker API files are stored in here.
|
||||||
|
|
||||||
|
* `__database.py` contains database interaction functions
|
||||||
|
* `engine.py` is entry point of API and main functions
|
||||||
|
* `api_core.py` has core functions
|
||||||
|
* `__start_scan.py` run new scans
|
||||||
|
* `database.sqlite3` an empty API database for sample, its copy to `~/.owasp-nettacker/database.sqlite3` and stores data i there.
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
OWASP Nettacker core functions
|
||||||
|
==============================
|
||||||
|
|
||||||
|
OWASP Nettacker core functions are stored in here.
|
||||||
|
|
||||||
|
* `_die.py` exit functions
|
||||||
|
* `_time.py` time functions
|
||||||
|
* `alert.py` user alerts and printing functions
|
||||||
|
* `args_loader.py` ARGV commands and apply rules
|
||||||
|
* `attack.py` start new attacks and multi-processing managements
|
||||||
|
* `color.py` color founds for windows and linux/mac.
|
||||||
|
* `compatible.py` compatibility functions
|
||||||
|
* `config.py` user configs (could be modify by user)
|
||||||
|
* `config_builder.py` core static configs (same as user configs but should not be change by users)
|
||||||
|
* `get_input.py` get inputs from users functions
|
||||||
|
* `ip.py` IPv4 and IPv6 functions
|
||||||
|
* `load_modules` load modules, requirements, paths functions
|
||||||
|
* `log.py` log the scans and generate reports
|
||||||
|
* `parse.py` parse the ARGV and pass it
|
||||||
|
* `targets.py` process, calculate and count targets
|
||||||
|
* `update.py` updates functions of the framework
|
||||||
|
* `wizard.py` wizard mode for the framework
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
OWASP Nettacker Libraries and Modules
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
OWASP Nettacker modules and libraries are located in here
|
||||||
|
|
||||||
|
* `argparse` argparse fixed library for unicode
|
||||||
|
* `brute` contains brute force types modules
|
||||||
|
* `graph` graph modules of the framework
|
||||||
|
* `html_log` HTML log contents
|
||||||
|
* `icmp` ICMP library
|
||||||
|
* `language` contains messages in several languages
|
||||||
|
* `scan` contains scan types modules
|
||||||
|
* `vuln` contains vulnerability types modules
|
||||||
|
* `socks_resolver` resolve address by socks proxy
|
||||||
|
|
@ -1 +1,7 @@
|
||||||
Script files are located in here
|
OWASP Nettacker Scripts
|
||||||
|
=======================
|
||||||
|
Script files are located in here.
|
||||||
|
|
||||||
|
* `__travis_test__.py` test the framework through the TravisCI
|
||||||
|
* `nettacker` run OWASP Nettacker through the terminal
|
||||||
|
* `nettacker.bat` run OWASP Nettacker throough the Windows CMD
|
||||||
12
setup.py
12
setup.py
|
|
@ -8,11 +8,15 @@ from setuptools import find_packages
|
||||||
|
|
||||||
|
|
||||||
def package_files(directory):
|
def package_files(directory):
|
||||||
'''
|
"""
|
||||||
This function was created to crawl the directory and find files (none python files) using os.walk
|
This function was created to crawl the directory and find files (none python files) using os.walk
|
||||||
:param directory: path to crawl
|
|
||||||
:return: list of package files in an array
|
Args:
|
||||||
'''
|
directory: path to crawl
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list of package files in an array
|
||||||
|
"""
|
||||||
paths = []
|
paths = []
|
||||||
for (path, directories, filenames) in os.walk(directory):
|
for (path, directories, filenames) in os.walk(directory):
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
|
|
|
||||||
|
|
@ -1 +1,5 @@
|
||||||
Web UI files are located in here
|
OWASP Nettacker WebUI
|
||||||
|
=====================
|
||||||
|
Web UI files are located in here.
|
||||||
|
|
||||||
|
* `static` static files for web UI
|
||||||
Loading…
Reference in New Issue