Skip to content

Commit

Permalink
New Faraday modifications:
Browse files Browse the repository at this point in the history
Notifications: Updating objets on faraday now results in a beautiful
notification in the QT ui.

Performance: Enhacing performance when lots of workspaces are available.
We now load each workspace whe it's needed instead of loading ahead the
full workspace list.

UI: Workspace split, now you can select the workspace to visualize. We
are now using bootstrap.

API: New operations on the Rest API (this is just for the following UI
modifications). Vulnerability update and delete operations.
  • Loading branch information
dioh committed Jun 6, 2014
2 parents 9dfa9ad + f9d068d commit e616bdb
Show file tree
Hide file tree
Showing 51 changed files with 1,972 additions and 622 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,9 @@ nosetests.xml
.mr.developer.cfg
.project
.pydevproject

# ui_mranea
lib-ubuntu13-10-i686.tgz
lib-ubuntu13-10-i686/
views/reports/_attachments/reports/push.sh
views/upload
Empty file added apis/__init__.py
Empty file.
Empty file added apis/rest/__init__.py
Empty file.
188 changes: 137 additions & 51 deletions plugins/api.py → apis/rest/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@

from plugins.core import PluginControllerForApi
from managers.all import CommandManager
from model.visitor import VulnsLookupVisitor

import utils.logs as logger


_plugin_controller_api = None
Expand All @@ -37,59 +40,38 @@ def stopServer():
IOLoop.instance().stop()


def startPluginControllerAPI(plugin_manager):
global _plugin_controller_api
def startAPIs(plugin_manager, model_controller):
global _rest_controllers
global _http_server
if _plugin_controller_api is None:
#TODO: load API configuration from config file
hostname = "localhost"
port = 9977
_plugin_controller_api = PluginControllerAPI(plugin_manager,
hostname,
port)
if _http_server is None:
_http_server = HTTPServer(WSGIContainer(_plugin_controller_api.getApp()))
_http_server.listen(port)
logging.getLogger("tornado.access").addHandler(logging.NullHandler())
logging.getLogger("tornado.access").propagate = False
threading.Thread(target=startServer).start()


def stopPluginControllerAPI():
stopServer()
_rest_controllers = [PluginControllerAPI(plugin_manager), ModelControllerAPI(model_controller)]
#TODO: load API configuration from config file
hostname = "localhost"
port = 9977
app = Flask('APISController')

_http_server = HTTPServer(WSGIContainer(app))
_http_server.listen(port)

class PluginControllerAPI(object):
def __init__(self, plugin_manager, hostname, port):
self.plugin_controller = PluginControllerForApi("PluginController", plugin_manager.getPlugins(), CommandManager())
self.app = Flask(__name__.split('.')[0])
self.addRoutes()
self.hostname = hostname
self.port = port
#self.api = Api(self.app)
routes = [r for c in _rest_controllers for r in c.getRoutes()]

def getApp(self):
return self.app
for route in routes:
app.add_url_rule(route.path, view_func=route.view_func, methods=route.methods)

#def run(self):
# self.app.run(host=self.hostname, port=self.port)
logging.getLogger("tornado.access").addHandler(logger.getLogger(app))
logging.getLogger("tornado.access").propagate = False
threading.Thread(target=startServer).start()

def stopAPIs():
stopServer()

def addRoutes(self):
self.app.add_url_rule('/cmd/input',
view_func=self.postCmdInput,
methods=['POST'])
self.app.add_url_rule('/cmd/output',
view_func=self.postCmdOutput,
methods=['POST'])
self.app.add_url_rule('/cmd/active-plugins',
view_func=self.clearActivePlugins,
methods=['DELETE'])

def startAPI(self):
pass
class RESTApi(object):
""" Abstract class for REST Controllers
All REST Controllers should extend this class
in order to get published"""

def stopAPI(self):
pass
def getRoutes(self):
raise NotImplementedError('Abstract Class')

def badRequest(self, message):
error = 400
Expand All @@ -101,16 +83,112 @@ def noContent(self, message):
return jsonify(code=code,
message=message), code

def pluginAvailable(self, new_cmd, output_file):
def ok(self, message):
code = 200
return jsonify(code=code,
cmd=new_cmd,
custom_output_file=output_file)
message=message)

def ok(self, message):
class ModelControllerAPI(RESTApi):
def __init__(self, model_controller):
self.controller = model_controller

def getRoutes(self):
routes = []
routes.append(Route(path='/model/edit/vulns',
view_func=self.postEditVulns,
methods=['POST']))

routes.append(Route(path='/model/del/vulns',
view_func=self.deleteVuln,
methods=['DELETE']))
return routes


return host

def deleteVuln(self):
json_data = request.get_json()
# validate mandatory:
if not 'vulnid' in json_data:
return self.badRequest("vulid is mandatory")
if not 'hostid' in json_data:
return self.badRequest("hostid is mandatory")

vulnid = json_data['vulnid']
hostid = json_data['hostid']

host = self.controller.getHost(hostid)
if not host:
return self.badRequest("no plugin available for cmd")

visitor = VulnsLookupVisitor(vulnid)
host.accept(visitor)

if not visitor.vulns:
return self.noContent('No vuls matched criteria')

# forward to controller
for vuln, parents in zip(visitor.vulns, visitor.parents):
last_parent = parents[0]
self.controller.delVulnSYNC(last_parent, vuln.getID())

return self.ok("output successfully sent to plugin")


def postEditVulns(self):
json_data = request.get_json()
# validate mandatory:
if not 'vulnid' in json_data:
return self.badRequest("vulid is mandatory")
if not 'hostid' in json_data:
return self.badRequest("hostid is mandatory")

vulnid = json_data['vulnid']
hostid = json_data['hostid']

host = self.controller.getHost(hostid)
if not host:
return self.badRequest("no plugin available for cmd")

visitor = VulnsLookupVisitor(vulnid)
host.accept(visitor)

if not visitor.vulns:
return self.noContent('No vuls matched criteria')

name = json_data.get('name', None)
desc = json_data.get('desc', None)
severity = json_data.get('severity', None)
refs = json_data.get('refs', None)

# forward to controller
for vuln in visitor.vulns:
self.controller.editVulnSYNC(vuln, name, desc, severity, refs)

return self.ok("output successfully sent to plugin")

class PluginControllerAPI(RESTApi):
def __init__(self, plugin_manager):
self.plugin_controller = PluginControllerForApi("PluginController", plugin_manager.getPlugins(), CommandManager())

def getRoutes(self):
routes = []
routes.append(Route(path='/cmd/input',
view_func=self.postCmdInput,
methods=['POST']))
routes.append(Route(path='/cmd/output',
view_func=self.postCmdOutput,
methods=['POST']))
routes.append(Route(path='/cmd/active-plugins',
view_func=self.clearActivePlugins,
methods=['DELETE']))
return routes

def pluginAvailable(self, new_cmd, output_file):
code = 200
return jsonify(code=code,
message=message)
cmd=new_cmd,
custom_output_file=output_file)

def postCmdInput(self):
json_data = request.get_json()
Expand Down Expand Up @@ -179,4 +257,12 @@ def send_output(self, cmd, output_file):
headers=self.headers)
if response.status_code != 200:
return False
return True
return True


class Route(object):
""" Route class, abstracts information about:
path, handler and methods """
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
13 changes: 13 additions & 0 deletions bin/getAllIpsInterfaces.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
Faraday Penetration Test IDE - Community Version
Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
See the file 'doc/LICENSE' for the license information
'''

for host in api.__model_controller.getAllHosts():
if len(host.getAllInterfaces()) > 1:
print host.name
45 changes: 45 additions & 0 deletions bin/getAllTelnet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
Faraday Penetration Test IDE - Community Version
Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
See the file 'doc/LICENSE' for the license information
'''
webs={}
for host in api.__model_controller.getAllHosts():

for i in host.getAllInterfaces():
for s in i.getAllServices():
for p in s.getPorts():
if str(p) == '23':
webs[host.name]=1

for k,v in webs.iteritems():
print "hydra -l '' -p 'telecom' -w 10 telnet://"+k+":23"





# 200.61.47.65
# 200.45.69.29
# 200.61.47.217
# 200.61.47.121
# 200.45.69.17
# 200.61.47.129
# 200.61.47.113
# 200.61.47.9
# 190.221.164.65
# 200.61.47.146
# 186.153.146.227
# 200.61.47.177
# 200.61.47.17
# 200.61.47.33
# 200.45.69.30
# 200.61.47.179
# 200.61.47.233
# 200.61.47.41
# 200.61.47.221
# 200.61.47.220
46 changes: 46 additions & 0 deletions bin/getAllVnc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
Faraday Penetration Test IDE - Community Version
Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
See the file 'doc/LICENSE' for the license information
'''
webs={}
for host in api.__model_controller.getAllHosts():

for i in host.getAllInterfaces():
for s in i.getAllServices():
for p in s.getPorts():
if str(p) == '5900':
webs[host.name]=1

for k,v in webs.iteritems():
print k
# print "hydra -l '' -p 'telecom' -w 10 telnet://"+k+":23"





# 200.61.47.65
# 200.45.69.29
# 200.61.47.217
# 200.61.47.121
# 200.45.69.17
# 200.61.47.129
# 200.61.47.113
# 200.61.47.9
# 190.221.164.65
# 200.61.47.146
# 186.153.146.227
# 200.61.47.177
# 200.61.47.17
# 200.61.47.33
# 200.45.69.30
# 200.61.47.179
# 200.61.47.233
# 200.61.47.41
# 200.61.47.221
# 200.61.47.220
7 changes: 7 additions & 0 deletions controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'''
Faraday Penetration Test IDE - Community Version
Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
See the file 'doc/LICENSE' for the license information
'''

23 changes: 23 additions & 0 deletions controllers/change.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'''
Faraday Penetration Test IDE - Community Version
Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
See the file 'doc/LICENSE' for the license information
'''

import model.guiapi


class ChangeController(object):
def __init__(self):
self.workspace = None

def setWorkspace(self, workspace):
self.workspace = workspace

def loadChanges(self, changes):
# first, we notify the changes
for change in changes:
model.guiapi.notification_center.changeFromInstance(change)
# then we reload the workspace
self.workspace.load()
3 changes: 2 additions & 1 deletion faraday
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ if [ ! -d $faraday_user/zsh ]; then
mkdir -p "$faraday_user/zsh"
fi
if [ -e $HOME/.zshrc ]; then
cp -a $HOME/.zshrc $faraday_user/zsh/
cp -a -L $HOME/.zshrc $faraday_user/zsh/
else
touch $HOME/.zshrc $faraday_user/zsh/.zshrc
fi
sed -i '1iZDOTDIR=$OLDZDOTDIR' $faraday_user/zsh/.zshrc
echo "source $faraday_user/zsh/faraday.zsh" >> $faraday_user/zsh/.zshrc
cp $faraday_base/zsh/faraday.zsh $faraday_user/zsh/
cp $faraday_base/zsh/plugin_controller_client.py $faraday_user/zsh/
Expand Down
4 changes: 3 additions & 1 deletion faraday-terminal.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@
###

#ZDOTDIR="~/.faraday/zsh/" /bin/zsh
ZDOTDIR="$HOME/.faraday/zsh/" /bin/zsh
FARADAYZDOTDIR="$HOME/.faraday/zsh/"
OLDZDOTDIR=$ZDOTDIR
ZDOTDIR=$FARADAYZDOTDIR /bin/zsh
#source ~/.faraday/zsh/.zshrc
Loading

0 comments on commit e616bdb

Please sign in to comment.