Skip to content

Commit e616bdb

Browse files
committed
New Faraday modifications:
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.
2 parents 9dfa9ad + f9d068d commit e616bdb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1972
-622
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,9 @@ nosetests.xml
3434
.mr.developer.cfg
3535
.project
3636
.pydevproject
37+
38+
# ui_mranea
39+
lib-ubuntu13-10-i686.tgz
40+
lib-ubuntu13-10-i686/
41+
views/reports/_attachments/reports/push.sh
42+
views/upload

apis/__init__.py

Whitespace-only changes.

apis/rest/__init__.py

Whitespace-only changes.

plugins/api.py renamed to apis/rest/api.py

Lines changed: 137 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919

2020
from plugins.core import PluginControllerForApi
2121
from managers.all import CommandManager
22+
from model.visitor import VulnsLookupVisitor
23+
24+
import utils.logs as logger
2225

2326

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

3942

40-
def startPluginControllerAPI(plugin_manager):
41-
global _plugin_controller_api
43+
def startAPIs(plugin_manager, model_controller):
44+
global _rest_controllers
4245
global _http_server
43-
if _plugin_controller_api is None:
44-
#TODO: load API configuration from config file
45-
hostname = "localhost"
46-
port = 9977
47-
_plugin_controller_api = PluginControllerAPI(plugin_manager,
48-
hostname,
49-
port)
50-
if _http_server is None:
51-
_http_server = HTTPServer(WSGIContainer(_plugin_controller_api.getApp()))
52-
_http_server.listen(port)
53-
logging.getLogger("tornado.access").addHandler(logging.NullHandler())
54-
logging.getLogger("tornado.access").propagate = False
55-
threading.Thread(target=startServer).start()
56-
57-
58-
def stopPluginControllerAPI():
59-
stopServer()
46+
_rest_controllers = [PluginControllerAPI(plugin_manager), ModelControllerAPI(model_controller)]
47+
#TODO: load API configuration from config file
48+
hostname = "localhost"
49+
port = 9977
50+
app = Flask('APISController')
6051

52+
_http_server = HTTPServer(WSGIContainer(app))
53+
_http_server.listen(port)
6154

62-
class PluginControllerAPI(object):
63-
def __init__(self, plugin_manager, hostname, port):
64-
self.plugin_controller = PluginControllerForApi("PluginController", plugin_manager.getPlugins(), CommandManager())
65-
self.app = Flask(__name__.split('.')[0])
66-
self.addRoutes()
67-
self.hostname = hostname
68-
self.port = port
69-
#self.api = Api(self.app)
55+
routes = [r for c in _rest_controllers for r in c.getRoutes()]
7056

71-
def getApp(self):
72-
return self.app
57+
for route in routes:
58+
app.add_url_rule(route.path, view_func=route.view_func, methods=route.methods)
7359

74-
#def run(self):
75-
# self.app.run(host=self.hostname, port=self.port)
60+
logging.getLogger("tornado.access").addHandler(logger.getLogger(app))
61+
logging.getLogger("tornado.access").propagate = False
62+
threading.Thread(target=startServer).start()
63+
64+
def stopAPIs():
65+
stopServer()
7666

77-
def addRoutes(self):
78-
self.app.add_url_rule('/cmd/input',
79-
view_func=self.postCmdInput,
80-
methods=['POST'])
81-
self.app.add_url_rule('/cmd/output',
82-
view_func=self.postCmdOutput,
83-
methods=['POST'])
84-
self.app.add_url_rule('/cmd/active-plugins',
85-
view_func=self.clearActivePlugins,
86-
methods=['DELETE'])
8767

88-
def startAPI(self):
89-
pass
68+
class RESTApi(object):
69+
""" Abstract class for REST Controllers
70+
All REST Controllers should extend this class
71+
in order to get published"""
9072

91-
def stopAPI(self):
92-
pass
73+
def getRoutes(self):
74+
raise NotImplementedError('Abstract Class')
9375

9476
def badRequest(self, message):
9577
error = 400
@@ -101,16 +83,112 @@ def noContent(self, message):
10183
return jsonify(code=code,
10284
message=message), code
10385

104-
def pluginAvailable(self, new_cmd, output_file):
86+
def ok(self, message):
10587
code = 200
10688
return jsonify(code=code,
107-
cmd=new_cmd,
108-
custom_output_file=output_file)
89+
message=message)
10990

110-
def ok(self, message):
91+
class ModelControllerAPI(RESTApi):
92+
def __init__(self, model_controller):
93+
self.controller = model_controller
94+
95+
def getRoutes(self):
96+
routes = []
97+
routes.append(Route(path='/model/edit/vulns',
98+
view_func=self.postEditVulns,
99+
methods=['POST']))
100+
101+
routes.append(Route(path='/model/del/vulns',
102+
view_func=self.deleteVuln,
103+
methods=['DELETE']))
104+
return routes
105+
106+
107+
return host
108+
109+
def deleteVuln(self):
110+
json_data = request.get_json()
111+
# validate mandatory:
112+
if not 'vulnid' in json_data:
113+
return self.badRequest("vulid is mandatory")
114+
if not 'hostid' in json_data:
115+
return self.badRequest("hostid is mandatory")
116+
117+
vulnid = json_data['vulnid']
118+
hostid = json_data['hostid']
119+
120+
host = self.controller.getHost(hostid)
121+
if not host:
122+
return self.badRequest("no plugin available for cmd")
123+
124+
visitor = VulnsLookupVisitor(vulnid)
125+
host.accept(visitor)
126+
127+
if not visitor.vulns:
128+
return self.noContent('No vuls matched criteria')
129+
130+
# forward to controller
131+
for vuln, parents in zip(visitor.vulns, visitor.parents):
132+
last_parent = parents[0]
133+
self.controller.delVulnSYNC(last_parent, vuln.getID())
134+
135+
return self.ok("output successfully sent to plugin")
136+
137+
138+
def postEditVulns(self):
139+
json_data = request.get_json()
140+
# validate mandatory:
141+
if not 'vulnid' in json_data:
142+
return self.badRequest("vulid is mandatory")
143+
if not 'hostid' in json_data:
144+
return self.badRequest("hostid is mandatory")
145+
146+
vulnid = json_data['vulnid']
147+
hostid = json_data['hostid']
148+
149+
host = self.controller.getHost(hostid)
150+
if not host:
151+
return self.badRequest("no plugin available for cmd")
152+
153+
visitor = VulnsLookupVisitor(vulnid)
154+
host.accept(visitor)
155+
156+
if not visitor.vulns:
157+
return self.noContent('No vuls matched criteria')
158+
159+
name = json_data.get('name', None)
160+
desc = json_data.get('desc', None)
161+
severity = json_data.get('severity', None)
162+
refs = json_data.get('refs', None)
163+
164+
# forward to controller
165+
for vuln in visitor.vulns:
166+
self.controller.editVulnSYNC(vuln, name, desc, severity, refs)
167+
168+
return self.ok("output successfully sent to plugin")
169+
170+
class PluginControllerAPI(RESTApi):
171+
def __init__(self, plugin_manager):
172+
self.plugin_controller = PluginControllerForApi("PluginController", plugin_manager.getPlugins(), CommandManager())
173+
174+
def getRoutes(self):
175+
routes = []
176+
routes.append(Route(path='/cmd/input',
177+
view_func=self.postCmdInput,
178+
methods=['POST']))
179+
routes.append(Route(path='/cmd/output',
180+
view_func=self.postCmdOutput,
181+
methods=['POST']))
182+
routes.append(Route(path='/cmd/active-plugins',
183+
view_func=self.clearActivePlugins,
184+
methods=['DELETE']))
185+
return routes
186+
187+
def pluginAvailable(self, new_cmd, output_file):
111188
code = 200
112189
return jsonify(code=code,
113-
message=message)
190+
cmd=new_cmd,
191+
custom_output_file=output_file)
114192

115193
def postCmdInput(self):
116194
json_data = request.get_json()
@@ -179,4 +257,12 @@ def send_output(self, cmd, output_file):
179257
headers=self.headers)
180258
if response.status_code != 200:
181259
return False
182-
return True
260+
return True
261+
262+
263+
class Route(object):
264+
""" Route class, abstracts information about:
265+
path, handler and methods """
266+
def __init__(self, **kwargs):
267+
for k, v in kwargs.items():
268+
setattr(self, k, v)

bin/getAllIpsInterfaces.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
'''
5+
Faraday Penetration Test IDE - Community Version
6+
Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
7+
See the file 'doc/LICENSE' for the license information
8+
9+
'''
10+
11+
for host in api.__model_controller.getAllHosts():
12+
if len(host.getAllInterfaces()) > 1:
13+
print host.name

bin/getAllTelnet.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
'''
5+
Faraday Penetration Test IDE - Community Version
6+
Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
7+
See the file 'doc/LICENSE' for the license information
8+
9+
'''
10+
webs={}
11+
for host in api.__model_controller.getAllHosts():
12+
13+
for i in host.getAllInterfaces():
14+
for s in i.getAllServices():
15+
for p in s.getPorts():
16+
if str(p) == '23':
17+
webs[host.name]=1
18+
19+
for k,v in webs.iteritems():
20+
print "hydra -l '' -p 'telecom' -w 10 telnet://"+k+":23"
21+
22+
23+
24+
25+
26+
# 200.61.47.65
27+
# 200.45.69.29
28+
# 200.61.47.217
29+
# 200.61.47.121
30+
# 200.45.69.17
31+
# 200.61.47.129
32+
# 200.61.47.113
33+
# 200.61.47.9
34+
# 190.221.164.65
35+
# 200.61.47.146
36+
# 186.153.146.227
37+
# 200.61.47.177
38+
# 200.61.47.17
39+
# 200.61.47.33
40+
# 200.45.69.30
41+
# 200.61.47.179
42+
# 200.61.47.233
43+
# 200.61.47.41
44+
# 200.61.47.221
45+
# 200.61.47.220

bin/getAllVnc.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
'''
5+
Faraday Penetration Test IDE - Community Version
6+
Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
7+
See the file 'doc/LICENSE' for the license information
8+
9+
'''
10+
webs={}
11+
for host in api.__model_controller.getAllHosts():
12+
13+
for i in host.getAllInterfaces():
14+
for s in i.getAllServices():
15+
for p in s.getPorts():
16+
if str(p) == '5900':
17+
webs[host.name]=1
18+
19+
for k,v in webs.iteritems():
20+
print k
21+
# print "hydra -l '' -p 'telecom' -w 10 telnet://"+k+":23"
22+
23+
24+
25+
26+
27+
# 200.61.47.65
28+
# 200.45.69.29
29+
# 200.61.47.217
30+
# 200.61.47.121
31+
# 200.45.69.17
32+
# 200.61.47.129
33+
# 200.61.47.113
34+
# 200.61.47.9
35+
# 190.221.164.65
36+
# 200.61.47.146
37+
# 186.153.146.227
38+
# 200.61.47.177
39+
# 200.61.47.17
40+
# 200.61.47.33
41+
# 200.45.69.30
42+
# 200.61.47.179
43+
# 200.61.47.233
44+
# 200.61.47.41
45+
# 200.61.47.221
46+
# 200.61.47.220

controllers/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'''
2+
Faraday Penetration Test IDE - Community Version
3+
Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
4+
See the file 'doc/LICENSE' for the license information
5+
6+
'''
7+

controllers/change.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'''
2+
Faraday Penetration Test IDE - Community Version
3+
Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
4+
See the file 'doc/LICENSE' for the license information
5+
6+
'''
7+
8+
import model.guiapi
9+
10+
11+
class ChangeController(object):
12+
def __init__(self):
13+
self.workspace = None
14+
15+
def setWorkspace(self, workspace):
16+
self.workspace = workspace
17+
18+
def loadChanges(self, changes):
19+
# first, we notify the changes
20+
for change in changes:
21+
model.guiapi.notification_center.changeFromInstance(change)
22+
# then we reload the workspace
23+
self.workspace.load()

faraday

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,11 @@ if [ ! -d $faraday_user/zsh ]; then
8686
mkdir -p "$faraday_user/zsh"
8787
fi
8888
if [ -e $HOME/.zshrc ]; then
89-
cp -a $HOME/.zshrc $faraday_user/zsh/
89+
cp -a -L $HOME/.zshrc $faraday_user/zsh/
9090
else
9191
touch $HOME/.zshrc $faraday_user/zsh/.zshrc
9292
fi
93+
sed -i '1iZDOTDIR=$OLDZDOTDIR' $faraday_user/zsh/.zshrc
9394
echo "source $faraday_user/zsh/faraday.zsh" >> $faraday_user/zsh/.zshrc
9495
cp $faraday_base/zsh/faraday.zsh $faraday_user/zsh/
9596
cp $faraday_base/zsh/plugin_controller_client.py $faraday_user/zsh/

0 commit comments

Comments
 (0)