Imported Upstream version 1.0.13
Sophie Brun
8 years ago
8 | 8 | |
9 | 9 | New features in the latest update |
10 | 10 | ===================================== |
11 | ||
12 | Aug 19, 2015: | |
13 | --- | |
14 | * Exported CSV contains filters and columns from Status Report in WEB UI | |
15 | * Vulnerability counter on Status Report in WEB UI | |
16 | * Added quick vuln edit and delete in WEB UI | |
17 | * Expanded Unit Tests for WEB UI | |
18 | * XML Cleaner | |
19 | * Kali 2.0 support | |
20 | * Improve plugins running status log (Adding log information on report importing) | |
21 | * Clean dev log on plugins | |
22 | * w3af plugin refactoring | |
23 | * Fix Debian 7/8.1 install support | |
24 | ||
11 | 25 | |
12 | 26 | Aug 05, 2015: |
13 | 27 | --- |
0 | #!/usr/bin/env python2.7 | |
1 | ''' | |
2 | Faraday Penetration Test IDE | |
3 | Copyright (C) 2014 Infobyte LLC (http://www.infobytesec.com/) | |
4 | See the file 'doc/LICENSE' for the license information | |
5 | ||
6 | ''' | |
7 | import argparse | |
8 | from bs4 import BeautifulSoup | |
9 | ||
10 | def main(): | |
11 | parser = argparse.ArgumentParser(prog='cleanXML', epilog="Example: ./%(prog)s.py") | |
12 | ||
13 | parser.add_argument('-i', '--input', action='store', type=str, | |
14 | dest='infile', help='XML File to read from', | |
15 | required=True) | |
16 | parser.add_argument('-o', '--output', action='store', type=str, | |
17 | dest='outfile', help='Filename to write output', | |
18 | default="clean.xml") | |
19 | ||
20 | args = parser.parse_args() | |
21 | ||
22 | xml = open(args.infile, 'r') | |
23 | soup = BeautifulSoup(xml.read(), 'xml') | |
24 | ||
25 | out = open(args.outfile, 'w') | |
26 | out.write(soup.encode('utf-8')) | |
27 | out.flush() | |
28 | out.close() | |
29 | ||
30 | xml.close() | |
31 | ||
32 | if __name__ == "__main__": | |
33 | main() |
0 | ''' | |
1 | Faraday Penetration Test IDE | |
2 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
3 | See the file 'doc/LICENSE' for the license information | |
4 | ||
5 | ''' | |
6 | import sys, os, string, ast, json | |
7 | ||
8 | try: | |
9 | import xml.etree.cElementTree as ET | |
10 | from xml.etree.cElementTree import Element, ElementTree | |
11 | except ImportError: | |
12 | import xml.etree.ElementTree as ET | |
13 | from xml.etree.ElementTree import Element, ElementTree | |
14 | ||
15 | the_config = None | |
16 | ||
17 | CONST_API_CON_INFO = "api_con_info" | |
18 | CONST_API_CON_INFO_HOST = "api_con_info_host" | |
19 | CONST_API_CON_INFO_PORT = "api_con_info_port" | |
20 | CONST_API_RESTFUL_CON_INFO_PORT = "api_restful_con_info_port" | |
21 | CONST_APPNAME = "appname" | |
22 | CONST_AUTH = "auth" | |
23 | CONST_AUTO_SHARE_WORKSPACE = "auto_share_workspace" | |
24 | CONST_CONFIG_PATH = "config_path" | |
25 | CONST_DATA_PATH = "data_path" | |
26 | CONST_DEBUG_STATUS = "debug_status" | |
27 | CONST_DEFAULT_CATEGORY = "default_category" | |
28 | CONST_DEFAULT_TEMP_PATH = "default_temp_path" | |
29 | CONST_FONT = "font" | |
30 | CONST_HOME_PATH = "home_path" | |
31 | CONST_HOST_TREE_TOGGLE = "host_tree_toggle" | |
32 | CONST_HSTACTIONS_PATH = "hstactions_path" | |
33 | CONST_ICONS_PATH = "icons_path" | |
34 | CONST_IMAGE_PATH = "image_path" | |
35 | CONST_LOG_CONSOLE_TOGGLE = "log_console_toggle" | |
36 | CONST_NETWORK_LOCATION = "network_location" | |
37 | CONST_PERSISTENCE_PATH = "persistence_path" | |
38 | CONST_PERSPECTIVE_VIEW = "perspective_view" | |
39 | CONST_REPO_PASSWORD = "repo_password" | |
40 | CONST_COUCH_URI = "couch_uri" | |
41 | CONST_COUCH_REPLICS = "couch_replics" | |
42 | CONST_COUCH_ISREPLICATED = "couch_is_replicated" | |
43 | CONST_REPO_URL = "repo_url" | |
44 | CONST_REPO_USER = "repo_user" | |
45 | CONST_REPORT_PATH = "report_path" | |
46 | CONST_SHELL_MAXIMIZED = "shell_maximized" | |
47 | CONST_VERSION = "version" | |
48 | CONST_UPDATEURI = "updates_uri" | |
49 | CONST_TKTURI = "tickets_uri" | |
50 | CONST_TKTAPIPARAMS = "tickets_api" | |
51 | CONST_TKTTEMPLATE = "tickets_template" | |
52 | ||
53 | CONST_LAST_WORKSPACE = "last_workspace" | |
54 | CONST_PLUGIN_SETTINGS = "plugin_settings" | |
55 | ||
56 | ||
57 | DEFAULT_XML = os.path.dirname(__file__) + "/default.xml" | |
58 | ||
59 | ||
60 | class Configuration: | |
61 | ||
62 | def __init__(self, xml_file=DEFAULT_XML): | |
63 | """ Initializer that handles a configuration automagically. """ | |
64 | ||
65 | self.filepath = xml_file | |
66 | ||
67 | if self._isConfig(): self._getConfig() | |
68 | ||
69 | def _isConfig(self): | |
70 | """ Checks whether the given file exists and belongs | |
71 | to faraday's configuration syntax""" | |
72 | ||
73 | root = f = None | |
74 | ||
75 | try: | |
76 | f = open(self.filepath, 'rb') | |
77 | try: | |
78 | for event, elem in ET.iterparse(f, ('start', )): | |
79 | root = elem.tag | |
80 | break | |
81 | except SyntaxError, err: | |
82 | print "Not an xml file.\n %s" % (err) | |
83 | return False | |
84 | ||
85 | except IOError, err: | |
86 | print "Error while opening file.\n%s. %s" % (err, self.filepath) | |
87 | return False | |
88 | ||
89 | finally: | |
90 | if f: f.close() | |
91 | ||
92 | return (root == "faraday") | |
93 | ||
94 | def _getTree(self): | |
95 | """ Returns an XML tree read from file. """ | |
96 | ||
97 | f = open(self.filepath) | |
98 | try: | |
99 | tree = ET.fromstring(f.read()) | |
100 | except SyntaxError, err: | |
101 | print "SyntaxError: %s. %s" % (err, self.filepath) | |
102 | return None | |
103 | return tree | |
104 | ||
105 | def _getValue(self, tree, var, default = None): | |
106 | """ Returns generic value from a variable on an XML tree. """ | |
107 | ||
108 | elem = tree.findall(var) | |
109 | if not(elem): | |
110 | return default | |
111 | ||
112 | return elem[0].text | |
113 | ||
114 | def _getConfig(self): | |
115 | """ Gathers all configuration data from self.filepath, and | |
116 | completes private attributes with such information. """ | |
117 | ||
118 | tree = self._getTree() | |
119 | if tree: | |
120 | self._api_con_info_host = self._getValue(tree, CONST_API_CON_INFO_HOST) | |
121 | self._api_con_info_port = self._getValue(tree, CONST_API_CON_INFO_PORT) | |
122 | self._api_restful_con_info_port = self._getValue(tree, CONST_API_RESTFUL_CON_INFO_PORT) | |
123 | self._api_con_info = self._getValue(tree, CONST_API_CON_INFO) | |
124 | self._appname = self._getValue(tree, CONST_APPNAME) | |
125 | self._auth = self._getValue(tree, CONST_AUTH) | |
126 | self._auto_share_workspace = self._getValue(tree, CONST_AUTO_SHARE_WORKSPACE) | |
127 | self._config_path = self._getValue(tree, CONST_CONFIG_PATH) | |
128 | self._data_path = self._getValue(tree, CONST_DATA_PATH) | |
129 | self._debug_status = self._getValue(tree, CONST_DEBUG_STATUS) | |
130 | self._default_category = self._getValue(tree, CONST_DEFAULT_CATEGORY) | |
131 | self._default_temp_path = self._getValue(tree, CONST_DEFAULT_TEMP_PATH) | |
132 | self._font = self._getValue(tree, CONST_FONT) | |
133 | self._home_path = self._getValue(tree, CONST_HOME_PATH) | |
134 | self._host_tree_toggle = self._getValue(tree, CONST_HOST_TREE_TOGGLE) | |
135 | self._hsactions_path = self._getValue(tree, CONST_HSTACTIONS_PATH) | |
136 | self._icons_path = self._getValue(tree, CONST_ICONS_PATH) | |
137 | self._image_path = self._getValue(tree, CONST_IMAGE_PATH) | |
138 | self._log_console_toggle = self._getValue(tree, CONST_LOG_CONSOLE_TOGGLE) | |
139 | self._network_location = self._getValue(tree, CONST_NETWORK_LOCATION) | |
140 | self._persistence_path = self._getValue(tree, CONST_PERSISTENCE_PATH) | |
141 | self._perspective_view = self._getValue(tree, CONST_PERSISTENCE_PATH) | |
142 | self._repo_password = self._getValue(tree, CONST_REPO_PASSWORD) | |
143 | self._couch_uri = self._getValue(tree, CONST_COUCH_URI, default = "") | |
144 | self._couch_replics = self._getValue(tree, CONST_COUCH_REPLICS, default = "") | |
145 | self._couch_is_replicated = bool(self._getValue(tree, CONST_COUCH_ISREPLICATED, default = False)) | |
146 | self._repo_url = self._getValue(tree, CONST_REPO_URL) | |
147 | self._repo_user = self._getValue(tree, CONST_REPO_USER) | |
148 | self._report_path = self._getValue(tree, CONST_REPORT_PATH) | |
149 | self._shell_maximized = self._getValue(tree, CONST_SHELL_MAXIMIZED) | |
150 | self._version = self._getValue(tree, CONST_VERSION) | |
151 | self._last_workspace = self._getValue(tree, CONST_LAST_WORKSPACE, default = "untitled") | |
152 | self._plugin_settings = json.loads(self._getValue(tree, CONST_PLUGIN_SETTINGS, default = "{}")) | |
153 | ||
154 | self._updates_uri = self._getValue(tree, CONST_UPDATEURI, default = "https://www.faradaysec.com/scripts/updates.php") | |
155 | self._tkts_uri = self._getValue(tree, CONST_TKTURI,default = "https://www.faradaysec.com/scripts/listener.php") | |
156 | self._tkt_api_params = self._getValue(tree, CONST_TKTAPIPARAMS,default ="{}") | |
157 | self._tkt_template = self._getValue(tree, CONST_TKTTEMPLATE,default ="{}") | |
158 | ||
159 | ||
160 | ||
161 | def getApiConInfo(self): | |
162 | if str(self._api_con_info_host) == "None" or str(self._api_con_info_port) == "None": | |
163 | return None | |
164 | return self._api_con_info_host, int(self._api_con_info_port) | |
165 | ||
166 | def getApiRestfulConInfo(self): | |
167 | if str(self._api_con_info_host) == "None" or str(self._api_restful_con_info_port) == "None": | |
168 | return None | |
169 | return self._api_con_info_host, int(self._api_restful_con_info_port) | |
170 | ||
171 | def getApiConInfoHost(self): | |
172 | return self._api_con_info_host | |
173 | ||
174 | def getApiConInfoPort(self): | |
175 | return self._api_con_info_port | |
176 | ||
177 | def getApiRestfulConInfoPort(self): | |
178 | return self._api_restful_con_info_port | |
179 | ||
180 | def getAppname(self): | |
181 | return self._appname | |
182 | ||
183 | def getAuth(self): | |
184 | return self._auth | |
185 | ||
186 | def getAutoShareWorkspace(self): | |
187 | return self._auto_share_workspace | |
188 | ||
189 | def getConfigPath(self): | |
190 | return os.path.expanduser(self._config_path) | |
191 | ||
192 | def getDataPath(self): | |
193 | return os.path.expanduser(self._data_path) | |
194 | ||
195 | def getDebugStatus(self): | |
196 | return int(self._debug_status) | |
197 | ||
198 | def getDefaultCategory(self): | |
199 | return self._default_category | |
200 | ||
201 | def getDefaultTempPath(self): | |
202 | return os.path.expanduser(self._default_temp_path) | |
203 | ||
204 | def getFont(self): | |
205 | return self._font | |
206 | ||
207 | def getHomePath(self): | |
208 | return os.path.expanduser(self._home_path) | |
209 | ||
210 | def getHostTreeToggle(self): | |
211 | return self._host_tree_toggle | |
212 | ||
213 | def getHsactionsPath(self): | |
214 | return os.path.expanduser(self._hsactions_path) | |
215 | ||
216 | def getIconsPath(self): | |
217 | return os.path.expanduser(self._icons_path) | |
218 | ||
219 | def getImagePath(self): | |
220 | return os.path.expanduser(self._image_path) | |
221 | ||
222 | def getLogConsoleToggle(self): | |
223 | return self._log_console_toggle | |
224 | ||
225 | def getNetworkLocation(self): | |
226 | return self._network_location | |
227 | ||
228 | def getPersistencePath(self): | |
229 | return os.path.expanduser(self._persistence_path) | |
230 | ||
231 | def getPerspectiveView(self): | |
232 | return self._perspective_view | |
233 | ||
234 | def getCouchURI(self): | |
235 | if self._couch_uri and self._couch_uri.endswith('/'): | |
236 | return self._couch_uri[:-1] | |
237 | else: | |
238 | return self._couch_uri | |
239 | ||
240 | def getCouchReplics(self): | |
241 | return self._couch_replics | |
242 | ||
243 | def getCouchIsReplicated(self): | |
244 | return self._couch_is_replicated | |
245 | ||
246 | def getRepoPassword(self): | |
247 | return self._repo_password | |
248 | ||
249 | def getRepoUrl(self): | |
250 | return self._repo_url | |
251 | ||
252 | def getRepoUser(self): | |
253 | return self._repo_user | |
254 | ||
255 | def getReportPath(self): | |
256 | return os.path.expanduser(self._report_path) | |
257 | ||
258 | def getShellMaximized(self): | |
259 | return self._shell_maximized | |
260 | ||
261 | def getVersion(self): | |
262 | return self._version | |
263 | ||
264 | def getLastWorkspace(self): | |
265 | return self._last_workspace | |
266 | ||
267 | def getPluginSettings(self): | |
268 | return self._plugin_settings | |
269 | ||
270 | def getUpdatesUri(self): | |
271 | return self._updates_uri | |
272 | ||
273 | def getTktPostUri(self): | |
274 | return self._tkts_uri | |
275 | ||
276 | def getApiParams(self): | |
277 | return self._tkt_api_params | |
278 | ||
279 | def getTktTemplate(self): | |
280 | return self._tkt_template | |
281 | ||
282 | ||
283 | ||
284 | def setLastWorkspace(self, workspaceName): | |
285 | self._last_workspace = workspaceName | |
286 | ||
287 | def setApiConInfo(self, val1, val2): | |
288 | self._api_con_info = val1, val2 | |
289 | self.setApiConInfoHost(val1) | |
290 | self.setApiConInfoPort(val2) | |
291 | ||
292 | def setApiRestfulConInfo(self, val1, val2): | |
293 | self._api_con_info = val1, val2 | |
294 | self.setApiConInfoHost(val1) | |
295 | self.setApiRestfulConInfoPort(val2) | |
296 | ||
297 | def setApiConInfoHost(self, val): | |
298 | self._api_con_info_host = val | |
299 | ||
300 | def setApiConInfoPort(self, val): | |
301 | self._api_con_info_port = str(val) | |
302 | ||
303 | def setApiRestfulConInfoPort(self, val): | |
304 | self._api_restful_con_info_port = str(val) | |
305 | ||
306 | def setAppname(self, val): | |
307 | self._appname = val | |
308 | ||
309 | def setAuth(self, val): | |
310 | self._auth = val | |
311 | ||
312 | def setAutoShareWorkspace(self, val): | |
313 | self._auto_share_workspace = val | |
314 | ||
315 | def setConfigPath(self, val): | |
316 | self._config_path = val | |
317 | ||
318 | def setDataPath(self, val): | |
319 | self._data_path = val | |
320 | ||
321 | def setDebugStatus(self, val): | |
322 | self._debug_status = int(val) | |
323 | ||
324 | def setDefaultCategory(self, val): | |
325 | self._default_category = val | |
326 | ||
327 | def setDefaultTempPath(self, val): | |
328 | self._default_temp_path = val | |
329 | ||
330 | def setFont(self, val): | |
331 | self._font = val | |
332 | ||
333 | def setHomePath(self, val): | |
334 | self._home_path = val | |
335 | ||
336 | def setHostTreeToggle(self, val): | |
337 | self._host_tree_toggle = val | |
338 | ||
339 | def setHsactionsPath(self, val): | |
340 | self._hsactions_path = val | |
341 | ||
342 | def setIconsPath(self, val): | |
343 | self._icons_path = val | |
344 | ||
345 | def setImagePath(self, val): | |
346 | self._image_path = val | |
347 | ||
348 | def setLogConsoleToggle(self, val): | |
349 | self._log_console_toggle = val | |
350 | ||
351 | def setNetworkLocation(self, val): | |
352 | self._network_location = val | |
353 | ||
354 | def setPersistencePath(self, val): | |
355 | self._persistence_path = val | |
356 | ||
357 | def setPerspectiveView(self, val): | |
358 | self._perspective_view = val | |
359 | ||
360 | def setRepoPassword(self, val): | |
361 | self._repo_password = val | |
362 | ||
363 | def setRepoUrl(self, val): | |
364 | self._repo_url = val | |
365 | ||
366 | def setRepoUser(self, val): | |
367 | self._repo_user = val | |
368 | ||
369 | def setReportPath(self, val): | |
370 | self._report_path = val | |
371 | ||
372 | def setShellMaximized(self, val): | |
373 | self._shell_maximized = val | |
374 | ||
375 | def setVersion(self, val): | |
376 | self._version = val | |
377 | ||
378 | def setCouchUri(self, uri): | |
379 | self._couch_uri = uri | |
380 | ||
381 | def setCouchIsReplicated(self, is_it): | |
382 | self._couch_is_replicated = is_it | |
383 | ||
384 | def setCouchReplics(self, urls): | |
385 | self._couch_replics = urls | |
386 | ||
387 | def setPluginSettings(self, settings): | |
388 | self._plugin_settings = settings | |
389 | ||
390 | def indent(self, elem, level=0): | |
391 | """ Indents the tree to make a pretty view of it. """ | |
392 | ||
393 | i = "\n" + level*" " | |
394 | if len(elem): | |
395 | if not elem.text or not elem.text.strip(): | |
396 | elem.text = i + " " | |
397 | if not elem.tail or not elem.tail.strip(): | |
398 | elem.tail = i | |
399 | for elem in elem: | |
400 | self.indent(elem, level+1) | |
401 | if not elem.tail or not elem.tail.strip(): | |
402 | elem.tail = i | |
403 | else: | |
404 | if level and (not elem.tail or not elem.tail.strip()): | |
405 | elem.tail = i | |
406 | ||
407 | ||
408 | def saveConfig(self, xml_file="~/.faraday/config/user.xml"): | |
409 | """ Saves XML config on new file. """ | |
410 | ||
411 | ROOT = Element("faraday") | |
412 | ||
413 | API_CON_INFO_HOST = Element(CONST_API_CON_INFO_HOST) | |
414 | API_CON_INFO_HOST.text = self.getApiConInfoHost() | |
415 | ROOT.append(API_CON_INFO_HOST) | |
416 | ||
417 | API_CON_INFO_PORT = Element(CONST_API_CON_INFO_PORT) | |
418 | API_CON_INFO_PORT.text = str(self.getApiConInfoPort()) | |
419 | ROOT.append(API_CON_INFO_PORT) | |
420 | ||
421 | API_RESTFUL_CON_INFO_PORT = Element(CONST_API_RESTFUL_CON_INFO_PORT) | |
422 | API_RESTFUL_CON_INFO_PORT.text = str(self.getApiRestfulConInfoPort()) | |
423 | ROOT.append(API_RESTFUL_CON_INFO_PORT) | |
424 | ||
425 | APPNAME = Element(CONST_APPNAME) | |
426 | APPNAME.text = self.getAppname() | |
427 | ROOT.append(APPNAME) | |
428 | ||
429 | AUTH = Element(CONST_AUTH, encrypted="no", algorithm="OTR") | |
430 | AUTH.text = self.getAuth() | |
431 | ROOT.append(AUTH) | |
432 | ||
433 | AUTO_SHARE_WORKSPACE = Element(CONST_AUTO_SHARE_WORKSPACE) | |
434 | AUTO_SHARE_WORKSPACE.text = self.getAutoShareWorkspace() | |
435 | ROOT.append(AUTO_SHARE_WORKSPACE) | |
436 | ||
437 | CONFIG_PATH = Element(CONST_CONFIG_PATH) | |
438 | CONFIG_PATH.text = self.getConfigPath() | |
439 | ROOT.append(CONFIG_PATH) | |
440 | ||
441 | DATA_PATH = Element(CONST_DATA_PATH) | |
442 | DATA_PATH.text = self.getDataPath() | |
443 | ROOT.append(DATA_PATH) | |
444 | ||
445 | DEBUG_STATUS = Element(CONST_DEBUG_STATUS) | |
446 | DEBUG_STATUS.text = str(self.getDebugStatus()) | |
447 | ROOT.append(DEBUG_STATUS) | |
448 | ||
449 | DEFAULT_CATEGORY = Element(CONST_DEFAULT_CATEGORY) | |
450 | DEFAULT_CATEGORY.text = self.getDefaultCategory() | |
451 | ROOT.append(DEFAULT_CATEGORY) | |
452 | ||
453 | DEFAULT_TEMP_PATH = Element(CONST_DEFAULT_TEMP_PATH) | |
454 | DEFAULT_TEMP_PATH.text = self.getDefaultTempPath() | |
455 | ROOT.append(DEFAULT_TEMP_PATH) | |
456 | ||
457 | FONT = Element(CONST_FONT) | |
458 | FONT.text = self.getFont() | |
459 | ROOT.append(FONT) | |
460 | ||
461 | HOME_PATH = Element(CONST_HOME_PATH) | |
462 | HOME_PATH.text = self.getHomePath() | |
463 | ROOT.append(HOME_PATH) | |
464 | ||
465 | ||
466 | HOST_TREE_TOGGLE = Element(CONST_HOST_TREE_TOGGLE) | |
467 | HOST_TREE_TOGGLE.text = self.getHostTreeToggle() | |
468 | ROOT.append(HOST_TREE_TOGGLE) | |
469 | ||
470 | HSTACTIONS_PATH = Element(CONST_HSTACTIONS_PATH) | |
471 | HSTACTIONS_PATH.text = self.getHsactionsPath() | |
472 | ROOT.append(HSTACTIONS_PATH) | |
473 | ||
474 | ICONS_PATH = Element(CONST_ICONS_PATH) | |
475 | ICONS_PATH.text = self.getIconsPath() | |
476 | ROOT.append(ICONS_PATH) | |
477 | ||
478 | IMAGE_PATH = Element(CONST_IMAGE_PATH) | |
479 | IMAGE_PATH.text = self.getImagePath() | |
480 | ROOT.append(IMAGE_PATH) | |
481 | ||
482 | LOG_CONSOLE_TOGGLE = Element(CONST_LOG_CONSOLE_TOGGLE) | |
483 | LOG_CONSOLE_TOGGLE.text = self.getLogConsoleToggle() | |
484 | ROOT.append(LOG_CONSOLE_TOGGLE) | |
485 | ||
486 | NETWORK_LOCATION = Element(CONST_NETWORK_LOCATION) | |
487 | NETWORK_LOCATION.text = self.getNetworkLocation() | |
488 | ROOT.append(NETWORK_LOCATION) | |
489 | ||
490 | PERSISTENCE_PATH = Element(CONST_PERSISTENCE_PATH) | |
491 | PERSISTENCE_PATH.text = self.getPersistencePath() | |
492 | ROOT.append(PERSISTENCE_PATH) | |
493 | ||
494 | PERSPECTIVE_VIEW = Element(CONST_PERSPECTIVE_VIEW) | |
495 | PERSPECTIVE_VIEW.text = self.getPerspectiveView() | |
496 | ROOT.append(PERSPECTIVE_VIEW) | |
497 | ||
498 | REPO_PASSWORD = Element(CONST_REPO_PASSWORD) | |
499 | REPO_PASSWORD.text = self.getRepoPassword() | |
500 | ROOT.append(REPO_PASSWORD) | |
501 | ||
502 | REPO_URL = Element(CONST_REPO_URL, type="SVN") | |
503 | REPO_URL.text = self.getRepoUrl() | |
504 | ROOT.append(REPO_URL) | |
505 | ||
506 | REPO_USER = Element(CONST_REPO_USER) | |
507 | REPO_USER.text = self.getRepoUser() | |
508 | ROOT.append(REPO_USER) | |
509 | ||
510 | REPORT_PATH = Element(CONST_REPORT_PATH) | |
511 | REPORT_PATH.text = self.getReportPath() | |
512 | ROOT.append(REPORT_PATH) | |
513 | ||
514 | SHELL_MAXIMIZED = Element(CONST_SHELL_MAXIMIZED) | |
515 | SHELL_MAXIMIZED.text = self.getShellMaximized() | |
516 | ROOT.append(SHELL_MAXIMIZED) | |
517 | ||
518 | LAST_WORKSPACE = Element(CONST_LAST_WORKSPACE) | |
519 | LAST_WORKSPACE.text = self.getLastWorkspace() | |
520 | ROOT.append(LAST_WORKSPACE) | |
521 | ||
522 | COUCH_URI = Element(CONST_COUCH_URI) | |
523 | COUCH_URI.text = self.getCouchURI() | |
524 | ROOT.append(COUCH_URI) | |
525 | ||
526 | COUCH_IS_REPLICATED = Element(CONST_COUCH_ISREPLICATED) | |
527 | COUCH_IS_REPLICATED.text = str(self.getCouchIsReplicated()) | |
528 | ROOT.append(COUCH_IS_REPLICATED) | |
529 | ||
530 | COUCH_REPLICS = Element(CONST_COUCH_REPLICS) | |
531 | COUCH_REPLICS.text = self.getCouchReplics() | |
532 | ROOT.append(COUCH_REPLICS) | |
533 | ||
534 | VERSION = Element(CONST_VERSION) | |
535 | VERSION.text = self.getVersion() | |
536 | ROOT.append(VERSION) | |
537 | ||
538 | PLUGIN_SETTINGS = Element(CONST_PLUGIN_SETTINGS) | |
539 | PLUGIN_SETTINGS.text = json.dumps(self.getPluginSettings()) | |
540 | ROOT.append(PLUGIN_SETTINGS) | |
541 | ||
542 | UPDATE_URI = Element(CONST_UPDATEURI) | |
543 | UPDATE_URI.text = self.getUpdatesUri() | |
544 | ROOT.append(UPDATE_URI) | |
545 | ||
546 | TKT_URI = Element(CONST_TKTURI) | |
547 | TKT_URI.text = self.getTktPostUri() | |
548 | ROOT.append(TKT_URI) | |
549 | ||
550 | TKT_APIPARAMS = Element(CONST_TKTAPIPARAMS) | |
551 | TKT_APIPARAMS.text = self.getApiParams() | |
552 | ROOT.append(TKT_APIPARAMS) | |
553 | ||
554 | TKT_TEMPLATE = Element(CONST_TKTTEMPLATE) | |
555 | TKT_TEMPLATE.text = self.getTktTemplate() | |
556 | ROOT.append(TKT_TEMPLATE) | |
557 | ||
558 | self.indent(ROOT, 0) | |
559 | xml_file = os.path.expanduser(xml_file) | |
560 | ElementTree(ROOT).write(xml_file) | |
561 | ||
562 | def getInstanceConfiguration(): | |
563 | global the_config | |
564 | if the_config is None: | |
565 | if os.path.exists(os.path.expanduser("~/.faraday/config/user.xml")): | |
566 | the_config = Configuration(os.path.expanduser("~/.faraday/config/user.xml")) | |
567 | else: | |
568 | the_config = Configuration(os.path.expanduser("~/.faraday/config/config.xml")) | |
569 | return the_config | |
570 | ||
571 | ||
572 | ||
573 | ||
574 | ||
575 | ||
576 | ||
577 | ||
578 | ||
579 | ||
580 | ||
581 | ||
582 | ||
0 | ''' | |
1 | Faraday Penetration Test IDE | |
2 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
3 | See the file 'doc/LICENSE' for the license information | |
4 | ||
5 | ''' | |
6 | import sys, os, string, ast, json | |
7 | ||
8 | try: | |
9 | import xml.etree.cElementTree as ET | |
10 | from xml.etree.cElementTree import Element, ElementTree | |
11 | except ImportError: | |
12 | import xml.etree.ElementTree as ET | |
13 | from xml.etree.ElementTree import Element, ElementTree | |
14 | ||
15 | the_config = None | |
16 | ||
17 | CONST_API_CON_INFO = "api_con_info" | |
18 | CONST_API_CON_INFO_HOST = "api_con_info_host" | |
19 | CONST_API_CON_INFO_PORT = "api_con_info_port" | |
20 | CONST_API_RESTFUL_CON_INFO_PORT = "api_restful_con_info_port" | |
21 | CONST_APPNAME = "appname" | |
22 | CONST_AUTH = "auth" | |
23 | CONST_AUTO_SHARE_WORKSPACE = "auto_share_workspace" | |
24 | CONST_CONFIG_PATH = "config_path" | |
25 | CONST_DATA_PATH = "data_path" | |
26 | CONST_DEBUG_STATUS = "debug_status" | |
27 | CONST_DEFAULT_CATEGORY = "default_category" | |
28 | CONST_DEFAULT_TEMP_PATH = "default_temp_path" | |
29 | CONST_FONT = "font" | |
30 | CONST_HOME_PATH = "home_path" | |
31 | CONST_HOST_TREE_TOGGLE = "host_tree_toggle" | |
32 | CONST_HSTACTIONS_PATH = "hstactions_path" | |
33 | CONST_ICONS_PATH = "icons_path" | |
34 | CONST_IMAGE_PATH = "image_path" | |
35 | CONST_LOG_CONSOLE_TOGGLE = "log_console_toggle" | |
36 | CONST_NETWORK_LOCATION = "network_location" | |
37 | CONST_PERSISTENCE_PATH = "persistence_path" | |
38 | CONST_PERSPECTIVE_VIEW = "perspective_view" | |
39 | CONST_REPO_PASSWORD = "repo_password" | |
40 | CONST_COUCH_URI = "couch_uri" | |
41 | CONST_COUCH_REPLICS = "couch_replics" | |
42 | CONST_COUCH_ISREPLICATED = "couch_is_replicated" | |
43 | CONST_REPO_URL = "repo_url" | |
44 | CONST_REPO_USER = "repo_user" | |
45 | CONST_REPORT_PATH = "report_path" | |
46 | CONST_SHELL_MAXIMIZED = "shell_maximized" | |
47 | CONST_VERSION = "version" | |
48 | CONST_UPDATEURI = "updates_uri" | |
49 | CONST_TKTURI = "tickets_uri" | |
50 | CONST_TKTAPIPARAMS = "tickets_api" | |
51 | CONST_TKTTEMPLATE = "tickets_template" | |
52 | ||
53 | CONST_LAST_WORKSPACE = "last_workspace" | |
54 | CONST_PLUGIN_SETTINGS = "plugin_settings" | |
55 | ||
56 | ||
57 | DEFAULT_XML = os.path.dirname(__file__) + "/default.xml" | |
58 | ||
59 | ||
60 | class Configuration: | |
61 | ||
62 | def __init__(self, xml_file=DEFAULT_XML): | |
63 | """ Initializer that handles a configuration automagically. """ | |
64 | ||
65 | self.filepath = xml_file | |
66 | ||
67 | if self._isConfig(): self._getConfig() | |
68 | ||
69 | def _isConfig(self): | |
70 | """ Checks whether the given file exists and belongs | |
71 | to faraday's configuration syntax""" | |
72 | ||
73 | root = f = None | |
74 | ||
75 | try: | |
76 | f = open(self.filepath, 'rb') | |
77 | try: | |
78 | for event, elem in ET.iterparse(f, ('start', )): | |
79 | root = elem.tag | |
80 | break | |
81 | except SyntaxError, err: | |
82 | print "Not an xml file.\n %s" % (err) | |
83 | return False | |
84 | ||
85 | except IOError, err: | |
86 | print "Error while opening file.\n%s. %s" % (err, self.filepath) | |
87 | return False | |
88 | ||
89 | finally: | |
90 | if f: f.close() | |
91 | ||
92 | return (root == "faraday") | |
93 | ||
94 | def _getTree(self): | |
95 | """ Returns an XML tree read from file. """ | |
96 | ||
97 | f = open(self.filepath) | |
98 | try: | |
99 | tree = ET.fromstring(f.read()) | |
100 | except SyntaxError, err: | |
101 | print "SyntaxError: %s. %s" % (err, self.filepath) | |
102 | return None | |
103 | return tree | |
104 | ||
105 | def _getValue(self, tree, var, default = None): | |
106 | """ Returns generic value from a variable on an XML tree. """ | |
107 | ||
108 | elem = tree.findall(var) | |
109 | if not(elem): | |
110 | return default | |
111 | ||
112 | return elem[0].text | |
113 | ||
114 | def _getConfig(self): | |
115 | """ Gathers all configuration data from self.filepath, and | |
116 | completes private attributes with such information. """ | |
117 | ||
118 | tree = self._getTree() | |
119 | if tree: | |
120 | self._api_con_info_host = self._getValue(tree, CONST_API_CON_INFO_HOST) | |
121 | self._api_con_info_port = self._getValue(tree, CONST_API_CON_INFO_PORT) | |
122 | self._api_restful_con_info_port = self._getValue(tree, CONST_API_RESTFUL_CON_INFO_PORT) | |
123 | self._api_con_info = self._getValue(tree, CONST_API_CON_INFO) | |
124 | self._appname = self._getValue(tree, CONST_APPNAME) | |
125 | self._auth = self._getValue(tree, CONST_AUTH) | |
126 | self._auto_share_workspace = self._getValue(tree, CONST_AUTO_SHARE_WORKSPACE) | |
127 | self._config_path = self._getValue(tree, CONST_CONFIG_PATH) | |
128 | self._data_path = self._getValue(tree, CONST_DATA_PATH) | |
129 | self._debug_status = self._getValue(tree, CONST_DEBUG_STATUS) | |
130 | self._default_category = self._getValue(tree, CONST_DEFAULT_CATEGORY) | |
131 | self._default_temp_path = self._getValue(tree, CONST_DEFAULT_TEMP_PATH) | |
132 | self._font = self._getValue(tree, CONST_FONT) | |
133 | self._home_path = self._getValue(tree, CONST_HOME_PATH) | |
134 | self._host_tree_toggle = self._getValue(tree, CONST_HOST_TREE_TOGGLE) | |
135 | self._hsactions_path = self._getValue(tree, CONST_HSTACTIONS_PATH) | |
136 | self._icons_path = self._getValue(tree, CONST_ICONS_PATH) | |
137 | self._image_path = self._getValue(tree, CONST_IMAGE_PATH) | |
138 | self._log_console_toggle = self._getValue(tree, CONST_LOG_CONSOLE_TOGGLE) | |
139 | self._network_location = self._getValue(tree, CONST_NETWORK_LOCATION) | |
140 | self._persistence_path = self._getValue(tree, CONST_PERSISTENCE_PATH) | |
141 | self._perspective_view = self._getValue(tree, CONST_PERSISTENCE_PATH) | |
142 | self._repo_password = self._getValue(tree, CONST_REPO_PASSWORD) | |
143 | self._couch_uri = self._getValue(tree, CONST_COUCH_URI, default = "") | |
144 | self._couch_replics = self._getValue(tree, CONST_COUCH_REPLICS, default = "") | |
145 | self._couch_is_replicated = bool(self._getValue(tree, CONST_COUCH_ISREPLICATED, default = False)) | |
146 | self._repo_url = self._getValue(tree, CONST_REPO_URL) | |
147 | self._repo_user = self._getValue(tree, CONST_REPO_USER) | |
148 | self._report_path = self._getValue(tree, CONST_REPORT_PATH) | |
149 | self._shell_maximized = self._getValue(tree, CONST_SHELL_MAXIMIZED) | |
150 | self._version = self._getValue(tree, CONST_VERSION) | |
151 | self._last_workspace = self._getValue(tree, CONST_LAST_WORKSPACE, default = "untitled") | |
152 | self._plugin_settings = json.loads(self._getValue(tree, CONST_PLUGIN_SETTINGS, default = "{}")) | |
153 | ||
154 | self._updates_uri = self._getValue(tree, CONST_UPDATEURI, default = "https://www.faradaysec.com/scripts/updates.php") | |
155 | self._tkts_uri = self._getValue(tree, CONST_TKTURI,default = "https://www.faradaysec.com/scripts/listener.php") | |
156 | self._tkt_api_params = self._getValue(tree, CONST_TKTAPIPARAMS,default ="{}") | |
157 | self._tkt_template = self._getValue(tree, CONST_TKTTEMPLATE,default ="{}") | |
158 | ||
159 | ||
160 | ||
161 | def getApiConInfo(self): | |
162 | if str(self._api_con_info_host) == "None" or str(self._api_con_info_port) == "None": | |
163 | return None | |
164 | return self._api_con_info_host, int(self._api_con_info_port) | |
165 | ||
166 | def getApiRestfulConInfo(self): | |
167 | if str(self._api_con_info_host) == "None" or str(self._api_restful_con_info_port) == "None": | |
168 | return None | |
169 | return self._api_con_info_host, int(self._api_restful_con_info_port) | |
170 | ||
171 | def getApiConInfoHost(self): | |
172 | return self._api_con_info_host | |
173 | ||
174 | def getApiConInfoPort(self): | |
175 | return self._api_con_info_port | |
176 | ||
177 | def getApiRestfulConInfoPort(self): | |
178 | return self._api_restful_con_info_port | |
179 | ||
180 | def getAppname(self): | |
181 | return self._appname | |
182 | ||
183 | def getAuth(self): | |
184 | return self._auth | |
185 | ||
186 | def getAutoShareWorkspace(self): | |
187 | return self._auto_share_workspace | |
188 | ||
189 | def getConfigPath(self): | |
190 | return os.path.expanduser(self._config_path) | |
191 | ||
192 | def getDataPath(self): | |
193 | return os.path.expanduser(self._data_path) | |
194 | ||
195 | def getDebugStatus(self): | |
196 | return int(self._debug_status) | |
197 | ||
198 | def getDefaultCategory(self): | |
199 | return self._default_category | |
200 | ||
201 | def getDefaultTempPath(self): | |
202 | return os.path.expanduser(self._default_temp_path) | |
203 | ||
204 | def getFont(self): | |
205 | return self._font | |
206 | ||
207 | def getHomePath(self): | |
208 | return os.path.expanduser(self._home_path) | |
209 | ||
210 | def getHostTreeToggle(self): | |
211 | return self._host_tree_toggle | |
212 | ||
213 | def getHsactionsPath(self): | |
214 | return os.path.expanduser(self._hsactions_path) | |
215 | ||
216 | def getIconsPath(self): | |
217 | return os.path.expanduser(self._icons_path) | |
218 | ||
219 | def getImagePath(self): | |
220 | return os.path.expanduser(self._image_path) | |
221 | ||
222 | def getLogConsoleToggle(self): | |
223 | return self._log_console_toggle | |
224 | ||
225 | def getNetworkLocation(self): | |
226 | return self._network_location | |
227 | ||
228 | def getPersistencePath(self): | |
229 | return os.path.expanduser(self._persistence_path) | |
230 | ||
231 | def getPerspectiveView(self): | |
232 | return self._perspective_view | |
233 | ||
234 | def getCouchURI(self): | |
235 | if self._couch_uri and self._couch_uri.endswith('/'): | |
236 | return self._couch_uri[:-1] | |
237 | else: | |
238 | return self._couch_uri | |
239 | ||
240 | def getCouchReplics(self): | |
241 | return self._couch_replics | |
242 | ||
243 | def getCouchIsReplicated(self): | |
244 | return self._couch_is_replicated | |
245 | ||
246 | def getRepoPassword(self): | |
247 | return self._repo_password | |
248 | ||
249 | def getRepoUrl(self): | |
250 | return self._repo_url | |
251 | ||
252 | def getRepoUser(self): | |
253 | return self._repo_user | |
254 | ||
255 | def getReportPath(self): | |
256 | return os.path.expanduser(self._report_path) | |
257 | ||
258 | def getShellMaximized(self): | |
259 | return self._shell_maximized | |
260 | ||
261 | def getVersion(self): | |
262 | return self._version | |
263 | ||
264 | def getLastWorkspace(self): | |
265 | return self._last_workspace | |
266 | ||
267 | def getPluginSettings(self): | |
268 | return self._plugin_settings | |
269 | ||
270 | def getUpdatesUri(self): | |
271 | return self._updates_uri | |
272 | ||
273 | def getTktPostUri(self): | |
274 | return self._tkts_uri | |
275 | ||
276 | def getApiParams(self): | |
277 | return self._tkt_api_params | |
278 | ||
279 | def getTktTemplate(self): | |
280 | return self._tkt_template | |
281 | ||
282 | ||
283 | ||
284 | def setLastWorkspace(self, workspaceName): | |
285 | self._last_workspace = workspaceName | |
286 | ||
287 | def setApiConInfo(self, val1, val2): | |
288 | self._api_con_info = val1, val2 | |
289 | self.setApiConInfoHost(val1) | |
290 | self.setApiConInfoPort(val2) | |
291 | ||
292 | def setApiRestfulConInfo(self, val1, val2): | |
293 | self._api_con_info = val1, val2 | |
294 | self.setApiConInfoHost(val1) | |
295 | self.setApiRestfulConInfoPort(val2) | |
296 | ||
297 | def setApiConInfoHost(self, val): | |
298 | self._api_con_info_host = val | |
299 | ||
300 | def setApiConInfoPort(self, val): | |
301 | self._api_con_info_port = str(val) | |
302 | ||
303 | def setApiRestfulConInfoPort(self, val): | |
304 | self._api_restful_con_info_port = str(val) | |
305 | ||
306 | def setAppname(self, val): | |
307 | self._appname = val | |
308 | ||
309 | def setAuth(self, val): | |
310 | self._auth = val | |
311 | ||
312 | def setAutoShareWorkspace(self, val): | |
313 | self._auto_share_workspace = val | |
314 | ||
315 | def setConfigPath(self, val): | |
316 | self._config_path = val | |
317 | ||
318 | def setDataPath(self, val): | |
319 | self._data_path = val | |
320 | ||
321 | def setDebugStatus(self, val): | |
322 | self._debug_status = int(val) | |
323 | ||
324 | def setDefaultCategory(self, val): | |
325 | self._default_category = val | |
326 | ||
327 | def setDefaultTempPath(self, val): | |
328 | self._default_temp_path = val | |
329 | ||
330 | def setFont(self, val): | |
331 | self._font = val | |
332 | ||
333 | def setHomePath(self, val): | |
334 | self._home_path = val | |
335 | ||
336 | def setHostTreeToggle(self, val): | |
337 | self._host_tree_toggle = val | |
338 | ||
339 | def setHsactionsPath(self, val): | |
340 | self._hsactions_path = val | |
341 | ||
342 | def setIconsPath(self, val): | |
343 | self._icons_path = val | |
344 | ||
345 | def setImagePath(self, val): | |
346 | self._image_path = val | |
347 | ||
348 | def setLogConsoleToggle(self, val): | |
349 | self._log_console_toggle = val | |
350 | ||
351 | def setNetworkLocation(self, val): | |
352 | self._network_location = val | |
353 | ||
354 | def setPersistencePath(self, val): | |
355 | self._persistence_path = val | |
356 | ||
357 | def setPerspectiveView(self, val): | |
358 | self._perspective_view = val | |
359 | ||
360 | def setRepoPassword(self, val): | |
361 | self._repo_password = val | |
362 | ||
363 | def setRepoUrl(self, val): | |
364 | self._repo_url = val | |
365 | ||
366 | def setRepoUser(self, val): | |
367 | self._repo_user = val | |
368 | ||
369 | def setReportPath(self, val): | |
370 | self._report_path = val | |
371 | ||
372 | def setShellMaximized(self, val): | |
373 | self._shell_maximized = val | |
374 | ||
375 | def setVersion(self, val): | |
376 | self._version = val | |
377 | ||
378 | def setCouchUri(self, uri): | |
379 | self._couch_uri = uri | |
380 | ||
381 | def setCouchIsReplicated(self, is_it): | |
382 | self._couch_is_replicated = is_it | |
383 | ||
384 | def setCouchReplics(self, urls): | |
385 | self._couch_replics = urls | |
386 | ||
387 | def setPluginSettings(self, settings): | |
388 | self._plugin_settings = settings | |
389 | ||
390 | def indent(self, elem, level=0): | |
391 | """ Indents the tree to make a pretty view of it. """ | |
392 | ||
393 | i = "\n" + level*" " | |
394 | if len(elem): | |
395 | if not elem.text or not elem.text.strip(): | |
396 | elem.text = i + " " | |
397 | if not elem.tail or not elem.tail.strip(): | |
398 | elem.tail = i | |
399 | for elem in elem: | |
400 | self.indent(elem, level+1) | |
401 | if not elem.tail or not elem.tail.strip(): | |
402 | elem.tail = i | |
403 | else: | |
404 | if level and (not elem.tail or not elem.tail.strip()): | |
405 | elem.tail = i | |
406 | ||
407 | ||
408 | def saveConfig(self, xml_file="~/.faraday/config/user.xml"): | |
409 | """ Saves XML config on new file. """ | |
410 | ||
411 | ROOT = Element("faraday") | |
412 | ||
413 | API_CON_INFO_HOST = Element(CONST_API_CON_INFO_HOST) | |
414 | API_CON_INFO_HOST.text = self.getApiConInfoHost() | |
415 | ROOT.append(API_CON_INFO_HOST) | |
416 | ||
417 | API_CON_INFO_PORT = Element(CONST_API_CON_INFO_PORT) | |
418 | API_CON_INFO_PORT.text = str(self.getApiConInfoPort()) | |
419 | ROOT.append(API_CON_INFO_PORT) | |
420 | ||
421 | API_RESTFUL_CON_INFO_PORT = Element(CONST_API_RESTFUL_CON_INFO_PORT) | |
422 | API_RESTFUL_CON_INFO_PORT.text = str(self.getApiRestfulConInfoPort()) | |
423 | ROOT.append(API_RESTFUL_CON_INFO_PORT) | |
424 | ||
425 | APPNAME = Element(CONST_APPNAME) | |
426 | APPNAME.text = self.getAppname() | |
427 | ROOT.append(APPNAME) | |
428 | ||
429 | AUTH = Element(CONST_AUTH, encrypted="no", algorithm="OTR") | |
430 | AUTH.text = self.getAuth() | |
431 | ROOT.append(AUTH) | |
432 | ||
433 | AUTO_SHARE_WORKSPACE = Element(CONST_AUTO_SHARE_WORKSPACE) | |
434 | AUTO_SHARE_WORKSPACE.text = self.getAutoShareWorkspace() | |
435 | ROOT.append(AUTO_SHARE_WORKSPACE) | |
436 | ||
437 | CONFIG_PATH = Element(CONST_CONFIG_PATH) | |
438 | CONFIG_PATH.text = self.getConfigPath() | |
439 | ROOT.append(CONFIG_PATH) | |
440 | ||
441 | DATA_PATH = Element(CONST_DATA_PATH) | |
442 | DATA_PATH.text = self.getDataPath() | |
443 | ROOT.append(DATA_PATH) | |
444 | ||
445 | DEBUG_STATUS = Element(CONST_DEBUG_STATUS) | |
446 | DEBUG_STATUS.text = str(self.getDebugStatus()) | |
447 | ROOT.append(DEBUG_STATUS) | |
448 | ||
449 | DEFAULT_CATEGORY = Element(CONST_DEFAULT_CATEGORY) | |
450 | DEFAULT_CATEGORY.text = self.getDefaultCategory() | |
451 | ROOT.append(DEFAULT_CATEGORY) | |
452 | ||
453 | DEFAULT_TEMP_PATH = Element(CONST_DEFAULT_TEMP_PATH) | |
454 | DEFAULT_TEMP_PATH.text = self.getDefaultTempPath() | |
455 | ROOT.append(DEFAULT_TEMP_PATH) | |
456 | ||
457 | FONT = Element(CONST_FONT) | |
458 | FONT.text = self.getFont() | |
459 | ROOT.append(FONT) | |
460 | ||
461 | HOME_PATH = Element(CONST_HOME_PATH) | |
462 | HOME_PATH.text = self.getHomePath() | |
463 | ROOT.append(HOME_PATH) | |
464 | ||
465 | ||
466 | HOST_TREE_TOGGLE = Element(CONST_HOST_TREE_TOGGLE) | |
467 | HOST_TREE_TOGGLE.text = self.getHostTreeToggle() | |
468 | ROOT.append(HOST_TREE_TOGGLE) | |
469 | ||
470 | HSTACTIONS_PATH = Element(CONST_HSTACTIONS_PATH) | |
471 | HSTACTIONS_PATH.text = self.getHsactionsPath() | |
472 | ROOT.append(HSTACTIONS_PATH) | |
473 | ||
474 | ICONS_PATH = Element(CONST_ICONS_PATH) | |
475 | ICONS_PATH.text = self.getIconsPath() | |
476 | ROOT.append(ICONS_PATH) | |
477 | ||
478 | IMAGE_PATH = Element(CONST_IMAGE_PATH) | |
479 | IMAGE_PATH.text = self.getImagePath() | |
480 | ROOT.append(IMAGE_PATH) | |
481 | ||
482 | LOG_CONSOLE_TOGGLE = Element(CONST_LOG_CONSOLE_TOGGLE) | |
483 | LOG_CONSOLE_TOGGLE.text = self.getLogConsoleToggle() | |
484 | ROOT.append(LOG_CONSOLE_TOGGLE) | |
485 | ||
486 | NETWORK_LOCATION = Element(CONST_NETWORK_LOCATION) | |
487 | NETWORK_LOCATION.text = self.getNetworkLocation() | |
488 | ROOT.append(NETWORK_LOCATION) | |
489 | ||
490 | PERSISTENCE_PATH = Element(CONST_PERSISTENCE_PATH) | |
491 | PERSISTENCE_PATH.text = self.getPersistencePath() | |
492 | ROOT.append(PERSISTENCE_PATH) | |
493 | ||
494 | PERSPECTIVE_VIEW = Element(CONST_PERSPECTIVE_VIEW) | |
495 | PERSPECTIVE_VIEW.text = self.getPerspectiveView() | |
496 | ROOT.append(PERSPECTIVE_VIEW) | |
497 | ||
498 | REPO_PASSWORD = Element(CONST_REPO_PASSWORD) | |
499 | REPO_PASSWORD.text = self.getRepoPassword() | |
500 | ROOT.append(REPO_PASSWORD) | |
501 | ||
502 | REPO_URL = Element(CONST_REPO_URL, type="SVN") | |
503 | REPO_URL.text = self.getRepoUrl() | |
504 | ROOT.append(REPO_URL) | |
505 | ||
506 | REPO_USER = Element(CONST_REPO_USER) | |
507 | REPO_USER.text = self.getRepoUser() | |
508 | ROOT.append(REPO_USER) | |
509 | ||
510 | REPORT_PATH = Element(CONST_REPORT_PATH) | |
511 | REPORT_PATH.text = self.getReportPath() | |
512 | ROOT.append(REPORT_PATH) | |
513 | ||
514 | SHELL_MAXIMIZED = Element(CONST_SHELL_MAXIMIZED) | |
515 | SHELL_MAXIMIZED.text = self.getShellMaximized() | |
516 | ROOT.append(SHELL_MAXIMIZED) | |
517 | ||
518 | LAST_WORKSPACE = Element(CONST_LAST_WORKSPACE) | |
519 | LAST_WORKSPACE.text = self.getLastWorkspace() | |
520 | ROOT.append(LAST_WORKSPACE) | |
521 | ||
522 | COUCH_URI = Element(CONST_COUCH_URI) | |
523 | COUCH_URI.text = self.getCouchURI() | |
524 | ROOT.append(COUCH_URI) | |
525 | ||
526 | COUCH_IS_REPLICATED = Element(CONST_COUCH_ISREPLICATED) | |
527 | COUCH_IS_REPLICATED.text = str(self.getCouchIsReplicated()) | |
528 | ROOT.append(COUCH_IS_REPLICATED) | |
529 | ||
530 | COUCH_REPLICS = Element(CONST_COUCH_REPLICS) | |
531 | COUCH_REPLICS.text = self.getCouchReplics() | |
532 | ROOT.append(COUCH_REPLICS) | |
533 | ||
534 | VERSION = Element(CONST_VERSION) | |
535 | VERSION.text = self.getVersion() | |
536 | ROOT.append(VERSION) | |
537 | ||
538 | PLUGIN_SETTINGS = Element(CONST_PLUGIN_SETTINGS) | |
539 | PLUGIN_SETTINGS.text = json.dumps(self.getPluginSettings()) | |
540 | ROOT.append(PLUGIN_SETTINGS) | |
541 | ||
542 | UPDATE_URI = Element(CONST_UPDATEURI) | |
543 | UPDATE_URI.text = self.getUpdatesUri() | |
544 | ROOT.append(UPDATE_URI) | |
545 | ||
546 | TKT_URI = Element(CONST_TKTURI) | |
547 | TKT_URI.text = self.getTktPostUri() | |
548 | ROOT.append(TKT_URI) | |
549 | ||
550 | TKT_APIPARAMS = Element(CONST_TKTAPIPARAMS) | |
551 | TKT_APIPARAMS.text = self.getApiParams() | |
552 | ROOT.append(TKT_APIPARAMS) | |
553 | ||
554 | TKT_TEMPLATE = Element(CONST_TKTTEMPLATE) | |
555 | TKT_TEMPLATE.text = self.getTktTemplate() | |
556 | ROOT.append(TKT_TEMPLATE) | |
557 | ||
558 | self.indent(ROOT, 0) | |
559 | xml_file = os.path.expanduser(xml_file) | |
560 | ElementTree(ROOT).write(xml_file) | |
561 | ||
562 | def getInstanceConfiguration(): | |
563 | global the_config | |
564 | if the_config is None: | |
565 | if os.path.exists(os.path.expanduser("~/.faraday/config/user.xml")): | |
566 | the_config = Configuration(os.path.expanduser("~/.faraday/config/user.xml")) | |
567 | else: | |
568 | the_config = Configuration(os.path.expanduser("~/.faraday/config/config.xml")) | |
569 | return the_config |
0 | <?xml version="1.0"?> | |
1 | <faraday> | |
2 | ||
3 | <appname>Faraday - Penetration Test IDE</appname> | |
4 | <version>1.0</version> | |
5 | <debug_status>0</debug_status> | |
6 | <font>-Misc-Fixed-medium-r-normal-*-12-100-100-100-c-70-iso8859-1</font> | |
7 | <home_path>~/</home_path> | |
8 | <image_path>~/.faraday/images/</image_path>> | |
9 | <icons_path>~/.faraday/images/icons/</icons_path> | |
10 | <data_path>~/.faraday/data</data_path> | |
11 | <config_path>~/.faraday/</config_path> | |
12 | <default_temp_path>~/.faraday/temp/</default_temp_path> | |
13 | <persistence_path>~/.faraday/persistence/</persistence_path> | |
14 | <report_path>~/.faraday/report/</report_path> | |
15 | <hstactions_path>~/.faraday/hstactions.dat</hstactions_path> | |
16 | ||
17 | <default_category>General</default_category> | |
18 | <auto_share_workspace>1</auto_share_workspace> | |
19 | <network_location>LAN</network_location> | |
20 | <perspective_view>Hosts</perspective_view> | |
21 | <log_console_toggle></log_console_toggle> | |
22 | <shell_maximized>0</shell_maximized> | |
23 | <host_tree_toggle></host_tree_toggle> | |
24 | ||
25 | <api_con_info>None</api_con_info> | |
26 | <api_con_info_host>None</api_con_info_host> | |
27 | <api_con_info_port>None</api_con_info_port> | |
28 | <auth encrypted="no" algorithm="OTR">0</auth> | |
29 | <repo_url type="svn"></repo_url> | |
30 | <repo_user>u</repo_user> | |
31 | <repo_password></repo_password> | |
32 | <couch_uri/> | |
33 | <couch_is_replicated/> | |
34 | <couch_replics/> | |
35 | ||
36 | <updates_uri>https://www.faradaysec.com/scripts/updates.php</updates_uri> | |
37 | <tickets_uri>https://www.faradaysec.com/scripts/listener.php</tickets_uri> | |
38 | <tickets_template>{}</tickets_template> | |
39 | <tickets_api>{}</tickets_api> | |
40 | ||
41 | ||
42 | </faraday> | |
0 | <?xml version="1.0"?> | |
1 | <faraday> | |
2 | ||
3 | <appname>Faraday - Penetration Test IDE</appname> | |
4 | <version>1.0.13</version> | |
5 | <debug_status>0</debug_status> | |
6 | <font>-Misc-Fixed-medium-r-normal-*-12-100-100-100-c-70-iso8859-1</font> | |
7 | <home_path>~/</home_path> | |
8 | <image_path>~/.faraday/images/</image_path>> | |
9 | <icons_path>~/.faraday/images/icons/</icons_path> | |
10 | <data_path>~/.faraday/data</data_path> | |
11 | <config_path>~/.faraday/</config_path> | |
12 | <default_temp_path>~/.faraday/temp/</default_temp_path> | |
13 | <persistence_path>~/.faraday/persistence/</persistence_path> | |
14 | <report_path>~/.faraday/report/</report_path> | |
15 | <hstactions_path>~/.faraday/hstactions.dat</hstactions_path> | |
16 | ||
17 | <default_category>General</default_category> | |
18 | <auto_share_workspace>1</auto_share_workspace> | |
19 | <network_location>LAN</network_location> | |
20 | <perspective_view>Hosts</perspective_view> | |
21 | <log_console_toggle></log_console_toggle> | |
22 | <shell_maximized>0</shell_maximized> | |
23 | <host_tree_toggle></host_tree_toggle> | |
24 | ||
25 | <api_con_info>None</api_con_info> | |
26 | <api_con_info_host>None</api_con_info_host> | |
27 | <api_con_info_port>None</api_con_info_port> | |
28 | <auth encrypted="no" algorithm="OTR">0</auth> | |
29 | <repo_url type="svn"></repo_url> | |
30 | <repo_user>u</repo_user> | |
31 | <repo_password></repo_password> | |
32 | <couch_uri/> | |
33 | <couch_is_replicated/> | |
34 | <couch_replics/> | |
35 | ||
36 | <updates_uri>https://www.faradaysec.com/scripts/updates.php</updates_uri> | |
37 | <tickets_uri>https://www.faradaysec.com/scripts/listener.php</tickets_uri> | |
38 | <tickets_template>{}</tickets_template> | |
39 | <tickets_api>{}</tickets_api> | |
40 | ||
41 | ||
42 | </faraday> |
57 | 57 | return self._main_window |
58 | 58 | |
59 | 59 | def run(self, args): |
60 | self._main_window.createShellTab() | |
61 | 60 | self.createLoggerWidget() |
62 | 61 | self._main_window.showAll() |
63 | 62 | couchURL = CONF.getCouchURI() |
349 | 349 | |
350 | 350 | self._log_console.show() |
351 | 351 | |
352 | self.timer = qt.QTimer(self) | |
353 | self.connect(self.timer, qt.SIGNAL('timeout()'), self.createShellTab) | |
354 | self.timer.start(200, True) | |
355 | ||
352 | 356 | for shell_widget in self._shell_widgets: |
353 | 357 | shell_widget.show() |
354 | 358 | |
361 | 365 | shell_widget.setFocus() |
362 | 366 | |
363 | 367 | def createShellTab(self): |
364 | ||
365 | 368 | tab_name = "Shell-%d" % self._tab_manager.getNextId() |
366 | 369 | self._main_app.createShellEnvironment(tab_name) |
367 | 370 |
13 | 13 | |
14 | 14 | update=0 |
15 | 15 | #protection |
16 | sha_kali2_i686=d08b0562acc3da5a392509a1801d5569e1ace750d26d020b83ecc4c8eea4f191 | |
17 | sha_kali2_x86_64=f8ee223706bd306dbdba1bd9232f196878c598cb449d006e24edbcbe85f19f2a | |
16 | 18 | sha_kali_i686=f071539d8d64ad9b30c7214daf5b890a94b0e6d68f13bdcc34c2453c99afe9c4 |
17 | 19 | sha_kali_x86_64=02a050372fb30ede1454e1dd99d97e0fe0963ce2bd36c45efe90eec78df11d04 |
18 | 20 | sha_ubuntu13_10_i686=8199904fb5fca8bc244c31b596c3ae0d441483bfbb2dc47f66186ceffbf3586e |
27 | 29 | if [ ! -f /usr/bin/lsb_release ] ; then |
28 | 30 | apt-get update |
29 | 31 | update=1 |
30 | apt-get -y install lsb-release | |
32 | apt-get -y install lsb-release | |
31 | 33 | fi |
32 | 34 | os=$(lsb_release -s -d) |
33 | 35 | elif [ -f /etc/debian_version ]; then |
42 | 44 | down=0 |
43 | 45 | if [ "$os" = "Ubuntu 10.04.2 LTS" ]; then |
44 | 46 | version="ubuntu10-04.02$arch" |
47 | elif [[ "$os" =~ "Kali GNU/Linux 2."* ]]; then | |
48 | version="kali2-$arch" | |
49 | down=1 | |
45 | 50 | elif [[ "$os" =~ .*Kali.* ]]; then |
46 | 51 | version="kali-$arch" |
47 | 52 | down=1 |
53 | 58 | elif [ "$os" = "Ubuntu 13.04" ]; then |
54 | 59 | version="ubuntu13-04-$arch" |
55 | 60 | down=1 |
56 | elif [[ "$os" =~ "Ubuntu 14.04".*|"Ubuntu 14.10".*|"Ubuntu Vivid Vervet (development branch)"|"Debian 8.".*|"Ubuntu 15".* ]]; then | |
61 | elif [[ "$os" =~ "Ubuntu 14.04".*|"Ubuntu 14.10".*|"Ubuntu Vivid Vervet (development branch)"|"Ubuntu 15".* ]]; then | |
57 | 62 | version="ubuntu13-10-$arch" |
58 | 63 | down=1 |
59 | 64 | # Install pip from github. |
60 | 65 | # Bug: https://bugs.launchpad.net/ubuntu/+source/python-pip/+bug/1306991 |
61 | 66 | wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py |
62 | 67 | python get-pip.py |
63 | elif [[ "$os" =~ "Debian 7".* ]]; then | |
68 | elif [[ "$os" =~ "Debian 7".*|"Debian 8".* ]]; then | |
64 | 69 | version="ubuntu13-10-$arch" |
65 | 70 | down=1 |
71 | wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py | |
72 | python get-pip.py | |
66 | 73 | echo "deb http://ftp.debian.org/debian experimental main" >> /etc/apt/sources.list |
67 | 74 | echo "deb http://ftp.debian.org/debian sid main" >> /etc/apt/sources.list |
68 | 75 | apt-get update |
69 | apt-get -t experimental -y install libc6-dev | |
70 | sed -i 's/deb http:\/\/ftp.debian.org\/debian experimental main//' /etc/apt/sources.list | |
71 | sed -i 's/deb http:\/\/ftp.debian.org\/debian sid main//' /etc/apt/sources.list | |
72 | apt-get update | |
76 | ||
77 | if [[ "$os" =~ "Debian 7".* ]]; then | |
78 | apt-get -t experimental -y install libc6-dev | |
79 | sed -i 's/deb http:\/\/ftp.debian.org\/debian experimental main//' /etc/apt/sources.list | |
80 | sed -i 's/deb http:\/\/ftp.debian.org\/debian sid main//' /etc/apt/sources.list | |
81 | apt-get update | |
82 | fi | |
73 | 83 | else |
74 | 84 | echo "[-] Could not find a install for $os ($arch $kernel)" |
75 | 85 | exit |
104 | 114 | apt-get -y install python-qt3 |
105 | 115 | fi |
106 | 116 | |
107 | apt-get -y install ipython python-pip python-dev couchdb libpq-dev | |
117 | if [ "$update" -eq 0 ]; then | |
118 | apt-get update | |
119 | update=1 | |
120 | fi | |
121 | apt-get --ignore-missing -y install ipython python-pip python-dev libpq-dev couchdb | |
108 | 122 | pip install -r requirements.txt |
109 | 123 | |
110 | 124 | echo "You can now run Faraday, enjoy!" |
19 | 19 | print "cElementTree could not be imported. Using ElementTree instead" |
20 | 20 | import xml.etree.ElementTree as ET |
21 | 21 | from apis.rest.api import PluginControllerAPIClient |
22 | ||
23 | from utils.common import sha1OfFile | |
22 | 24 | |
23 | 25 | from config.configuration import getInstanceConfiguration |
24 | 26 | CONF = getInstanceConfiguration() |
86 | 88 | #TODO: get host and port from config |
87 | 89 | client = PluginControllerAPIClient("127.0.0.1", 9977) |
88 | 90 | |
89 | model.api.devlog("The file is %s, %s" % (filename,parser.report_type)) | |
91 | model.api.log("Importing report type: %s , (%s) - (%s)" % (parser.report_type, filename, sha1OfFile(filename))) | |
90 | 92 | |
91 | 93 | command_string = "./%s report" % parser.report_type.lower() |
92 | 94 | model.api.devlog("Executing %s" % (command_string)) |
93 | 95 | |
94 | 96 | new_cmd, output_file = client.send_cmd(command_string) |
95 | 97 | client.send_output(command_string, filename) |
98 | else: | |
99 | model.api.log("Report type not found: (%s)" % (filename)) | |
100 | ||
96 | 101 | os.rename(filename, os.path.join(self._report_ppath, name)) |
97 | 102 | |
98 | 103 | self.onlinePlugins() |
0 | #!/usr/bin/env python | |
1 | ''' | |
2 | Faraday Penetration Test IDE | |
3 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
4 | See the file 'doc/LICENSE' for the license information | |
5 | ||
6 | ''' | |
7 | import os | |
8 | import sys | |
9 | import signal | |
10 | ||
11 | # TODO: no seria mejor activar todo ? | |
12 | # XXX: something strange happens if we import | |
13 | # this module at the bottom of the list.... | |
14 | from auth.manager import SecurityManager | |
15 | from auth.manager import codes | |
16 | from model.controller import ModelController | |
17 | from persistence.persistence_managers import DbManager | |
18 | from controllers.change import ChangeController | |
19 | from managers.model_managers import WorkspaceManager | |
20 | import model.api | |
21 | import model.guiapi | |
22 | import apis.rest.api as restapi | |
23 | import model.log | |
24 | from utils.logs import getLogger | |
25 | import traceback | |
26 | from managers.all import PluginManager | |
27 | from managers.mapper_manager import MapperManager | |
28 | from managers.reports_managers import ReportManager | |
29 | ||
30 | from utils.error_report import exception_handler | |
31 | from utils.error_report import installThreadExcepthook | |
32 | ||
33 | from gui.gui_app import UiFactory | |
34 | ||
35 | from config.configuration import getInstanceConfiguration | |
36 | CONF = getInstanceConfiguration() | |
37 | ||
38 | ||
39 | class MainApplication(object): | |
40 | """ | |
41 | """ | |
42 | ||
43 | def __init__(self, args): | |
44 | self._original_excepthook = sys.excepthook | |
45 | ||
46 | self._configuration = CONF | |
47 | ||
48 | self._security_manager = SecurityManager() | |
49 | self._mappers_manager = MapperManager() | |
50 | self._changes_controller = ChangeController() | |
51 | self._db_manager = DbManager() | |
52 | ||
53 | self._model_controller = ModelController( | |
54 | self._security_manager, | |
55 | self._mappers_manager) | |
56 | ||
57 | self._plugin_manager = PluginManager( | |
58 | os.path.join(CONF.getConfigPath(), "plugins"), | |
59 | self._mappers_manager) | |
60 | ||
61 | self._reports_manager = ReportManager(10, self._plugin_manager.createController("ReportManager")) | |
62 | ||
63 | self._workspace_manager = WorkspaceManager( | |
64 | self._db_manager, | |
65 | self._mappers_manager, | |
66 | self._changes_controller, | |
67 | self._reports_manager) | |
68 | ||
69 | self.gui_app = UiFactory.create(self._model_controller, | |
70 | self._plugin_manager, | |
71 | self._workspace_manager, | |
72 | args.gui) | |
73 | ||
74 | self.gui_app.setSplashImage(os.path.join( | |
75 | CONF.getImagePath(), "splash2.png")) | |
76 | ||
77 | def enableExceptHook(self): | |
78 | sys.excepthook = exception_handler | |
79 | installThreadExcepthook() | |
80 | ||
81 | def disableLogin(self): | |
82 | CONF.setAuth(sys.disablelogin) | |
83 | ||
84 | def start(self): | |
85 | try: | |
86 | ||
87 | self.gui_app.startSplashScreen() | |
88 | self.gui_app.splashMessage("Starting Faraday") | |
89 | ||
90 | signal.signal(signal.SIGINT, self.ctrlC) | |
91 | ||
92 | logged = True | |
93 | ||
94 | while True: | |
95 | ||
96 | username, password = "usuario", "password" | |
97 | ||
98 | if username is None and password is None: | |
99 | break | |
100 | result = self._security_manager.authenticateUser(username, password) | |
101 | if result == codes.successfulLogin: | |
102 | logged = True | |
103 | break | |
104 | ||
105 | if logged: | |
106 | model.api.devlog("Starting application...") | |
107 | model.api.devlog("Setting up remote API's...") | |
108 | # We need to create the last used workspace (or the default | |
109 | # workspace) before we start the model controller and the | |
110 | # report manager | |
111 | ||
112 | last_workspace = CONF.getLastWorkspace() | |
113 | if not self._workspace_manager.workspaceExists(last_workspace): | |
114 | getLogger(self).info("Your last workspace ("+last_workspace+") wasn't accessible, check configuration...") | |
115 | self._workspace_manager.openDefaultWorkspace() | |
116 | #self._workspace_manager.createWorkspace(last_workspace, 'default workspace, probably created already in couchb') | |
117 | else: | |
118 | self._workspace_manager.openWorkspace(last_workspace) | |
119 | ||
120 | model.api.setUpAPIs( | |
121 | self._model_controller, | |
122 | self._workspace_manager, | |
123 | CONF.getApiConInfoHost(), | |
124 | CONF.getApiConInfoPort()) | |
125 | model.guiapi.setUpGUIAPIs(self._model_controller) | |
126 | ||
127 | model.api.devlog("Starting model controller daemon...") | |
128 | ||
129 | self._model_controller.start() | |
130 | model.api.startAPIServer() | |
131 | restapi.startAPIs( | |
132 | self._plugin_manager, | |
133 | self._model_controller, | |
134 | self._mappers_manager, | |
135 | CONF.getApiConInfoHost(), | |
136 | CONF.getApiRestfulConInfoPort()) | |
137 | # Start report manager here | |
138 | getLogger(self).debug("Starting Reports Manager Thread") | |
139 | self._reports_manager.startWatch() | |
140 | ||
141 | model.api.devlog("Faraday ready...") | |
142 | model.api.__current_logged_user = username | |
143 | ||
144 | self.gui_app.splashMessage("Loading workspace... Please wait.") | |
145 | ||
146 | self.gui_app.loadWorkspaces() | |
147 | ||
148 | self.gui_app.stopSplashScreen() | |
149 | ||
150 | except Exception: | |
151 | print "There was an error while starting Faraday" | |
152 | print "-" * 50 | |
153 | traceback.print_exc() | |
154 | print "-" * 50 | |
155 | self.__exit(-1) | |
156 | ||
157 | if logged: | |
158 | exit_code = self.gui_app.run([]) | |
159 | #exit_code = self.app.exec_loop() | |
160 | else: | |
161 | exit_code = -1 | |
162 | ||
163 | return self.__exit(exit_code) | |
164 | ||
165 | def __exit(self, exit_code=0): | |
166 | """ | |
167 | Exits the application with the provided code. | |
168 | It also waits until all app threads end. | |
169 | """ | |
170 | model.api.devlog("Closing Faraday...") | |
171 | model.api.devlog("stopping model controller thread...") | |
172 | model.api.stopAPIServer() | |
173 | restapi.stopServer() | |
174 | self._reports_manager.stop() | |
175 | self._changes_controller.stop() | |
176 | self._model_controller.stop() | |
177 | self._model_controller.join() | |
178 | self.gui_app.quit() | |
179 | model.api.devlog("Waiting for controller threads to end...") | |
180 | return exit_code | |
181 | ||
182 | def quit(self): | |
183 | """ | |
184 | Redefined quit handler to nicely end up things | |
185 | """ | |
186 | self.gui_app.quit() | |
187 | ||
188 | def ctrlC(self, signal, frame): | |
189 | getLogger(self).info("Exiting...") | |
190 | self.__exit(exit_code=0) | |
191 | ||
192 | def getWorkspaceManager(self): | |
193 | return self._workspace_manager | |
0 | #!/usr/bin/env python | |
1 | ''' | |
2 | Faraday Penetration Test IDE | |
3 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
4 | See the file 'doc/LICENSE' for the license information | |
5 | ||
6 | ''' | |
7 | import os | |
8 | import sys | |
9 | import signal | |
10 | import threading | |
11 | import requests | |
12 | ||
13 | # TODO: no seria mejor activar todo ? | |
14 | # XXX: something strange happens if we import | |
15 | # this module at the bottom of the list.... | |
16 | from auth.manager import SecurityManager | |
17 | from auth.manager import codes | |
18 | from model.controller import ModelController | |
19 | from persistence.persistence_managers import DbManager | |
20 | from controllers.change import ChangeController | |
21 | from managers.model_managers import WorkspaceManager | |
22 | import model.api | |
23 | import model.guiapi | |
24 | import apis.rest.api as restapi | |
25 | import model.log | |
26 | from utils.logs import getLogger | |
27 | import traceback | |
28 | from managers.all import PluginManager | |
29 | from managers.mapper_manager import MapperManager | |
30 | from managers.reports_managers import ReportManager | |
31 | ||
32 | from utils.error_report import exception_handler | |
33 | from utils.error_report import installThreadExcepthook | |
34 | ||
35 | from gui.gui_app import UiFactory | |
36 | ||
37 | from config.configuration import getInstanceConfiguration | |
38 | CONF = getInstanceConfiguration() | |
39 | ||
40 | ||
41 | class TimerClass(threading.Thread): | |
42 | def __init__(self): | |
43 | threading.Thread.__init__(self) | |
44 | self.__event = threading.Event() | |
45 | ||
46 | def run(self): | |
47 | while not self.__event.is_set(): | |
48 | try: | |
49 | res = requests.get( | |
50 | "https://www.faradaysec.com/scripts/updatedb.php", | |
51 | params={'version': CONF.getVersion()}, | |
52 | timeout=1, | |
53 | verify=True) | |
54 | res.status_code | |
55 | except Exception: | |
56 | model.api.devlog("CWE database couldn't be updated") | |
57 | self.__event.wait(43200) | |
58 | ||
59 | def stop(self): | |
60 | self.__event.set() | |
61 | ||
62 | ||
63 | class MainApplication(object): | |
64 | """ | |
65 | """ | |
66 | ||
67 | def __init__(self, args): | |
68 | self._original_excepthook = sys.excepthook | |
69 | ||
70 | self._configuration = CONF | |
71 | ||
72 | self._security_manager = SecurityManager() | |
73 | self._mappers_manager = MapperManager() | |
74 | self._changes_controller = ChangeController() | |
75 | self._db_manager = DbManager() | |
76 | ||
77 | self._model_controller = ModelController( | |
78 | self._security_manager, | |
79 | self._mappers_manager) | |
80 | ||
81 | self._plugin_manager = PluginManager( | |
82 | os.path.join(CONF.getConfigPath(), "plugins"), | |
83 | self._mappers_manager) | |
84 | ||
85 | self._reports_manager = ReportManager(10, self._plugin_manager.createController("ReportManager")) | |
86 | ||
87 | self._workspace_manager = WorkspaceManager( | |
88 | self._db_manager, | |
89 | self._mappers_manager, | |
90 | self._changes_controller, | |
91 | self._reports_manager) | |
92 | ||
93 | self.gui_app = UiFactory.create(self._model_controller, | |
94 | self._plugin_manager, | |
95 | self._workspace_manager, | |
96 | args.gui) | |
97 | ||
98 | self.gui_app.setSplashImage(os.path.join( | |
99 | CONF.getImagePath(), "splash2.png")) | |
100 | ||
101 | self.timer = TimerClass() | |
102 | self.timer.start() | |
103 | ||
104 | def enableExceptHook(self): | |
105 | sys.excepthook = exception_handler | |
106 | installThreadExcepthook() | |
107 | ||
108 | def disableLogin(self): | |
109 | CONF.setAuth(sys.disablelogin) | |
110 | ||
111 | def start(self): | |
112 | try: | |
113 | ||
114 | self.gui_app.startSplashScreen() | |
115 | self.gui_app.splashMessage("Starting Faraday") | |
116 | ||
117 | signal.signal(signal.SIGINT, self.ctrlC) | |
118 | ||
119 | logged = True | |
120 | ||
121 | while True: | |
122 | ||
123 | username, password = "usuario", "password" | |
124 | ||
125 | if username is None and password is None: | |
126 | break | |
127 | result = self._security_manager.authenticateUser(username, password) | |
128 | if result == codes.successfulLogin: | |
129 | logged = True | |
130 | break | |
131 | ||
132 | if logged: | |
133 | model.api.devlog("Starting application...") | |
134 | model.api.devlog("Setting up remote API's...") | |
135 | # We need to create the last used workspace (or the default | |
136 | # workspace) before we start the model controller and the | |
137 | # report manager | |
138 | ||
139 | last_workspace = CONF.getLastWorkspace() | |
140 | if not self._workspace_manager.workspaceExists(last_workspace): | |
141 | getLogger(self).info("Your last workspace ("+last_workspace+") wasn't accessible, check configuration...") | |
142 | self._workspace_manager.openDefaultWorkspace() | |
143 | #self._workspace_manager.createWorkspace(last_workspace, 'default workspace, probably created already in couchb') | |
144 | else: | |
145 | self._workspace_manager.openWorkspace(last_workspace) | |
146 | ||
147 | model.api.setUpAPIs( | |
148 | self._model_controller, | |
149 | self._workspace_manager, | |
150 | CONF.getApiConInfoHost(), | |
151 | CONF.getApiConInfoPort()) | |
152 | model.guiapi.setUpGUIAPIs(self._model_controller) | |
153 | ||
154 | model.api.devlog("Starting model controller daemon...") | |
155 | ||
156 | self._model_controller.start() | |
157 | model.api.startAPIServer() | |
158 | restapi.startAPIs( | |
159 | self._plugin_manager, | |
160 | self._model_controller, | |
161 | self._mappers_manager, | |
162 | CONF.getApiConInfoHost(), | |
163 | CONF.getApiRestfulConInfoPort()) | |
164 | # Start report manager here | |
165 | getLogger(self).debug("Starting Reports Manager Thread") | |
166 | self._reports_manager.startWatch() | |
167 | ||
168 | model.api.devlog("Faraday ready...") | |
169 | model.api.__current_logged_user = username | |
170 | ||
171 | self.gui_app.splashMessage("Loading workspace... Please wait.") | |
172 | ||
173 | self.gui_app.loadWorkspaces() | |
174 | ||
175 | self.gui_app.stopSplashScreen() | |
176 | ||
177 | except Exception: | |
178 | print "There was an error while starting Faraday" | |
179 | print "-" * 50 | |
180 | traceback.print_exc() | |
181 | print "-" * 50 | |
182 | self.__exit(-1) | |
183 | ||
184 | if logged: | |
185 | exit_code = self.gui_app.run([]) | |
186 | #exit_code = self.app.exec_loop() | |
187 | else: | |
188 | exit_code = -1 | |
189 | ||
190 | return self.__exit(exit_code) | |
191 | ||
192 | def __exit(self, exit_code=0): | |
193 | """ | |
194 | Exits the application with the provided code. | |
195 | It also waits until all app threads end. | |
196 | """ | |
197 | model.api.devlog("Closing Faraday...") | |
198 | model.api.devlog("stopping model controller thread...") | |
199 | model.api.stopAPIServer() | |
200 | restapi.stopServer() | |
201 | self._reports_manager.stop() | |
202 | self._changes_controller.stop() | |
203 | self._model_controller.stop() | |
204 | self._model_controller.join() | |
205 | self.gui_app.quit() | |
206 | self.timer.stop() | |
207 | model.api.devlog("Waiting for controller threads to end...") | |
208 | return exit_code | |
209 | ||
210 | def quit(self): | |
211 | """ | |
212 | Redefined quit handler to nicely end up things | |
213 | """ | |
214 | self.gui_app.quit() | |
215 | ||
216 | def ctrlC(self, signal, frame): | |
217 | getLogger(self).info("Exiting...") | |
218 | self.__exit(exit_code=0) | |
219 | ||
220 | def getWorkspaceManager(self): | |
221 | return self._workspace_manager |
23 | 23 | from model.hosts import Host, Interface, Service |
24 | 24 | |
25 | 25 | from model.commands_history import CommandRunInformation |
26 | from utils.common import sha1OfStr | |
26 | 27 | |
27 | 28 | from time import time |
28 | 29 | |
407 | 408 | |
408 | 409 | if self._active_plugin.has_custom_output(): |
409 | 410 | if not os.path.isfile(self._active_plugin.get_custom_file_path()): |
410 | model.api.devlog("PluginController output file (%s) not created" % self._active_plugin.get_custom_file_path()) | |
411 | model.api.devlog("Report file PluginController output file (%s) not created" % self._active_plugin.get_custom_file_path()) | |
411 | 412 | return False |
412 | 413 | output_file = open(self._active_plugin.get_custom_file_path(), 'r') |
413 | 414 | output = output_file.read() |
783 | 784 | |
784 | 785 | def run(self): |
785 | 786 | proc_name = self.name |
787 | plugin = self.plugin | |
786 | 788 | model.api.devlog("-" * 40) |
787 | 789 | model.api.devlog("proc_name = %s" % proc_name) |
788 | 790 | model.api.devlog("Starting run method on PluginProcess") |
795 | 797 | if output is not None: |
796 | 798 | model.api.devlog('%s: %s' % (proc_name, "New Output")) |
797 | 799 | try: |
800 | self.output = output | |
798 | 801 | self.plugin.parseOutputString(output) |
799 | 802 | except Exception as e: |
800 | ||
803 | print ('Plugin Error: %s, (%s)' % (plugin.id, sha1OfStr(output))) | |
804 | model.api.log('Plugin Error: %s, (%s)' % (plugin.id, sha1OfStr(output)),"DEBUG") | |
801 | 805 | model.api.devlog("Plugin raised an exception:") |
802 | 806 | model.api.devlog(traceback.format_exc()) |
803 | 807 | else: |
805 | 809 | try: |
806 | 810 | self.new_elem_queue.put(self.plugin._pending_actions.get(block=False)) |
807 | 811 | except Queue.Empty: |
812 | model.api.log('Plugin Error: %s, (%s)' % (plugin.id, sha1OfStr(output)),"DEBUG") | |
808 | 813 | model.api.devlog("PluginProcess run _pending_actions queue Empty. Breaking loop") |
809 | 814 | break |
810 | 815 | except Exception: |
816 | model.api.log('Plugin Error: %s, (%s)' % (plugin.id, sha1OfStr(output)),"DEBUG") | |
811 | 817 | model.api.devlog("PluginProcess run getting from _pending_action queue - something strange happened... unhandled exception?") |
812 | 818 | model.api.devlog(traceback.format_exc()) |
813 | 819 | break |
816 | 822 | |
817 | 823 | done = True |
818 | 824 | model.api.devlog('%s: Exiting' % proc_name) |
825 | model.api.log('Plugin finished: %s, (%s)' % (plugin.id, sha1OfStr(self.output)),"DEBUG") | |
826 | print ('Plugin finished: %s, (%s)' % (plugin.id, sha1OfStr(self.output))) | |
819 | 827 | |
820 | 828 | self.output_queue.task_done() |
821 | 829 | self.new_elem_queue.put(None) |
397 | 397 | |
398 | 398 | |
399 | 399 | for issue in parser.issues: |
400 | print dir(issue) | |
401 | 400 | |
402 | 401 | desc=issue.description |
403 | 402 | desc+="\nSolution: " + issue.remedy_guidance if issue.remedy_guidance !="None" else "" |
194 | 194 | for item in parser.items: |
195 | 195 | if item['ip'] == "127.0.0.1" or item['ip'] == '': |
196 | 196 | continue |
197 | print "agregando (%s) (%s)" % (item['host'],item['ip']) | |
198 | 197 | h_id = self.createAndAddHost(item['ip']) |
199 | 198 | i_id = self.createAndAddInterface(h_id, item['ip'], ipv4_address= item['ip'], hostname_resolution = [item['host']]) |
200 | 199 | if item['isResolver']: |
84 | 84 | ports = [self._port], |
85 | 85 | status = "open") |
86 | 86 | |
87 | ||
88 | ||
89 | ||
90 | print ("Host detected: %s" % ip_address) | |
91 | ||
92 | api.log("New host detected: %s" % ip_address) | |
93 | 87 | if debug is True: |
94 | 88 | api.devlog("Debug is active") |
95 | 89 |
370 | 370 | self.createAndAddNoteToHost(h_id,n.ntype,n.data) |
371 | 371 | |
372 | 372 | for v in item.vulnsByHost: |
373 | print (h_id, v.name, v.desc, v.refs) | |
374 | 373 | v_id = self.createAndAddVulnToHost(h_id, v.name, v.desc, ref=v.refs) |
375 | 374 | |
376 | 375 | |
377 | 376 | for s in item.services: |
378 | print (h_id, i_id , s['name'], | |
379 | s['proto'], | |
380 | [s['port']], | |
381 | s['state'], | |
382 | s['info']) | |
383 | 377 | s_id = self.createAndAddServiceToInterface(h_id, i_id , s['name'], |
384 | 378 | s['proto'], |
385 | 379 | ports = [s['port']], |
393 | 387 | |
394 | 388 | if s['port'] in item.credsByService: |
395 | 389 | for c in item.credsByService[s['port']]: |
396 | print "CREDS" | |
397 | print (h_id,s_id,s['port'],c.user,c.passwd) | |
398 | 390 | self.createAndAddCredToService(h_id,s_id,c.user,c.passwd) |
399 | 391 | |
400 | 392 | n_id = None |
409 | 401 | pname=v.pname, params=v.params, query=v.query, |
410 | 402 | category=v.category) |
411 | 403 | else: |
412 | print (h_id, s_id, v.name, v.desc, v.refs) | |
413 | 404 | v_id = self.createAndAddVulnToService(h_id, s_id, v.name, v.desc, ref=v.refs) |
414 | 405 | |
415 | 406 |
108 | 108 | if not os.path.exists(self._output_file_path): |
109 | 109 | return False |
110 | 110 | parser = SslcheckParser(self._output_file_path) |
111 | print parser.result | |
112 | print parser.hostinfo | |
111 | # print parser.result | |
112 | # print parser.hostinfo | |
113 | 113 | for host in parser.result: |
114 | 114 | h_id = self.createAndAddHost(host) |
115 | 115 | if(re.match("(^[2][0-5][0-5]|^[1]{0,1}[0-9]{1,2})\.([0-2][0-5][0-5]|[1]{0,1}[0-9]{1,2})\.([0-2][0-5][0-5]|[1]{0,1}[0-9]{1,2})\.([0-2][0-5][0-5]|[1]{0,1}[0-9]{1,2})$" |
157 | 157 | self.detail = self.get_text_from_subnode('description') |
158 | 158 | self.severity = self.node.get('severity') |
159 | 159 | self.method = self.node.get('method') |
160 | self.param = self.node.get('var') if self.node.get('var') != "None" else "" | |
160 | 161 | self.req = self.resp = '' |
161 | 162 | for tx in self.node.findall('http-transactions/http-transaction'): |
162 | 163 | |
227 | 228 | |
228 | 229 | for item in parser.items: |
229 | 230 | v_id = self.createAndAddVulnWebToService(h_id, s_id, item.name, |
230 | item.detail, website=parser.host, severity=item.severity, | |
231 | item.detail, pname=item.param, path=item.url, website=parser.host, severity=item.severity, | |
231 | 232 | method=item.method, request=item.req, response=item.resp) |
232 | 233 | del parser |
233 | 234 |
273 | 273 | i=1; |
274 | 274 | for item in parser.items: |
275 | 275 | mport = "%s%i" % (self.port,i) |
276 | print "estoy recorriendo algo ? (%s) (%s) (%s) (%s) (%s) (%s)" % (item.url,item.info,item.parameter,self.port,self.protocol,self.host) | |
277 | 276 | s_id = self.createAndAddServiceToInterface(h_id, i_id, mport, |
278 | 277 | "tcp", |
279 | 278 | [mport], |
176 | 176 | |
177 | 177 | def parseOutputString(self, output, debug = False): |
178 | 178 | |
179 | ||
180 | print "X1 testing" | |
179 | ||
181 | 180 | parser = X1XmlParser(output) |
182 | 181 | for item in parser.items: |
183 | 182 | h_id = self.createAndAddHost(item.host,item.name) |
517 | 517 | }); |
518 | 518 | }); |
519 | 519 | }); |
520 | ||
521 | ||
522 | describe('statusReportCtrl check all function', function() { | |
523 | var $controller, | |
524 | $scope; | |
525 | ||
526 | var $vulnsManager, | |
527 | vulnsManagerMock, | |
528 | $workspacesFact, | |
529 | workspacesFactMock; | |
530 | ||
531 | var returnPromise; | |
532 | ||
533 | beforeEach(function () { | |
534 | module('faradayApp'); | |
535 | ||
536 | inject(function(_$rootScope_, _$controller_, _$q_, _$modal_) { | |
537 | // The injector unwraps the underscores (_) from around the parameter names when matching | |
538 | $scope = _$rootScope_.$new(); | |
539 | // workspaces variables | |
540 | ||
541 | returnPromise = function(res) { | |
542 | var deferred = _$q_.defer(); | |
543 | deferred.resolve(res); | |
544 | return deferred.promise; | |
545 | } | |
546 | ||
547 | rejectPromise = function(res) { | |
548 | var deferred = _$q_.defer(); | |
549 | deferred.reject(res); | |
550 | return deferred.promise; | |
551 | } | |
552 | ||
553 | workspacesFactMock = { | |
554 | list: function() { | |
555 | return returnPromise(['ws1', 'ws2']) | |
556 | } | |
557 | } | |
558 | ||
559 | vulnsManagerMock = { | |
560 | vulns: [], | |
561 | getVulns: function(workspace) { | |
562 | vulnsManagerMock.vulns = []; | |
563 | for (var i=0; i < 10; i++) { | |
564 | var vuln1 = { | |
565 | "_id": "1.2.3." + i, | |
566 | "_rev": "1-abe16726389e434ca3f37384ea76128e", | |
567 | "name": "vuln " + i, | |
568 | "parent": "1.2.3", | |
569 | "resolution": "Be careful", | |
570 | "refs": [ | |
571 | "CVE-2002-1623", | |
572 | "7423", | |
573 | "OSVDB:3820, CERT:886601" | |
574 | ], | |
575 | "metadata": { | |
576 | "update_time": 1429643049.395857, | |
577 | "update_user": "john", | |
578 | "update_action": 0, | |
579 | "creator": "john", | |
580 | "create_time": 1429643049.395857 + i, | |
581 | "update_controller_action": "ModelControler.newVuln", | |
582 | "owner": "john" | |
583 | }, | |
584 | "owned": false, | |
585 | "severity": "med", | |
586 | "type": "Vulnerability", | |
587 | "owner": "john", | |
588 | "desc": "I'm scared!", | |
589 | "data": "", | |
590 | "description": "I'm scared!" | |
591 | }; | |
592 | var vuln2 = { | |
593 | "_id": "2.2.3." + i, | |
594 | "_rev": "1-abe16726389e434ca3f37384ea76128e", | |
595 | "name": "vuln " + i, | |
596 | "parent": "2.2.3", | |
597 | "resolution": "Be careful", | |
598 | "refs": [ | |
599 | "CVE-2002-1623", | |
600 | "7423", | |
601 | "OSVDB:3820, CERT:886601" | |
602 | ], | |
603 | "metadata": { | |
604 | "update_time": 1429643049.395857, | |
605 | "update_user": "john", | |
606 | "update_action": 0, | |
607 | "creator": "john", | |
608 | "create_time": 1429643049.395857 + i + 10, | |
609 | "update_controller_action": "ModelControler.newVuln", | |
610 | "owner": "john" | |
611 | }, | |
612 | "owned": false, | |
613 | "severity": "high", | |
614 | "type": "Vulnerability", | |
615 | "owner": "john", | |
616 | "desc": "I'm scared!", | |
617 | "data": "", | |
618 | "description": "I'm scared!" | |
619 | }; | |
620 | vulnsManagerMock.vulns.push(vuln1); | |
621 | vulnsManagerMock.vulns.push(vuln2); | |
622 | } | |
623 | return returnPromise(vulnsManagerMock.vulns); | |
624 | } | |
625 | }; | |
626 | ||
627 | $controller = _$controller_('statusReportCtrl', { | |
628 | $scope: $scope, | |
629 | vulnsManager: vulnsManagerMock, | |
630 | hostsManager: {}, | |
631 | workspacesFact: workspacesFactMock, | |
632 | $routeParams: {wsId: 'ws1'}, | |
633 | $modal: _$modal_ | |
634 | }); | |
635 | }); | |
636 | }); | |
637 | ||
638 | describe('sort properly', function() { | |
639 | beforeEach(function() { | |
640 | $scope.selectall = false; | |
641 | $scope.reverse = false; | |
642 | $scope.pageSize = 5; | |
643 | // we set the sort field to make sure that | |
644 | // vulns are in the same order in every test | |
645 | $scope.sortField = "metadata.create_time"; | |
646 | search_elem = function(aVulns, id){ | |
647 | for(var i=0; i < aVulns.length; i++){ | |
648 | if (aVulns[i]._id == id) { | |
649 | return aVulns[i]; | |
650 | } | |
651 | } | |
652 | return {}; | |
653 | }; | |
654 | }); | |
655 | it('when current page is 0', function() { | |
656 | $scope.currentPage = 0; | |
657 | $scope.$apply(); | |
658 | $scope.checkAll(); | |
659 | ||
660 | $scope.vulns.forEach(function(v) { | |
661 | if(v._id === "1.2.3.0" || v._id === "1.2.3.1" || v._id === "1.2.3.2" || v._id === "1.2.3.3" || v._id === "1.2.3.4") { | |
662 | expect(search_elem($scope.vulns, v._id).selected_statusreport_controller).toEqual(true); | |
663 | } else { | |
664 | expect(search_elem($scope.vulns, v._id).selected_statusreport_controller).not.toEqual(true); | |
665 | } | |
666 | }); | |
667 | }); | |
668 | it('when current page is 1', function() { | |
669 | $scope.currentPage = 1; | |
670 | $scope.$apply(); | |
671 | $scope.checkAll(); | |
672 | ||
673 | $scope.vulns.forEach(function(v) { | |
674 | if(v._id === "1.2.3.5" || v._id === "1.2.3.6" || v._id === "1.2.3.7" || v._id === "1.2.3.8" || v._id === "1.2.3.9") { | |
675 | expect(search_elem($scope.vulns, v._id).selected_statusreport_controller).toEqual(true); | |
676 | } else { | |
677 | expect(search_elem($scope.vulns, v._id).selected_statusreport_controller).not.toEqual(true); | |
678 | } | |
679 | }); | |
680 | }); | |
681 | it('when current page is 0 and filtering', function() { | |
682 | $scope.currentPage = 0; | |
683 | $scope.expression = {severity:"med"}; | |
684 | $scope.$apply(); | |
685 | $scope.checkAll(); | |
686 | ||
687 | $scope.vulns.forEach(function(v) { | |
688 | if(v._id === "1.2.3.0" || v._id === "1.2.3.1" || v._id === "1.2.3.2" || v._id === "1.2.3.3" || v._id === "1.2.3.4") { | |
689 | expect(search_elem($scope.vulns, v._id).selected_statusreport_controller).toEqual(true); | |
690 | } else { | |
691 | expect(search_elem($scope.vulns, v._id).selected_statusreport_controller).not.toEqual(true); | |
692 | } | |
693 | }); | |
694 | }); | |
695 | it('when current page is 1 and filtering', function() { | |
696 | $scope.currentPage = 1; | |
697 | $scope.expression = {severity:"high"}; | |
698 | $scope.$apply(); | |
699 | $scope.checkAll(); | |
700 | ||
701 | $scope.vulns.forEach(function(v) { | |
702 | if(v._id === "2.2.3.5" || v._id === "2.2.3.6" || v._id === "2.2.3.7" || v._id === "2.2.3.8" || v._id === "2.2.3.9") { | |
703 | expect(search_elem($scope.vulns, v._id).selected_statusreport_controller).toEqual(true); | |
704 | } else { | |
705 | expect(search_elem($scope.vulns, v._id).selected_statusreport_controller).not.toEqual(true); | |
706 | } | |
707 | }); | |
708 | }); | |
709 | it('when page size is the total of vulns', function() { | |
710 | $scope.currentPage = 0; | |
711 | $scope.pageSize = 20; | |
712 | $scope.expression = {severity:"high"}; | |
713 | $scope.$apply(); | |
714 | $scope.checkAll(); | |
715 | ||
716 | $scope.vulns.forEach(function(v) { | |
717 | if(v._id.split(".")[0] === "2") { | |
718 | expect(search_elem($scope.vulns, v._id).selected_statusreport_controller).toEqual(true); | |
719 | } else { | |
720 | expect(search_elem($scope.vulns, v._id).selected_statusreport_controller).not.toEqual(true); | |
721 | } | |
722 | }); | |
723 | }); | |
724 | }); | |
725 | ||
726 | }); |
2 | 2 | // See the file 'doc/LICENSE' for the license information |
3 | 3 | |
4 | 4 | describe('vulnsManager', function() { |
5 | // Declare dependencies | |
5 | 6 | var vulnsManager, |
6 | 7 | Vuln, |
7 | 8 | WebVuln, |
8 | hostsManager, | |
9 | $filter, | |
9 | hostsManager; | |
10 | ||
11 | var $filter, | |
10 | 12 | $httpBackend, |
11 | 13 | $q, |
12 | BASEURL, | |
13 | vuln1, | |
14 | hosts, interfaces, | |
14 | BASEURL; | |
15 | ||
16 | // Declare data | |
17 | var vuln1, | |
18 | couchVuln1, | |
19 | vuln2, | |
20 | couchVuln2, | |
21 | couchVulnEmpty; | |
22 | ||
23 | var hosts, interfaces, | |
15 | 24 | hostnames = []; |
16 | 25 | |
17 | 26 | // Set up the module |
18 | 27 | beforeEach(module('faradayApp')); |
19 | 28 | |
20 | beforeEach(inject(function($injector, _vulnsManager_, _Vuln_, _WebVuln_) { | |
21 | ||
29 | // Initialize data | |
30 | beforeEach(function() { | |
22 | 31 | vuln1 = { |
23 | 32 | "_id": "1.e29ba38bfa81e7f9050f6517babc14cf32cacdff", |
24 | 33 | "_rev": "1-abe16726389e434ca3f37384ea76128e", |
57 | 66 | "ws": "ws" |
58 | 67 | }; |
59 | 68 | |
60 | hosts = { | |
69 | couchVuln1 = { | |
61 | 70 | "total_rows": 1, |
62 | 71 | "offset": 0, |
63 | "rows": [ | |
72 | "rows":[ | |
64 | 73 | { |
65 | "_id": "1", | |
66 | "value": { | |
67 | "name": "Host parent" | |
68 | } | |
74 | "id": "1.2.3.8b4ffaedb84dd60d5f43c58eba66a7651458c8de", | |
75 | "key":"4b84b15bff6ee5796152495a230e45e3d7e947d9.34ac3ea37a2854ce00f2d97c648bf3a7cc27ebca", | |
76 | "value": vuln1 | |
69 | 77 | } |
70 | 78 | ] |
71 | 79 | }; |
72 | 80 | |
73 | interfaces = { | |
74 | "total_rows": 3, | |
75 | "offset": 0, | |
76 | "rows": [ | |
81 | vuln2 = { | |
82 | "_id": "1.e29ba38bfa81e7f9050f6517babc14cf32cacdff", | |
83 | "_rev": "1-abe16726389e434ca3f37384ea76128e", | |
84 | "desc": "Hello World!", | |
85 | "data": "", | |
86 | "metadata": { | |
87 | "update_time": 1429643049.395857, | |
88 | "update_user": "", | |
89 | "update_action": 0, | |
90 | "creator": "UI Web", | |
91 | "create_time": 1429643049.395857, | |
92 | "update_controller_action": "ModelControler.newVuln", | |
93 | "owner": "" | |
94 | }, | |
95 | "name": "Something something dark side", | |
96 | "owned": false, | |
97 | "owner": "john", | |
98 | "parent": "1", | |
99 | "resolution": "Be careful", | |
100 | "refs": [ | |
101 | "CVE-2002-1623", | |
102 | "7423", | |
103 | "OSVDB:3820, CERT:886601" | |
104 | ], | |
105 | "severity": "med", | |
106 | "type": "Vulnerability", | |
107 | "ws": "ws" | |
108 | }; | |
109 | ||
110 | couchVuln2 = { | |
111 | "total_rows":1, | |
112 | "offset":0, | |
113 | "rows":[ | |
77 | 114 | { |
78 | "_id": "1.2", | |
79 | "value": { | |
80 | "parent": "1", | |
81 | "hostnames": [ | |
82 | "h21", | |
83 | "h22", | |
84 | "h23" | |
85 | ] | |
86 | } | |
87 | }, { | |
88 | "_id": "1.3", | |
89 | "value": { | |
90 | "parent": "1", | |
91 | "hostnames": [ | |
92 | "h31", | |
93 | "h32", | |
94 | "h33" | |
95 | ] | |
96 | } | |
97 | }, { | |
98 | "_id": "1.4", | |
99 | "value": { | |
100 | "parent": "1", | |
101 | "hostnames": [ | |
102 | "h41", | |
103 | "h42", | |
104 | "h43" | |
105 | ] | |
106 | } | |
115 | "id": "1.2.3.8b4ffaedb84dd60d5f43c58eba66a7651458c8de", | |
116 | "key":"4b84b15bff6ee5796152495a230e45e3d7e947d9.34ac3ea37a2854ce00f2d97c648bf3a7cc27ebca", | |
117 | "value": vuln2 | |
107 | 118 | } |
108 | 119 | ] |
109 | 120 | }; |
110 | 121 | |
111 | interfaces.rows.forEach(function(interf) { | |
112 | hostnames = hostnames.concat(interf.value.hostnames); | |
113 | }); | |
114 | ||
115 | hostsManagerMock = { | |
122 | couchVulnEmpty = { | |
123 | "total_rows":0, | |
124 | "offset":0, | |
125 | "rows":[] | |
126 | }; | |
127 | ||
128 | hosts = [ | |
129 | { | |
130 | "_id": "1", | |
131 | "name": "Host parent" | |
132 | } | |
133 | ]; | |
134 | ||
135 | interfaces = [ | |
136 | { | |
137 | "parent": "1", | |
138 | "hostnames": [ | |
139 | "h21", | |
140 | "h22", | |
141 | "h23" | |
142 | ] | |
143 | }, { | |
144 | "parent": "1", | |
145 | "hostnames": [ | |
146 | "h31", | |
147 | "h32", | |
148 | "h33" | |
149 | ] | |
150 | }, { | |
151 | "parent": "1", | |
152 | "hostnames": [ | |
153 | "h41", | |
154 | "h42", | |
155 | "h43" | |
156 | ] | |
157 | } | |
158 | ]; | |
159 | ||
160 | interfaces.forEach(function(interf) { | |
161 | interf.hostnames.forEach(function(hostname) { | |
162 | if(hostnames.indexOf(hostname) < 0) hostnames.push(hostname); | |
163 | }); | |
164 | }); | |
165 | }); | |
166 | ||
167 | // Initialize dependencies | |
168 | //beforeEach(inject(function($injector, _vulnsManager_, _Vuln_, _WebVuln_, _$filter_, _$httpBackend_, _$q_) { | |
169 | beforeEach(function() { | |
170 | var hostsManagerMock = { | |
116 | 171 | getHosts: function(ws) { |
117 | var deferred = _$q_.defer(); | |
172 | var deferred = $q.defer(); | |
118 | 173 | deferred.resolve(hosts); |
119 | 174 | return deferred.promise; |
120 | 175 | }, |
121 | getallInterfaces: function() { | |
122 | var deferred = _$q_.defer(); | |
176 | getAllInterfaces: function() { | |
177 | var deferred = $q.defer(); | |
123 | 178 | deferred.resolve(interfaces); |
124 | 179 | return deferred.promise; |
125 | 180 | } |
126 | 181 | }; |
127 | 182 | |
128 | $filter = $injector.get('$filter'); | |
129 | $httpBackend = $injector.get('$httpBackend'); | |
130 | $q = $injector.get('$q'); | |
131 | $rootScope = $injector.get('$rootScope'); | |
132 | hostsManager = hostsManagerMock; | |
133 | vulnsManager = _vulnsManager_; | |
134 | Vuln = _Vuln_; | |
135 | WebVuln = _WebVuln_; | |
136 | BASEURL = 'http://localhost:9876/'; | |
137 | })); | |
183 | module(function($provide) { | |
184 | $provide.factory('hostsManager', function($q) { return hostsManagerMock; }); | |
185 | }); | |
186 | ||
187 | inject(function(_vulnsManager_, _Vuln_, _WebVuln_, _$filter_, _$httpBackend_, _$q_, _hostsManager_) { | |
188 | $filter = _$filter_; | |
189 | $httpBackend = _$httpBackend_; | |
190 | $q = _$q_; | |
191 | vulnsManager = _vulnsManager_; | |
192 | Vuln = _Vuln_; | |
193 | WebVuln = _WebVuln_; | |
194 | hostsManager = _hostsManager_; | |
195 | BASEURL = 'http://localhost:9876/'; | |
196 | }); | |
197 | ||
198 | }); | |
138 | 199 | |
139 | 200 | afterEach(function() { |
140 | 201 | $httpBackend.verifyNoOutstandingExpectation(); |
143 | 204 | |
144 | 205 | describe('Basic usage', function() { |
145 | 206 | it('getVulns', function() { |
146 | var vuln = { | |
147 | "total_rows": 1, | |
148 | "offset": 0, | |
149 | "rows":[ | |
150 | { | |
151 | "id": "1.2.3.8b4ffaedb84dd60d5f43c58eba66a7651458c8de", | |
152 | "key":"4b84b15bff6ee5796152495a230e45e3d7e947d9.34ac3ea37a2854ce00f2d97c648bf3a7cc27ebca", | |
153 | "value": vuln1 | |
154 | } | |
155 | ] | |
156 | }; | |
157 | ||
158 | ||
159 | 207 | var vulns; |
160 | 208 | |
161 | $httpBackend.expect('GET', BASEURL + 'ws/_design/vulns/_view/all').respond(200, vuln); | |
162 | $httpBackend.expect('GET', BASEURL + 'ws/_design/hosts/_view/hosts').respond(200, hosts); | |
163 | $httpBackend.expect('GET', BASEURL + 'ws/_design/interfaces/_view/interfaces').respond(200, interfaces); | |
209 | $httpBackend.expect('GET', BASEURL + 'ws/_design/vulns/_view/all').respond(200, couchVuln1); | |
164 | 210 | |
165 | 211 | vulnsManager.getVulns("ws") |
166 | 212 | .then(function(vs) { |
177 | 223 | for(var prop in vuln1) { |
178 | 224 | expect(v[prop]).toEqual(vuln1[prop]); |
179 | 225 | } |
180 | expect(v["target"]).toEqual(hosts.rows[0].value.name); | |
226 | expect(v["target"]).toEqual(hosts[0].name); | |
181 | 227 | expect(v["hostnames"]).toEqual(hostnames); |
182 | 228 | }); |
183 | 229 | |
186 | 232 | for(var prop in vuln1) { |
187 | 233 | expect(v[prop]).toEqual(vuln1[prop]); |
188 | 234 | } |
189 | expect(v["target"]).toEqual(hosts.rows[0].value.name); | |
235 | expect(v["target"]).toEqual(hosts[0].name); | |
190 | 236 | expect(v["hostnames"]).toEqual(hostnames); |
191 | 237 | }); |
192 | 238 | }); |
194 | 240 | it('createVuln', function() { |
195 | 241 | var id = vuln1._id, |
196 | 242 | vuln = vuln1; |
243 | ||
197 | 244 | delete vuln._id; |
198 | 245 | delete vuln._rev; |
199 | 246 | |
200 | var resp = { | |
201 | "total_rows":1, | |
202 | "offset":0, | |
203 | "rows":[ | |
204 | { | |
205 | "id": "1.2.3.8b4ffaedb84dd60d5f43c58eba66a7651458c8de", | |
206 | "key":"4b84b15bff6ee5796152495a230e45e3d7e947d9.34ac3ea37a2854ce00f2d97c648bf3a7cc27ebca", | |
207 | "value": vuln1 | |
208 | } | |
209 | ] | |
210 | }; | |
211 | ||
212 | 247 | var vulns = []; |
213 | 248 | |
214 | 249 | // insert new vuln in Couch |
215 | 250 | $httpBackend.expect('PUT', BASEURL + "ws/" + id).respond(201, {"rev": "1234"}); |
216 | $httpBackend.expect('GET', BASEURL + 'ws/_design/hosts/_view/hosts').respond(200, hosts); | |
217 | $httpBackend.expect('GET', BASEURL + 'ws/_design/interfaces/_view/interfaces').respond(200, interfaces); | |
218 | ||
219 | var lala = vulnsManager.createVuln("ws", vuln); | |
220 | ||
221 | $httpBackend.flush(); | |
222 | $rootScope.$apply(); | |
223 | ||
224 | expect(vulns.length).toEqual(1); | |
225 | expect(vulns[0]._id).toEqual(id); | |
251 | ||
252 | vulnsManager.createVuln("ws", vuln) | |
253 | .then(function(vs) { | |
254 | vulns = vs; | |
255 | }); | |
256 | ||
257 | $httpBackend.flush(); | |
258 | ||
259 | expect(vulnsManager.vulns.length).toEqual(1); | |
226 | 260 | expect(vulnsManager.vulns[0]._id).toEqual(id); |
261 | vulnsManager.vulns.forEach(function(v) { | |
262 | for(var prop in vuln1) { | |
263 | if(prop !== "metadata") expect(v[prop]).toEqual(vuln1[prop]); | |
264 | } | |
265 | expect(v["target"]).toEqual(hosts[0].name); | |
266 | expect(v["hostnames"]).toEqual(hostnames); | |
267 | }); | |
227 | 268 | }); |
228 | 269 | |
229 | 270 | it('deleteVuln', function() { |
232 | 273 | delete vuln._id; |
233 | 274 | delete vuln._rev; |
234 | 275 | |
235 | var respInsert = { | |
236 | "total_rows":1, | |
237 | "offset":0, | |
238 | "rows":[ | |
239 | { | |
240 | "id": "1.2.3.8b4ffaedb84dd60d5f43c58eba66a7651458c8de", | |
241 | "key":"4b84b15bff6ee5796152495a230e45e3d7e947d9.34ac3ea37a2854ce00f2d97c648bf3a7cc27ebca", | |
242 | "value": vuln1 | |
243 | } | |
244 | ] | |
245 | }; | |
246 | ||
247 | var respDelete = { | |
248 | "total_rows":0, | |
249 | "offset":0, | |
250 | "rows":[] | |
251 | }; | |
252 | ||
253 | 276 | // insert new vuln in Couch |
254 | 277 | $httpBackend.expect('PUT', BASEURL + "ws/" + id).respond(201, {"rev": vuln1._rev}); |
255 | // getVulns | |
256 | $httpBackend.expect('GET', BASEURL + 'ws/_design/vulns/_view/all').respond(200, respInsert); | |
257 | 278 | |
258 | 279 | vulnsManager.createVuln("ws", vuln); |
259 | 280 | |
261 | 282 | |
262 | 283 | // delete vuln |
263 | 284 | $httpBackend.expect('DELETE', BASEURL + 'ws/' + id + "?rev=" + vuln1._rev).respond(200); |
264 | // getVulns | |
265 | $httpBackend.expect('GET', BASEURL + 'ws/_design/vulns/_view/all').respond(200, respDelete); | |
266 | 285 | |
267 | vulnsManager.deleteVuln("ws", vulnsManager.vulns[0]); | |
286 | vulnsManager.deleteVuln(vulnsManager.vulns[0]); | |
268 | 287 | $httpBackend.flush(); |
269 | 288 | |
270 | 289 | expect(vulnsManager.vulns.length).toEqual(0); |
276 | 295 | delete vuln._id; |
277 | 296 | delete vuln._rev; |
278 | 297 | |
279 | var vulnMod = { | |
280 | "_id": "1.2.3.e29ba38bfa81e7f9050f6517babc14cf32cacdff", | |
281 | "_rev": "1-abe16726389e434ca3f37384ea76128e", | |
282 | "desc": "Hello World!", | |
283 | "data": "", | |
284 | "metadata": { | |
285 | "update_time": 1429643049.395857, | |
286 | "update_user": "", | |
287 | "update_action": 0, | |
288 | "creator": "UI Web", | |
289 | "create_time": 1429643049.395857, | |
290 | "update_controller_action": "ModelControler.newVuln", | |
291 | "owner": "" | |
292 | }, | |
293 | "name": "Something something dark side", | |
294 | "owned": false, | |
295 | "owner": "", | |
296 | "parent": "1.2.3", | |
297 | "resolution": "Be careful", | |
298 | "refs": [ | |
299 | "CVE-2002-1623", | |
300 | "7423", | |
301 | "OSVDB:3820, CERT:886601" | |
302 | ], | |
303 | "severity": "med", | |
304 | "type": "Vulnerability", | |
305 | "ws": "ws" | |
306 | }; | |
307 | ||
308 | var respInsert = { | |
309 | "total_rows":1, | |
310 | "offset":0, | |
311 | "rows":[ | |
312 | { | |
313 | "id": "1.2.3.8b4ffaedb84dd60d5f43c58eba66a7651458c8de", | |
314 | "key":"4b84b15bff6ee5796152495a230e45e3d7e947d9.34ac3ea37a2854ce00f2d97c648bf3a7cc27ebca", | |
315 | "value": vuln1 | |
316 | } | |
317 | ] | |
318 | }; | |
319 | ||
320 | var respUpdate = { | |
321 | "total_rows":1, | |
322 | "offset":0, | |
323 | "rows":[ | |
324 | { | |
325 | "id": "1.2.3.8b4ffaedb84dd60d5f43c58eba66a7651458c8de", | |
326 | "key":"4b84b15bff6ee5796152495a230e45e3d7e947d9.34ac3ea37a2854ce00f2d97c648bf3a7cc27ebca", | |
327 | "value": vulnMod | |
328 | } | |
329 | ] | |
330 | }; | |
331 | ||
332 | 298 | // insert new vuln in Couch |
333 | 299 | $httpBackend.expect('PUT', BASEURL + "ws/" + id).respond(201, {"rev": "1234"}); |
334 | // getVulns | |
335 | $httpBackend.expect('GET', BASEURL + 'ws/_design/vulns/_view/all').respond(200, respInsert); | |
336 | 300 | // call to insert |
337 | 301 | vulnsManager.createVuln("ws", vuln); |
338 | 302 | $httpBackend.flush(); |
339 | 303 | |
340 | 304 | // update vuln |
341 | $httpBackend.expect('PUT', BASEURL + 'ws/' + id).respond(200, {"rev": "2345"}); | |
342 | // getVulns | |
343 | $httpBackend.expect('GET', BASEURL + 'ws/_design/vulns/_view/all').respond(200, respUpdate); | |
305 | $httpBackend.expect('PUT', BASEURL + 'ws/' + id).respond(200, {"rev": "1-abe16726389e434ca3f37384ea76128e"}); | |
344 | 306 | |
345 | var vulns = vulnsManager.updateVuln(vuln.ws, vulnsManager.vulns[0], vulnMod); | |
307 | var vulns = vulnsManager.updateVuln(vulnsManager.vulns[0], vuln2); | |
346 | 308 | $httpBackend.flush(); |
347 | 309 | |
348 | 310 | expect(vulnsManager.vulns.length).toEqual(1); |
349 | 311 | |
350 | for(var prop in vulnMod) { | |
351 | if(vulnMod.hasOwnProperty(prop)) { | |
352 | if(prop != "metadata") expect(vulnsManager.vulns[0][prop]).toEqual(vulnMod[prop]); | |
312 | for(var prop in vuln2) { | |
313 | if(vuln2.hasOwnProperty(prop)) { | |
314 | if(prop != "metadata") expect(vulnsManager.vulns[0][prop]).toEqual(vuln2[prop]); | |
353 | 315 | } |
354 | 316 | } |
355 | 317 | }); |
10 | 10 | import struct |
11 | 11 | import sys |
12 | 12 | import requests |
13 | ||
14 | def sha1OfFile(filepath): | |
15 | with open(filepath, 'rb') as f: | |
16 | return hashlib.sha1(f.read()).hexdigest() | |
17 | ||
18 | def sha1OfStr(strvalue): | |
19 | return hashlib.sha1(strvalue).hexdigest() | |
13 | 20 | |
14 | 21 | def get_hash(parts): |
15 | 22 |
908 | 908 | white-space: -webkit-pre-wrap; /* Newer versions of Chrome/Safari*/ |
909 | 909 | word-break: break-all; |
910 | 910 | white-space: normal; |
911 | }⏎ | |
911 | } | |
912 | #counter{ | |
913 | font-size: 12px; | |
914 | position: fixed; | |
915 | background: #999; | |
916 | opacity: 0.6; | |
917 | color: #FFF; | |
918 | display: block; | |
919 | right: 0px; | |
920 | border-radius: 7px 0px 0px 7px; | |
921 | padding: 5px; | |
922 | bottom: 40px; | |
923 | text-decoration: none!important; | |
924 | z-index: 100000; | |
925 | -webkit-transition: opacity 0.5s ease-out; | |
926 | -moz-transition: opacity 0.5s ease-out; | |
927 | -o-transition: opacity 0.5s ease-out; | |
928 | transition: opacity 0.5s ease-out; | |
929 | cursor: default; | |
930 | } | |
931 | #counter:hover{ | |
932 | opacity: 0; | |
933 | } | |
934 | .counterNum{ | |
935 | font-size: 15px; | |
936 | font-weight: bold; | |
937 | } | |
938 | .text-center{text-align: center; width: 25px;} |
73 | 73 | <script type="text/javascript" src="scripts/commons/filters/orderObjectBy.js"></script> |
74 | 74 | <script type="text/javascript" src="scripts/commons/filters/startFrom.js"></script> |
75 | 75 | <script type="text/javascript" src="scripts/commons/filters/integer.js"></script> |
76 | <script type="text/javascript" src="scripts/csv/providers/csv.js"></script> | |
76 | 77 | <script type="text/javascript" src="scripts/fileExporter/directives/download.js"></script> |
77 | 78 | <script type="text/javascript" src="scripts/fileExporter/providers/blob.js"></script> |
78 | 79 | <script type="text/javascript" src="scripts/fileExporter/providers/click.js"></script> |
102 | 103 | <script type="text/javascript" src="scripts/workspaces/controllers/workspacesModalNew.js"></script> |
103 | 104 | <script type="text/javascript" src="scripts/workspaces/providers/workspaces.js"></script> |
104 | 105 | <script type="text/javascript" src="scripts/dashboard/controllers/dashboard.js"></script> |
105 | <script type="text/javascript" src="scripts/dashboard/controllers/graphicsBarCtrl.js"></script> | |
106 | <script type="text/javascript" src="scripts/dashboard/controllers/treemapModalCtrl.js"></script> | |
106 | 107 | <script type="text/javascript" src="scripts/dashboard/controllers/summarizedCtrl.js"></script> |
107 | <script type="text/javascript" src="scripts/dashboard/controllers/vulnsbyprice.js"></script> | |
108 | <script type="text/javascript" src="scripts/dashboard/controllers/workspaceProgress.js"></script> | |
109 | 108 | <script type="text/javascript" src="scripts/dashboard/providers/dashboard.js"></script> |
110 | 109 | <script type="text/javascript" src="scripts/d3/providers/d3.js"></script> |
111 | 110 | <script type="text/javascript" src="scripts/d3/directives/treemap.js"></script> |
0 | // Faraday Penetration Test IDE | |
1 | // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
2 | // See the file 'doc/LICENSE' for the license information | |
3 | ||
4 | angular.module('faradayApp') | |
5 | .factory('csvService', function() { | |
6 | var csvService = {}; | |
7 | ||
8 | csvService.generator = function(properties, values, ws) { | |
9 | var values = angular.copy(values); | |
10 | var obj_content = "", | |
11 | aProperties = []; | |
12 | ||
13 | for(key in properties) { | |
14 | if(properties.hasOwnProperty(key)) { | |
15 | if(properties[key] === true) { | |
16 | aProperties.push(key); | |
17 | } | |
18 | } | |
19 | } | |
20 | values.forEach(function(v) { | |
21 | aProperties.forEach(function(prop) { | |
22 | object = {}; | |
23 | if(typeof(v[prop]) === "object") v[prop] = parseObject(v[prop]); | |
24 | if(typeof(v[prop]) != "undefined" && v[prop] != null) { | |
25 | object[prop] = cleanCSV(v[prop]); | |
26 | } else { | |
27 | object[prop] = ""; | |
28 | } | |
29 | if(prop === "date") object[prop] = parseDate(v["metadata"]["create_time"] * 1000); | |
30 | if(prop === "web") { | |
31 | if(v.type === "Vulnerability") { | |
32 | object[prop] = false; | |
33 | } else { | |
34 | object[prop] = true; | |
35 | } | |
36 | } | |
37 | obj_content += "\"" + object[prop] + "\","; | |
38 | }); | |
39 | obj_content = obj_content.substring(0, obj_content.length - 1); | |
40 | obj_content += "\n"; | |
41 | }); | |
42 | var content = JSON.stringify(aProperties).replace(/\[|\]/g,"") + "\n" + obj_content; | |
43 | var csvObj = { | |
44 | "content": content, | |
45 | "extension": "csv", | |
46 | "title": "SR-" + ws, | |
47 | "type": "text/csv" | |
48 | }; | |
49 | ||
50 | return csvObj; | |
51 | }; | |
52 | ||
53 | cleanCSV = function(field) { | |
54 | return field.replace(/\"/g, "\"\""); | |
55 | }; | |
56 | ||
57 | parseObject = function(object) { | |
58 | var parsedData = ""; | |
59 | if(object.length === undefined) { | |
60 | for(key in object){ | |
61 | if(object.hasOwnProperty(key)) { | |
62 | parsedData += key + ":" + object[key] + "\n"; | |
63 | } | |
64 | } | |
65 | } else { | |
66 | object.forEach(function(obj, k) { | |
67 | parsedData += obj + "\n"; | |
68 | }); | |
69 | } | |
70 | parsedData = parsedData.substring(0, parsedData.length - 1); | |
71 | return parsedData; | |
72 | }; | |
73 | ||
74 | parseDate = function(date) { | |
75 | var d = new Date(date); | |
76 | return d.getMonth()+1 +"/" + d.getDate() + "/" + d.getFullYear(); | |
77 | }; | |
78 | ||
79 | return csvService; | |
80 | }); |
42 | 42 | return [{ |
43 | 43 | k: d.key, |
44 | 44 | c: d.color, |
45 | y: d.value, | |
45 | y: d.amount, | |
46 | 46 | x: 0 |
47 | 47 | }]; |
48 | 48 | }); |
0 | // Faraday Penetration Test IDE | |
1 | // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
2 | // See the file 'doc/LICENSE' for the license information | |
3 | ||
4 | angular.module('faradayApp') | |
5 | .controller('graphicsBarCtrl', | |
6 | ['$scope', '$route', '$routeParams', '$modal', 'dashboardSrv', | |
7 | function($scope, $route, $routeParams, $modal, dashboardSrv) { | |
8 | //current workspace | |
9 | var workspace = $routeParams.wsId; | |
10 | $scope.barData = []; | |
11 | $scope.treemapData = []; | |
12 | $scope.cakeData = []; | |
13 | ||
14 | if (workspace != undefined){ | |
15 | dashboardSrv.getHostsByServicesCount(workspace).then(function(res){ | |
16 | if (res.length > 2) { | |
17 | res.sort(function(a, b){ | |
18 | return b.value-a.value; | |
19 | }); | |
20 | colors = ["rgb(57, 59, 121)","rgb(82, 84, 163)","rgb(107, 110, 207)"]; | |
21 | var tmp = []; | |
22 | res.slice(0, 3).forEach(function(srv){ | |
23 | srv.color = colors.shift(); | |
24 | tmp.push(srv); | |
25 | }); | |
26 | $scope.barData = tmp; | |
27 | } | |
28 | }); | |
29 | ||
30 | dashboardSrv.getServicesCount(workspace).then(function(res){ | |
31 | if (res.length > 4) { | |
32 | res.sort(function(a, b){ | |
33 | return b.value - a.value; | |
34 | }); | |
35 | colors = ["#FA5882", "#FF0040", "#B40431", "#610B21", "#2A0A1B"]; | |
36 | var tmp = []; | |
37 | res.slice(0, 5).forEach(function(srv){ | |
38 | srv.color = colors.shift(); | |
39 | tmp.push(srv); | |
40 | }); | |
41 | $scope.treemapData = {"children": tmp}; | |
42 | } | |
43 | }); | |
44 | ||
45 | dashboardSrv.getVulnerabilitiesCount(workspace).then(function(res){ | |
46 | if (res.length > 0) { | |
47 | var tmp = [ | |
48 | {"key": "low", "value": 0, "color": "#A1CE31"}, | |
49 | {"key": "med", "value": 0, "color": "#DFBF35"}, | |
50 | {"key": "high", "value": 0, "color": "#DF3936"}, | |
51 | {"key": "critical", "value": 0, "color": "#8B00FF"}, | |
52 | {"key": "info", "value": 0, "color": "#428BCA"} | |
53 | ]; | |
54 | ||
55 | function accumulate(_array, key, value){ | |
56 | _array.forEach(function(obj){ | |
57 | if (obj.key == key){ | |
58 | obj.value += value; | |
59 | } | |
60 | }); | |
61 | } | |
62 | ||
63 | res.forEach(function(tvuln){ | |
64 | if (tvuln.key == 1 || tvuln.key == "info"){ | |
65 | accumulate(tmp, "info", tvuln.value); | |
66 | } else if (tvuln.key == 2 || tvuln.key == "low") { | |
67 | accumulate(tmp, "low", tvuln.value); | |
68 | } else if (tvuln.key == 3 || tvuln.key == "med") { | |
69 | accumulate(tmp, "med", tvuln.value); | |
70 | } else if (tvuln.key == 4 || tvuln.key == "high") { | |
71 | accumulate(tmp, "high", tvuln.value); | |
72 | } else if (tvuln.key == 5 || tvuln.key == "critical") { | |
73 | accumulate(tmp, "critical", tvuln.value); | |
74 | } | |
75 | }); | |
76 | $scope.cakeData = {"children": tmp}; | |
77 | } | |
78 | }); | |
79 | } | |
80 | ||
81 | $scope.treemap = function(){ | |
82 | if($scope.treemapData.children){ | |
83 | var modal = $modal.open({ | |
84 | templateUrl: 'scripts/dashboard/partials/modal-treemap.html', | |
85 | controller: 'treemapModalCtrl', | |
86 | size: 'lg', | |
87 | resolve: { | |
88 | workspace: function(){ | |
89 | return $scope.workspace; | |
90 | } | |
91 | } | |
92 | }); | |
93 | } | |
94 | }; | |
95 | ||
96 | }]); | |
97 | ||
98 | angular.module('faradayApp') | |
99 | .controller('treemapModalCtrl', | |
100 | ['$scope', '$modalInstance', 'dashboardSrv', 'workspace', | |
101 | function($scope, $modalInstance, dashboardSrv, workspace){ | |
102 | ||
103 | dashboardSrv.getServicesCount(workspace).then(function(res){ | |
104 | if (res.length > 4) { | |
105 | res.sort(function(a, b){ | |
106 | return b.value - a.value; | |
107 | }); | |
108 | colors = ["#FA5882", "#FF0040", "#B40431", "#610B21", "#2A0A1B"]; | |
109 | var tmp = []; | |
110 | res.slice(0, 5).forEach(function(srv){ | |
111 | srv.color = colors.shift(); | |
112 | tmp.push(srv); | |
113 | }); | |
114 | $scope.treemapDataModel = {"children": tmp, "height":300, "width": 500}; | |
115 | } | |
116 | }); | |
117 | ||
118 | $scope.ok = function(){ | |
119 | $modalInstance.close(); | |
120 | } | |
121 | ||
122 | }]);⏎ |
3 | 3 | |
4 | 4 | angular.module('faradayApp') |
5 | 5 | .controller('summarizedCtrl', |
6 | ['$scope', '$route', '$routeParams', '$modal', 'dashboardSrv', 'vulnsManager', | |
7 | function($scope, $route, $routeParams, $modal, dashboardSrv, vulnsManager) { | |
6 | ['$scope', '$route', '$routeParams', '$modal', 'dashboardSrv', 'vulnsManager', 'workspacesFact', | |
7 | function($scope, $route, $routeParams, $modal, dashboardSrv, vulnsManager, workspacesFact) { | |
8 | 8 | //current workspace |
9 | 9 | var workspace = $routeParams.wsId; |
10 | 10 | $scope.servicesCount = []; |
11 | 11 | $scope.objectsCount = []; |
12 | $scope.vulnsCount = []; | |
13 | 12 | $scope.commands = []; |
14 | 13 | $scope.hosts = []; |
15 | 14 | $scope.showPagination = 1; |
16 | 15 | $scope.currentPage = 0; |
17 | 16 | $scope.pageSize = 10; |
18 | 17 | $scope.pagination = 10; |
18 | $scope.vulns; | |
19 | ||
20 | // graphicsBarCtrl data | |
21 | $scope.topServices; // previously known as treemapData | |
22 | $scope.topHosts; // previously known as barData | |
23 | $scope.vulnsCount; | |
24 | $scope.vulnsCountClass; // classified vulns count | |
25 | ||
26 | // vulnsByPrice | |
27 | $scope.workspaceWorth; | |
28 | $scope.vulnPrices = dashboardSrv.vulnPrices; | |
29 | ||
30 | // wsProgress | |
31 | $scope.wsDuration; | |
32 | $scope.wsEnd; | |
33 | $scope.wsStart; | |
34 | $scope.wsProgress; | |
19 | 35 | |
20 | 36 | // cmd table sorting |
21 | 37 | $scope.cmdSortField = 'date'; |
77 | 93 | if(workspace != undefined) { |
78 | 94 | $scope.workspace = workspace; |
79 | 95 | |
80 | dashboardSrv.getServicesCount(workspace).then(function(res){ | |
81 | res.sort(function(a, b){ | |
96 | dashboardSrv.getServicesCount(workspace).then(function(res) { | |
97 | res.sort(function(a, b) { | |
82 | 98 | return b.value - a.value; |
83 | 99 | }); |
100 | ||
84 | 101 | $scope.servicesCount = res; |
85 | 102 | |
103 | if(res.length > 4) { | |
104 | var colors = ["#FA5882", "#FF0040", "#B40431", "#610B21", "#2A0A1B"]; | |
105 | var tmp = []; | |
106 | res.slice(0, 5).forEach(function(srv) { | |
107 | srv.color = colors.shift(); | |
108 | tmp.push(srv); | |
109 | }); | |
110 | $scope.topServices = {"children": tmp}; | |
111 | } | |
86 | 112 | }); |
87 | 113 | |
88 | 114 | dashboardSrv.getObjectsCount(workspace).then(function(res){ |
94 | 120 | $scope.objectsCount = res; |
95 | 121 | }); |
96 | 122 | |
97 | dashboardSrv.getVulnerabilitiesCount(workspace).then(function(res){ | |
98 | if (res.length > 0) { | |
123 | dashboardSrv.getVulnerabilitiesCount(workspace).then(function(res) { | |
124 | if(res.length > 0) { | |
99 | 125 | var tmp = [ |
100 | {"key": "critical", "value": 0}, | |
101 | {"key": "high", "value": 0}, | |
102 | {"key": "med", "value": 0}, | |
103 | {"key": "low", "value": 0}, | |
104 | {"key": "info", "value": 0}, | |
105 | {"key": "unclassified", "value": 0} | |
126 | {"key": "critical", "value": 0, "color": "#932EBE", "amount": 0}, | |
127 | {"key": "high", "value": 0, "color": "#DF3936", "amount": 0}, | |
128 | {"key": "med", "value": 0, "color": "#DFBF35", "amount": 0}, | |
129 | {"key": "low", "value": 0, "color": "#A1CE31", "amount": 0}, | |
130 | {"key": "info", "value": 0, "color": "#428BCA", "amount": 0}, | |
131 | {"key": "unclassified", "value": 0, "color": "#999999", "amount": 0} | |
106 | 132 | ]; |
107 | 133 | |
108 | function accumulate(_array, key, value){ | |
109 | _array.forEach(function(obj){ | |
110 | if (obj.key == key){ | |
111 | obj.value += value; | |
112 | } | |
113 | }); | |
114 | } | |
115 | ||
116 | res.forEach(function(tvuln){ | |
117 | if (tvuln.key == 1 || tvuln.key == "info"){ | |
118 | accumulate(tmp, "info", tvuln.value); | |
134 | res.forEach(function(tvuln) { | |
135 | if(tvuln.key == 1 || tvuln.key == "info") { | |
136 | dashboardSrv.accumulate(tmp, "info", tvuln.value, "value"); | |
119 | 137 | } else if (tvuln.key == 2 || tvuln.key == "low") { |
120 | accumulate(tmp, "low", tvuln.value); | |
138 | dashboardSrv.accumulate(tmp, "low", tvuln.value, "value"); | |
121 | 139 | } else if (tvuln.key == 3 || tvuln.key == "med") { |
122 | accumulate(tmp, "med", tvuln.value); | |
140 | dashboardSrv.accumulate(tmp, "med", tvuln.value, "value"); | |
123 | 141 | } else if (tvuln.key == 4 || tvuln.key == "high") { |
124 | accumulate(tmp, "high", tvuln.value); | |
142 | dashboardSrv.accumulate(tmp, "high", tvuln.value, "value"); | |
125 | 143 | } else if (tvuln.key == 5 || tvuln.key == "critical") { |
126 | accumulate(tmp, "critical", tvuln.value); | |
144 | dashboardSrv.accumulate(tmp, "critical", tvuln.value, "value"); | |
127 | 145 | } else if (tvuln.key == 6 || tvuln.key == "unclassified") { |
128 | accumulate(tmp, "unclassified", tvuln.value); | |
146 | dashboardSrv.accumulate(tmp, "unclassified", tvuln.value, "value"); | |
129 | 147 | } |
130 | 148 | }); |
149 | ||
150 | // used to create colored boxes for vulns | |
131 | 151 | $scope.vulnsCount = tmp; |
152 | ||
153 | // used to create workspace's worth | |
154 | $scope.generateVulnPrices($scope.vulnsCount, $scope.vulnPrices); | |
155 | $scope.workspaceWorth = $scope.sumProperty($scope.vulnsCount, "amount"); | |
156 | ||
157 | // used to create pie chart for vulns | |
158 | $scope.vulnsCountClass = {"children": angular.copy(tmp)}; | |
159 | for(var i = 0; i < $scope.vulnsCountClass.children.length; i++) { | |
160 | if($scope.vulnsCountClass.children[i].key == "unclassified") { | |
161 | $scope.vulnsCountClass.children.splice(i, 1); | |
162 | break; | |
163 | } | |
164 | }; | |
165 | ||
166 | $scope.$watch('vulnPrices', function(ps) { | |
167 | if($scope.vulnsCount != undefined) { | |
168 | $scope.generateVulnPrices($scope.vulnsCount, $scope.vulnPrices); | |
169 | $scope.workspaceWorth = $scope.sumProperty($scope.vulnsCount, "amount"); | |
170 | } | |
171 | }, true); | |
132 | 172 | } |
133 | 173 | }); |
134 | 174 | |
148 | 188 | }); |
149 | 189 | |
150 | 190 | dashboardSrv.getHosts(workspace).then(function(res){ |
151 | dashboardSrv.getHostsByServicesCount(workspace).then(function(servicesCount){ | |
191 | dashboardSrv.getHostsByServicesCount(workspace).then(function(servicesCount) { | |
152 | 192 | res.forEach(function(host){ |
153 | 193 | // Maybe this part should be in the view somehow |
154 | 194 | // or, even better, in CSS file |
155 | 195 | oss = ["windows", "cisco", "router", "osx", "apple","linux", "unix"]; |
156 | oss.forEach(function(os){ | |
196 | oss.forEach(function(os) { | |
157 | 197 | if (host.os.toLowerCase().indexOf(os) != -1) { |
158 | 198 | host.icon = os; |
159 | 199 | if (os == "unix") { |
169 | 209 | host.servicesCount = count.value; |
170 | 210 | return |
171 | 211 | } |
172 | }) | |
212 | }); | |
213 | // load data for Top Hosts | |
214 | if(servicesCount.length > 2) { | |
215 | servicesCount.sort(function(a, b) { | |
216 | return b.value-a.value; | |
217 | }); | |
218 | var colors = ["rgb(57, 59, 121)","rgb(82, 84, 163)","rgb(107, 110, 207)"]; | |
219 | var tmp = []; | |
220 | servicesCount.slice(0, 3).forEach(function(srv) { | |
221 | srv.color = colors.shift(); | |
222 | tmp.push(srv); | |
223 | }); | |
224 | $scope.topHosts = tmp; | |
225 | } | |
173 | 226 | $scope.hosts.push(host); |
174 | 227 | }); |
175 | 228 | }); |
178 | 231 | vulnsManager.getVulns(workspace).then(function(vulns) { |
179 | 232 | $scope.vulns = vulns; |
180 | 233 | }); |
181 | } | |
234 | ||
235 | workspacesFact.getDuration($scope.workspace).then(function(duration) { | |
236 | $scope.wsDuration = duration; | |
237 | $scope.wsProgress = $scope.calculateProgress($scope.wsDuration); | |
238 | $scope.wsStart = $scope.wsDuration.start; | |
239 | $scope.wsEnd = $scope.wsDuration.end; | |
240 | }); | |
241 | }; | |
182 | 242 | |
183 | 243 | $scope.numberOfPages = function() { |
184 | 244 | $scope.filteredData = $scope.hosts; |
188 | 248 | $scope.showPagination = 1; |
189 | 249 | }; |
190 | 250 | return parseInt($scope.filteredData.length/$scope.pageSize); |
191 | } | |
251 | }; | |
192 | 252 | |
193 | 253 | $scope.go = function(page,pagination){ |
194 | 254 | if(this.go_page < $scope.numberOfPages()+1 && this.go_page > -1){ |
198 | 258 | if(this.go_page > $scope.numberOfPages()){ |
199 | 259 | $scope.currentPage = 0; |
200 | 260 | } |
201 | } | |
261 | }; | |
202 | 262 | |
203 | 263 | $scope.showServices = function(host_id) { |
204 | 264 | if ($scope.workspace != undefined){ |
216 | 276 | } |
217 | 277 | }); |
218 | 278 | } |
219 | } | |
279 | }; | |
220 | 280 | |
221 | 281 | $scope.showHosts = function(srv_name) { |
222 | 282 | if ($scope.workspace != undefined){ |
234 | 294 | } |
235 | 295 | }); |
236 | 296 | } |
237 | } | |
297 | }; | |
298 | ||
299 | $scope.treemap = function(data) { | |
300 | if(data !== undefined && data != {}) { | |
301 | var modal = $modal.open({ | |
302 | templateUrl: 'scripts/dashboard/partials/modal-treemap.html', | |
303 | controller: 'treemapModalCtrl', | |
304 | size: 'lg', | |
305 | resolve: { | |
306 | workspace: function() { | |
307 | return $scope.workspace; | |
308 | } | |
309 | } | |
310 | }); | |
311 | } | |
312 | }; | |
313 | ||
314 | $scope.sumProperty = function(data, prop) { | |
315 | var total = 0; | |
316 | ||
317 | for(var d in data) { | |
318 | if(data.hasOwnProperty(d)) { | |
319 | if(data[d][prop] !== undefined) total += parseInt(data[d][prop]); | |
320 | } | |
321 | } | |
322 | ||
323 | return total; | |
324 | }; | |
325 | ||
326 | $scope.generateVulnPrices = function(vulns, prices) { | |
327 | vulns.forEach(function(vuln) { | |
328 | vuln.amount = vuln.value * prices[vuln.key]; | |
329 | }); | |
330 | }; | |
331 | ||
332 | $scope.calculateProgress = function(duration) { | |
333 | var partial = 0, | |
334 | progress = 0, | |
335 | today = new Date(), | |
336 | total = 0; | |
337 | ||
338 | if(duration.start == "" || duration.end == "") { | |
339 | progress = null; | |
340 | } else { | |
341 | today = today.getTime(); | |
342 | partial = today - duration.start; | |
343 | total = duration.end - duration.start; | |
344 | ||
345 | if(today > duration.end) { | |
346 | progress = 100; | |
347 | } else if(duration.start < today && today <= duration.end && total > 0) { | |
348 | progress = Math.round(partial * 100 / total); | |
349 | } | |
350 | } | |
351 | ||
352 | return progress; | |
353 | }; | |
238 | 354 | }]); |
239 | 355 | |
240 | 356 | angular.module('faradayApp') |
316 | 432 | $modalInstance.close(); |
317 | 433 | } |
318 | 434 | |
319 | }]);⏎ | |
435 | }]); |
0 | // Faraday Penetration Test IDE | |
1 | // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
2 | // See the file 'doc/LICENSE' for the license information | |
3 | ||
4 | angular.module('faradayApp') | |
5 | .controller('treemapModalCtrl', | |
6 | ['$scope', '$modalInstance', 'dashboardSrv', 'workspace', | |
7 | function($scope, $modalInstance, dashboardSrv, workspace) { | |
8 | ||
9 | dashboardSrv.getServicesCount(workspace).then(function(res) { | |
10 | if(res.length > 4) { | |
11 | res.sort(function(a, b) { | |
12 | return b.value - a.value; | |
13 | }); | |
14 | var colors = ["#FA5882", "#FF0040", "#B40431", "#610B21", "#2A0A1B"]; | |
15 | var tmp = []; | |
16 | res.slice(0, 5).forEach(function(srv) { | |
17 | srv.color = colors.shift(); | |
18 | tmp.push(srv); | |
19 | }); | |
20 | $scope.treemapDataModel = {"children": tmp, "height":300, "width": 500}; | |
21 | } | |
22 | }); | |
23 | ||
24 | $scope.ok = function() { | |
25 | $modalInstance.close(); | |
26 | } | |
27 | }]); |
0 | // Faraday Penetration Test IDE | |
1 | // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
2 | // See the file 'doc/LICENSE' for the license information | |
3 | ||
4 | angular.module('faradayApp') | |
5 | .controller('vulnsbypriceCtrl', | |
6 | ['$scope', '$rootScope', '$route', '$routeParams', 'dashboardSrv', | |
7 | function($scope, $rootScope, $route, $routeParams, dashboardSrv) { | |
8 | init = function() { | |
9 | //current workspace | |
10 | $scope.workspace = $routeParams.wsId; | |
11 | ||
12 | $scope.prices = dashboardSrv.vulnPrices; | |
13 | ||
14 | dashboardSrv.getVulnerabilities($scope.workspace).then(function(res) { | |
15 | $scope.vulns = res; | |
16 | $scope.generateData(res, $scope.prices); | |
17 | }); | |
18 | ||
19 | $scope.$watch('prices', function(ps) { | |
20 | if($scope.vulns != undefined) $scope.generateData($scope.vulns, ps); | |
21 | }, true); | |
22 | }; | |
23 | ||
24 | $scope.generateData = function(vulns, prices) { | |
25 | $scope.data = $scope.generatePrices(vulns, prices); | |
26 | $scope.total = $scope.generateTotal($scope.data); | |
27 | }; | |
28 | ||
29 | $scope.generateTotal = function(data) { | |
30 | var total = 0; | |
31 | ||
32 | for(var d in data) { | |
33 | if(data.hasOwnProperty(d)) { | |
34 | total += parseInt(data[d]['value']); | |
35 | } | |
36 | } | |
37 | ||
38 | return total; | |
39 | }; | |
40 | ||
41 | $scope.generatePrices = function(vulns, prices) { | |
42 | var data = [ | |
43 | { | |
44 | color: '#932ebe', | |
45 | value: 0, | |
46 | key: 'critical' | |
47 | }, { | |
48 | color: '#DF3936', | |
49 | value: 0, | |
50 | key: 'high' | |
51 | }, { | |
52 | color: '#DFBF35', | |
53 | value: 0, | |
54 | key: 'med' | |
55 | }, { | |
56 | color: '#A1CE31', | |
57 | value: 0, | |
58 | key: 'low' | |
59 | }, { | |
60 | color: '#2e97bd', | |
61 | value: 0, | |
62 | key: 'info' | |
63 | }, { | |
64 | color: '#999999', | |
65 | value: 0, | |
66 | key: 'unclassified' | |
67 | } | |
68 | ]; | |
69 | ||
70 | vulns.forEach(function(vuln) { | |
71 | var sev = vuln.value.severity; | |
72 | ||
73 | if(sev == 0 || sev == "unclassified") { | |
74 | dashboardSrv.accumulate(data, "unclassified", parseInt(prices[sev])); | |
75 | } else if(sev == 1 || sev == "info") { | |
76 | dashboardSrv.accumulate(data, "info", parseInt(prices[sev])); | |
77 | } else if(sev == 2 || sev == "low") { | |
78 | dashboardSrv.accumulate(data, "low", parseInt(prices[sev])); | |
79 | } else if(sev == 3 || sev == "med") { | |
80 | dashboardSrv.accumulate(data, "med", parseInt(prices[sev])); | |
81 | } else if(sev == 4 || sev == "high") { | |
82 | dashboardSrv.accumulate(data, "high", parseInt(prices[sev])); | |
83 | } else if(sev == 5 || sev == "critical") { | |
84 | dashboardSrv.accumulate(data, "critical", parseInt(prices[sev])); | |
85 | } | |
86 | }); | |
87 | ||
88 | return data; | |
89 | }; | |
90 | ||
91 | init(); | |
92 | }]); |
0 | // Faraday Penetration Test IDE | |
1 | // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
2 | // See the file 'doc/LICENSE' for the license information | |
3 | ||
4 | angular.module('faradayApp') | |
5 | .controller('workspaceProgressCtrl', | |
6 | ['$scope', '$route', '$routeParams', 'workspacesFact', | |
7 | function($scope, $route, $routeParams, workspacesFact) { | |
8 | $scope.duration; | |
9 | $scope.end; | |
10 | $scope.start; | |
11 | $scope.progress; | |
12 | $scope.workspace; | |
13 | ||
14 | init = function() { | |
15 | $scope.workspace = $routeParams.wsId; | |
16 | workspacesFact.getDuration($scope.workspace).then(function(duration) { | |
17 | $scope.duration = duration; | |
18 | $scope.progress = $scope.calculateProgress($scope.duration); | |
19 | $scope.start = $scope.duration.start; | |
20 | $scope.end = $scope.duration.end; | |
21 | }); | |
22 | }; | |
23 | ||
24 | $scope.calculateProgress = function(duration) { | |
25 | var partial = 0, | |
26 | progress = 0, | |
27 | today = new Date(), | |
28 | total = 0; | |
29 | ||
30 | if(duration.start == "" || duration.end == "") { | |
31 | progress = null; | |
32 | } else { | |
33 | today = today.getTime(); | |
34 | partial = today - duration.start; | |
35 | total = duration.end - duration.start; | |
36 | ||
37 | if(today > duration.end) { | |
38 | progress = 100; | |
39 | } else if(duration.start < today && today <= duration.end && total > 0) { | |
40 | progress = Math.round(partial * 100 / total); | |
41 | } | |
42 | } | |
43 | ||
44 | return progress; | |
45 | }; | |
46 | ||
47 | init(); | |
48 | }]); |
21 | 21 | </h2><!-- .ws-label --> |
22 | 22 | <div class="reports"> |
23 | 23 | </div><!-- .reports --> |
24 | <div ng-controller="graphicsBarCtrl" ng-include="'scripts/dashboard/partials/graphics-bar.html'"></div> | |
25 | <div ng-controller="summarizedCtrl" ng-include="'scripts/dashboard/partials/summarized.html'"></div> | |
26 | <div class="row"> | |
27 | <div class="col-lg-6 col-lg-left"> | |
28 | <div ng-controller="summarizedCtrl" ng-include="'scripts/dashboard/partials/last-vulns.html'"></div> | |
29 | <div ng-controller="summarizedCtrl" ng-include="'scripts/dashboard/partials/compound.html'"></div> | |
30 | </div> | |
31 | <div class="col-lg-6 col-lg-right"> | |
32 | <div ng-controller="summarizedCtrl" ng-include="'scripts/dashboard/partials/vulns-by-severity.html'"></div> | |
33 | <div ng-controller="vulnsbypriceCtrl" ng-include="'scripts/dashboard/partials/vulns-by-price.html'"></div> | |
34 | <div ng-controller="summarizedCtrl" ng-include="'scripts/dashboard/partials/commands-list.html'"></div> | |
35 | <div ng-controller="workspaceProgressCtrl" ng-include="'scripts/dashboard/partials/workspace-progress.html'"></div> | |
36 | </div> | |
37 | </div> | |
24 | <div ng-controller="summarizedCtrl"> | |
25 | <div ng-include="'scripts/dashboard/partials/graphics-bar.html'"></div> | |
26 | <div ng-include="'scripts/dashboard/partials/summarized.html'"></div> | |
27 | <div class="row"> | |
28 | <div class="col-lg-6 col-lg-left"> | |
29 | <div ng-include="'scripts/dashboard/partials/last-vulns.html'"></div> | |
30 | <div ng-include="'scripts/dashboard/partials/compound.html'"></div> | |
31 | </div> | |
32 | <div class="col-lg-6 col-lg-right"> | |
33 | <div ng-include="'scripts/dashboard/partials/vulns-by-severity.html'"></div> | |
34 | <div ng-include="'scripts/dashboard/partials/vulns-by-price.html'"></div> | |
35 | <div ng-include="'scripts/dashboard/partials/commands-list.html'"></div> | |
36 | <div ng-include="'scripts/dashboard/partials/workspace-progress.html'"></div> | |
37 | </div> | |
38 | </div><!-- .rows --> | |
39 | </div><!-- ng-controller --> | |
38 | 40 | </div><!-- #reports-main --> |
39 | 41 | </div><!-- .right-main --> |
40 | 42 | </section> |
5 | 5 | <article id='treemap' class='panel panel-default'> |
6 | 6 | <header> |
7 | 7 | <h2> |
8 | <a class="treemap-view" href="" ng-disabled="{{nodata}}" ng-click="treemap()">Top Services</a> | |
8 | <a class="treemap-view" href="" ng-disabled="{{nodata}}" ng-click="treemap(topServices)">Top Services</a> | |
9 | 9 | <span class="glyphicon glyphicon-info-sign" tooltip="Top 5 services with the largest quantity of hosts"></span> |
10 | 10 | </h2> |
11 | 11 | </header> |
12 | 12 | <span id="treemapText"></span> |
13 | <div ng-if="treemapData.length < 5" class="alert alert-info alert-dismissible"> | |
13 | <div ng-if="topServices == undefined || topServices.length < 5" class="alert alert-info alert-dismissible"> | |
14 | 14 | <button type="button" class="close" data-dismiss="alert"> |
15 | 15 | <span aria-hidden="true">×</span> |
16 | 16 | <span class="sr-only">Close</span> |
17 | 17 | </button> |
18 | 18 | <p>At least 5 services needed to show this visualization</p> |
19 | 19 | </div> |
20 | <d3-treemap data="treemapData"></d3-treemap> | |
20 | <d3-treemap data="topServices"></d3-treemap> | |
21 | 21 | </article> |
22 | 22 | </div> |
23 | 23 | <div class='col-lg-2'> |
28 | 28 | </h2> |
29 | 29 | </header> |
30 | 30 | <span id="barText"></span> |
31 | <div ng-if="barData.length < 3" class="alert alert-info alert-dismissible"> | |
31 | <div ng-if="topHosts == undefined || topHosts.length < 3" class="alert alert-info alert-dismissible"> | |
32 | 32 | <button type="button" class="close" data-dismiss="alert"> |
33 | 33 | <span aria-hidden="true">×</span> |
34 | 34 | <span class="sr-only">Close</span> |
35 | 35 | </button> |
36 | 36 | <p>At least 3 hosts needed to show this visualization</p> |
37 | 37 | </div> |
38 | <d3-bars data="barData"></d3-bars> | |
38 | <d3-bars data="topHosts"></d3-bars> | |
39 | 39 | </article> |
40 | 40 | </div> |
41 | 41 | <div class='col-lg-2'> |
46 | 46 | </h2> |
47 | 47 | </header> |
48 | 48 | <span id="cakeText"></span> |
49 | <div ng-if="cakeData.length == 0" class="alert alert-info alert-dismissible"> | |
49 | <div ng-if="vulnsCountClass == undefined || vulnsCountClass.length == 0" class="alert alert-info alert-dismissible"> | |
50 | 50 | <button type="button" class="close" data-dismiss="alert"> |
51 | 51 | <span aria-hidden="true">×</span> |
52 | 52 | <span class="sr-only">Close</span> |
53 | 53 | </button> |
54 | 54 | <p>No vulnerabilities found yet</p> |
55 | 55 | </div> |
56 | <d3-cake data="cakeData"></d3-cake> | |
56 | <d3-cake data="vulnsCountClass"></d3-cake> | |
57 | 57 | </article> |
58 | </div>⏎ | |
58 | </div> |
4 | 4 | <span class="glyphicon glyphicon-info-sign" tooltip="Total net worth of Workspace, according to current vulnerabilities' prices"></span> |
5 | 5 | </h2> |
6 | 6 | </header> |
7 | <div class="main"> | |
8 | <div class="center-lg-6"><h4><i class="fa fa-money fa-2x"></i> {{total | currency}} total</h4></div> | |
9 | <div d3-horizontal-stacked-bar data="data" class="stackedbars"></div> | |
7 | <div ng-if="vulnsCount == undefined || vulnsCount.length == 0" class="alert alert-info alert-dismissible no-margin-bottom"> | |
8 | <button type="button" class="close" data-dismiss="alert"> | |
9 | <span aria-hidden="true">×</span> | |
10 | <span class="sr-only">Close</span> | |
11 | </button> | |
12 | <p>No vulnerabilities found yet.</p> | |
13 | </div> | |
14 | <div class="main" ng-if="vulnsCount.length > 0"> | |
15 | <div class="center-lg-6"><h4><i class="fa fa-money fa-2x"></i> {{workspaceWorth | currency}} total</h4></div> | |
16 | <div d3-horizontal-stacked-bar data="vulnsCount" class="stackedbars"></div> | |
10 | 17 | <div id="vulns-by-price-reference" class="center-lg-6"> |
11 | 18 | <ul class="label-list"> |
12 | <li ng-repeat="(severity, price) in prices" tooltip="Click on number to edit price"><span class="label vuln fondo-{{severity}}">{{severity}} $<span contenteditable="true" ng-model="prices[severity]"></span></span></li> | |
19 | <li ng-repeat="(severity, price) in vulnPrices" tooltip="Click on number to edit price"><span class="label vuln fondo-{{severity}}">{{severity}} $<span contenteditable="true" ng-model="vulnPrices[severity]"></span></span></li> | |
13 | 20 | </ul> |
14 | 21 | </div><!-- #vulns-by-price-reference .center-lg-6 --> |
15 | 22 | </div> |
16 | </article>⏎ | |
23 | </article> |
4 | 4 | <span class="glyphicon glyphicon-info-sign" tooltip="Vulnerabilities count arranged by severity"></span> |
5 | 5 | </h2> |
6 | 6 | </header> |
7 | <div ng-if="vulnsCount.length == 0" class="alert alert-info alert-dismissible no-margin-bottom"> | |
7 | <div ng-if="vulnsCount == undefined || vulnsCount.length == 0" class="alert alert-info alert-dismissible no-margin-bottom"> | |
8 | 8 | <button type="button" class="close" data-dismiss="alert"> |
9 | 9 | <span aria-hidden="true">×</span> |
10 | 10 | <span class="sr-only">Close</span> |
21 | 21 | </article> |
22 | 22 | </div> |
23 | 23 | </div> |
24 | </article>⏎ | |
24 | </article> |
5 | 5 | </h2> |
6 | 6 | </header> |
7 | 7 | <div> |
8 | <div id="workspace-progress-reference" class="center-lg-6" ng-if="progress"> | |
9 | <progressbar value="progress" class="progress-striped">{{progress}}%</progressbar> | |
8 | <div id="workspace-progress-reference" class="center-lg-6" ng-if="wsProgress"> | |
9 | <progressbar value="wsProgress" class="progress-striped">{{wsProgress}}%</progressbar> | |
10 | 10 | <ul class="label-list"> |
11 | <li><span class="label label-default">Start date: {{start | date:"MM/dd/yyyy"}}</span></li> | |
12 | <li><span class="label label-default">End date: {{end | date:"MM/dd/yyyy"}}</span></li> | |
11 | <li><span class="label label-default">Start date: {{wsStart | date:"MM/dd/yyyy"}}</span></li> | |
12 | <li><span class="label label-default">End date: {{wsEnd | date:"MM/dd/yyyy"}}</span></li> | |
13 | 13 | </ul> |
14 | 14 | </div><!-- #workspace-progress-reference .center-lg-6 --> |
15 | <div ng-if="!progress" class="alert alert-info alert-dismissible no-margin-bottom"> | |
15 | <div ng-if="!wsProgress" class="alert alert-info alert-dismissible no-margin-bottom"> | |
16 | 16 | <button type="button" class="close" data-dismiss="alert"> |
17 | 17 | <span aria-hidden="true">×</span> |
18 | 18 | <span class="sr-only">Close</span> |
20 | 20 | <p>Start date and end date are required</p> |
21 | 21 | </div><!-- ng-if --> |
22 | 22 | </div> |
23 | </article>⏎ | |
23 | </article> |
162 | 162 | }; |
163 | 163 | |
164 | 164 | |
165 | dashboardSrv.accumulate = function(_array, key, value) { | |
166 | _array.forEach(function(obj){ | |
165 | dashboardSrv.accumulate = function(_array, key, value, accum) { | |
166 | _array.forEach(function(obj) { | |
167 | 167 | if(obj.key == key) { |
168 | obj.value += value; | |
168 | if(obj[accum] === undefined) obj[accum] = 0; | |
169 | obj[accum] += value; | |
169 | 170 | } |
170 | 171 | }); |
171 | 172 | }; |
2 | 2 | // See the file 'doc/LICENSE' for the license information |
3 | 3 | |
4 | 4 | angular.module('faradayApp') |
5 | .controller('navigationCtrl', ['$scope', '$http','$route', '$routeParams', '$cookies', '$location', | |
6 | function($scope, $http, $route, $routeParams, $cookies, $location) { | |
5 | .controller('navigationCtrl', ['$scope', '$http','$route', '$routeParams', '$cookies', '$location', '$interval', | |
6 | function($scope, $http, $route, $routeParams, $cookies, $location, $interval) { | |
7 | 7 | |
8 | 8 | $scope.workspace = ""; |
9 | 9 | $scope.component = ""; |
10 | ||
11 | $scope.checkCwe = function() { | |
12 | $http.get("https://www.faradaysec.com/scripts/updatedb.php").then(function() { | |
13 | }, function() { | |
14 | console.log("CWE database couldn't be updated"); | |
15 | }); | |
16 | }; | |
17 | ||
18 | var timer = $interval($scope.checkCwe, 43200000); | |
19 | $scope.checkCwe(); | |
20 | ||
21 | $scope.$on('$destroy', function() { | |
22 | $interval.cancel(timer); | |
23 | }); | |
10 | 24 | |
11 | 25 | $scope.$on('$routeChangeSuccess', function() { |
12 | 26 | $scope.updateWorkspace(); |
6 | 6 | ['$scope', '$filter', '$routeParams', |
7 | 7 | '$location', '$modal', '$cookies', '$q', 'BASEURL', |
8 | 8 | 'SEVERITIES', 'EASEOFRESOLUTION', 'hostsManager', |
9 | 'vulnsManager', 'workspacesFact', | |
9 | 'vulnsManager', 'workspacesFact', 'csvService', | |
10 | 10 | function($scope, $filter, $routeParams, |
11 | 11 | $location, $modal, $cookies, $q, BASEURL, |
12 | 12 | SEVERITIES, EASEOFRESOLUTION, hostsManager, |
13 | vulnsManager, workspacesFact) { | |
13 | vulnsManager, workspacesFact, csvService) { | |
14 | 14 | $scope.baseurl; |
15 | 15 | $scope.columns; |
16 | 16 | $scope.easeofresolution; |
81 | 81 | } |
82 | 82 | // set columns to show and hide by default |
83 | 83 | $scope.columns = objectoSRColumns || { |
84 | "date": true, | |
85 | "severity": true, | |
86 | "target": true, | |
87 | "name": true, | |
88 | "desc": true, | |
89 | "resolution": false, | |
84 | 90 | "data": true, |
85 | "date": true, | |
86 | "desc": true, | |
87 | 91 | "easeofresolution": false, |
92 | "status": false, | |
93 | "website": false, | |
94 | "path": false, | |
95 | "request": false, | |
96 | "refs": true, | |
88 | 97 | "evidence": false, |
89 | 98 | "hostnames": false, |
90 | 99 | "impact": false, |
91 | 100 | "method": false, |
92 | "name": true, | |
93 | 101 | "params": false, |
94 | "path": false, | |
95 | 102 | "pname": false, |
96 | 103 | "query": false, |
97 | "refs": true, | |
98 | "request": false, | |
99 | 104 | "response": false, |
100 | "resolution": false, | |
101 | "severity": true, | |
102 | "status": false, | |
103 | "target": true, | |
104 | "web": false, | |
105 | "website": false | |
105 | "web": false | |
106 | 106 | }; |
107 | 107 | |
108 | 108 | $scope.vulnWebSelected = false; |
110 | 110 | |
111 | 111 | $scope.selectedVulns = function() { |
112 | 112 | selected = []; |
113 | $scope.vulns.forEach(function(vuln) { | |
113 | var tmp_vulns = $filter('orderObjectBy')($scope.vulns, $scope.sortField, $scope.reverse); | |
114 | tmp_vulns = $filter('filter')(tmp_vulns, $scope.expression); | |
115 | tmp_vulns = tmp_vulns.splice($scope.pageSize * $scope.currentPage, $scope.pageSize); | |
116 | tmp_vulns.forEach(function(vuln) { | |
114 | 117 | if (vuln.selected_statusreport_controller) { |
115 | 118 | selected.push(vuln); |
116 | 119 | } |
118 | 121 | return selected; |
119 | 122 | } |
120 | 123 | |
121 | ||
122 | // returns scope vulns as CSV obj | |
123 | // toggles column sort field | |
124 | cleanCSV = function(field) { | |
125 | return field.replace(/\n[ ]*\n/g, "").replace(/\"/g, "'").replace(/[\n\r]/g, "%0A").replace(/[,]/g, "%2c"); | |
126 | }; | |
127 | ||
128 | $scope.toCSV = function() { | |
129 | var method = "", | |
130 | website = "", | |
131 | desc = "", | |
132 | easeofres = "", | |
133 | impact = "", | |
134 | text = "", | |
135 | path = "", | |
136 | pname = "", | |
137 | params = "", | |
138 | query = "", | |
139 | refs = "", | |
140 | request = "", | |
141 | response = "", | |
142 | resolution = "", | |
143 | content = "\"Date\", \"Web\", \"Status\", \"Severity\", "+ | |
144 | "\"Name\", \"Target\", \"Description\", "+ | |
145 | "\"Data\", \"Method\", \"Path\", \"Param Name\", \"Params\", "+ | |
146 | "\"Query\", \"References\", \"Request\", \"Response\", \"Resolution\",\"Website\", "+ | |
147 | "\"Ease of Resolution\", \"Impact\"\n"; | |
148 | ||
149 | $scope.vulns.then(function(vs) { | |
150 | forEach(function(v) { | |
151 | method = ""; | |
152 | website = ""; | |
153 | desc = ""; | |
154 | easeofres = "", | |
155 | impact = JSON.stringify(v.impact), | |
156 | text = ""; | |
157 | path = ""; | |
158 | pname = ""; | |
159 | params = ""; | |
160 | query = ""; | |
161 | refs = ""; | |
162 | request = ""; | |
163 | response = ""; | |
164 | resolution = ""; | |
165 | refs = v.refs.toString(); | |
166 | ||
167 | if(typeof(v.desc) != "undefined" && v.desc != null) desc = cleanCSV(v.desc); | |
168 | if(typeof(v.data) != "undefined" && v.data != null) text = cleanCSV(v.data); | |
169 | if(typeof(v.resolution) != "undefined" && v.resolution != null) resolution = cleanCSV(v.resolution); | |
170 | if(typeof(refs) != "undefined" && refs != null){ | |
171 | refs = cleanCSV(refs); | |
172 | refs = refs.replace(/%2c/g,"%0A"); | |
173 | } | |
174 | if(typeof(impact) != "undefined" && impact != null){ | |
175 | impact = cleanCSV(impact); | |
176 | impact = impact.replace(/%2c/g,"%0A"); | |
177 | } | |
178 | if(v.type === "VulnerabilityWeb") { | |
179 | if(typeof(v.method) != "undefined" && v.method != null) method = cleanCSV(v.method); | |
180 | if(typeof(v.website) != "undefined" && v.website != null) website = cleanCSV(v.website); | |
181 | if(typeof(v.path) != "undefined" && v.path != null) path = cleanCSV(v.path); | |
182 | if(typeof(v.pname) != "undefined" && v.pname != null) pname = cleanCSV(v.pname); | |
183 | if(typeof(v.params) != "undefined" && v.params != null) params = cleanCSV(v.params); | |
184 | if(typeof(v.query) != "undefined" && v.query != null) query = cleanCSV(v.query); | |
185 | if(typeof(refs) != "undefined" && refs != null){ | |
186 | refs = cleanCSV(refs); | |
187 | refs = refs.replace(/%2c/g,"%0A"); | |
188 | } | |
189 | if(typeof(v.request) != "undefined" && v.request != null) request = cleanCSV(v.request); | |
190 | if(typeof(v.response) != "undefined" && v.response != null) response = cleanCSV(v.response); | |
191 | if(typeof(v.resolution) != "undefined" && v.resolution != null) resolution = cleanCSV(v.resolution); | |
192 | } | |
193 | ||
194 | content += "\""+v.date+"\","+ | |
195 | " \""+v.web+"\","+ | |
196 | " \"Vulnerable\","+ | |
197 | " \""+v.severity+"\","+ | |
198 | " \""+v.name+"\","+ | |
199 | " \""+v.target+"\","+ | |
200 | " \""+desc+"\","+ | |
201 | " \""+text+"\","+ | |
202 | " \""+method+"\","+ | |
203 | " \""+path+"\","+ | |
204 | " \""+pname+"\","+ | |
205 | " \""+params+"\","+ | |
206 | " \""+query+"\","+ | |
207 | " \""+refs+"\","+ | |
208 | " \""+request+"\","+ | |
209 | " \""+response+"\","+ | |
210 | " \""+resolution+"\","+ | |
211 | " \""+website+"\","+ | |
212 | " \""+impact+"\","+ | |
213 | " \""+easeofres+"\""+ | |
214 | "\n"; | |
215 | }); | |
216 | }); | |
217 | ||
218 | var obj = { | |
219 | "content": content, | |
220 | "extension": "csv", | |
221 | "title": "SR-" + $scope.workspace, | |
222 | "type": "text/csv" | |
223 | }; | |
224 | ||
225 | return obj; | |
124 | $scope.csv = function() { | |
125 | tmp_vulns = $filter('filter')($scope.vulns, $scope.expression); | |
126 | return csvService.generator($scope.columns, tmp_vulns, $scope.workspace); | |
226 | 127 | }; |
227 | 128 | |
228 | 129 | showMessage = function(msg) { |
249 | 150 | }); |
250 | 151 | }; |
251 | 152 | |
153 | ||
252 | 154 | // action triggered from DELETE button |
253 | 155 | $scope.delete = function() { |
254 | if($scope.selectedVulns().length > 0) { | |
156 | _delete($scope.selectedVulns()); | |
157 | }; | |
158 | // delete only one vuln | |
159 | $scope.deleteVuln = function(vuln) { | |
160 | _delete([vuln]); | |
161 | }; | |
162 | ||
163 | _delete = function(vulns) { | |
164 | if(vulns.length > 0) { | |
255 | 165 | var modal = $modal.open({ |
256 | 166 | templateUrl: 'scripts/commons/partials/modalDelete.html', |
257 | 167 | controller: 'commonsModalDelete', |
259 | 169 | resolve: { |
260 | 170 | msg: function() { |
261 | 171 | var msg = ""; |
262 | if($scope.selectedVulns().length == 1) { | |
172 | if(vulns.length == 1) { | |
263 | 173 | msg = "A vulnerability will be deleted."; |
264 | 174 | } else { |
265 | msg = $scope.selectedVulns().length + " vulnerabilities will be deleted."; | |
175 | msg = vulns.length + " vulnerabilities will be deleted."; | |
266 | 176 | } |
267 | 177 | msg += " This action cannot be undone. Are you sure you want to proceed?"; |
268 | 178 | return msg; |
271 | 181 | }); |
272 | 182 | |
273 | 183 | modal.result.then(function() { |
274 | $scope.remove($scope.selectedVulns()); | |
184 | $scope.remove(vulns); | |
275 | 185 | }); |
276 | 186 | } else { |
277 | 187 | showMessage('No vulnerabilities were selected to delete'); |
280 | 190 | |
281 | 191 | // action triggered from EDIT button |
282 | 192 | $scope.edit = function() { |
283 | if ($scope.selectedVulns().length == 1) { | |
193 | _edit($scope.selectedVulns()); | |
194 | }; | |
195 | ||
196 | $scope.editVuln = function(vuln) { | |
197 | _edit([vuln]); | |
198 | }; | |
199 | ||
200 | _edit = function(vulns) { | |
201 | if (vulns.length == 1) { | |
284 | 202 | var modal = $modal.open({ |
285 | 203 | templateUrl: 'scripts/statusReport/partials/modalEdit.html', |
286 | 204 | controller: 'modalEditCtrl as modal', |
290 | 208 | return $scope.severities; |
291 | 209 | }, |
292 | 210 | vuln: function() { |
293 | return $scope.selectedVulns()[0]; | |
211 | return vulns[0]; | |
294 | 212 | } |
295 | 213 | } |
296 | 214 | }); |
297 | 215 | modal.result.then(function(data) { |
298 | vulnsManager.updateVuln($scope.selectedVulns()[0], data).then(function(){ | |
216 | vulnsManager.updateVuln(vulns[0], data).then(function(){ | |
299 | 217 | }, function(errorMsg){ |
300 | showMessage("Error updating vuln " + $scope.selectedVulns()[0].name + " (" + $scope.selectedVulns()[0]._id + "): " + errorMsg); | |
218 | showMessage("Error updating vuln " + vulns[0].name + " (" + vulns[0]._id + "): " + errorMsg); | |
301 | 219 | }); |
302 | 220 | |
303 | 221 | }); |
9 | 9 | title="Current workspace">Status report for {{ workspace }} ({{vulns.length}} vulns)</span></h2><!-- WS name --> |
10 | 10 | </div><!-- .ws-label --> |
11 | 11 | <div id="ws-control" class="btn-group btn-small-margin"> |
12 | <button file-exporter="toCSV()" type="button" class="btn btn-success" title="Download CSV for current workspace"> | |
12 | <button file-exporter="csv()" type="button" class="btn btn-success" title="Download CSV for current workspace"> | |
13 | 13 | <span class="glyphicon glyphicon-download"></span> |
14 | 14 | </button> |
15 | 15 | <button id="refresh" type="button" class="btn btn-danger" title="Refresh current workspace" ng-click="location.reload()"> |
72 | 72 | <span class="input-group-addon glyphicon-btn glyphicon glyphicon-remove" ng-click="searchFor(false, '')" ng-if="search"></span> |
73 | 73 | <input type="text" class="form-control" id="filter-by" |
74 | 74 | placeholder="enter keywords" ng-change="currentPage = 0" ng-model="searchParams" /> |
75 | <span class="input-group-addon glyphicon-btn glyphicon glyphicon-search" ng-click="searchFor(true, searchParams)"></span> | |
75 | <span class="input-group-addon glyphicon-btn" ng-click="searchFor(true, searchParams)"> | |
76 | <i class="fa fa-search" ng-if="vulns"></i> | |
77 | <i class="fa fa-refresh fa-spin" ng-if="vulns.length == 0"></i> | |
78 | </span> | |
76 | 79 | </div> |
77 | 80 | </div> |
78 | 81 | </form> |
93 | 96 | <thead> |
94 | 97 | <tr> |
95 | 98 | <th><input type="checkbox" ng-model="selectall" ng-click="checkAll()"/></th> |
99 | <th><a href=""></a></th> | |
100 | <th><a href=""></a></th> | |
96 | 101 | <th ng-if="columns.date"> |
97 | 102 | <a href="" ng-click="toggleSort('metadata.create_time')">Date</a> |
98 | 103 | <a href="" ng-click="toggleShow('date', true)"><span class="glyphicon glyphicon-remove"></span></a> |
190 | 195 | selection-model-selected-attribute="selected_statusreport_controller" |
191 | 196 | selection-model-selected-class="multi-selected" |
192 | 197 | selection-model-on-change="selectionChange()"> |
193 | <td><input type="checkbox" name="{{v.id}}"/></td> | |
198 | <td class="text-center"><input type="checkbox" name="{{v.id}}"/></td> | |
199 | <td class="text-center"><span ng-click="editVuln(v)" class="glyphicon glyphicon-pencil cursor" tooltip="Edit"></span></td> | |
200 | <td class="text-center"><span ng-click="deleteVuln(v)" class="glyphicon glyphicon-trash cursor" tooltip="Delete"></span></td> | |
194 | 201 | <td ng-if="columns.date">{{v.metadata.create_time * 1000 | date:'MM/dd/yyyy'}}</td> |
195 | 202 | <td ng-if="columns.target">{{v.target}}</td> |
196 | 203 | <td ng-if="columns.status">Vulnerable</td> |
243 | 250 | </form> |
244 | 251 | </div> |
245 | 252 | </div> |
253 | <div id="counter"> | |
254 | <span>Total</span> | |
255 | <span class="counterNum">{{vulns.length}}</span> | |
256 | <div ng-if="search"> | |
257 | <span>Viewing</span> | |
258 | <span class="counterNum">{{filtered.length}}</span> | |
259 | </div> | |
260 | <p style="margin:0px" ng-if="!search"></p> | |
261 | <span>Selected</span> | |
262 | <span class="counterNum">{{selectedVulns().length}}</span> | |
263 | </div> | |
246 | 264 | </div><!-- .reports --> |
247 | 265 | </div><!-- #reports-main --></div><!-- .right-main --> |
248 | 266 | </section><!-- #main --> |
72 | 72 | }; |
73 | 73 | |
74 | 74 | vulnsManager.deleteVuln = function(vuln) { |
75 | var deferred = $q.defer(); | |
75 | var deferred = $q.defer(), | |
76 | 76 | self = this; |
77 | 77 | vuln.remove().then(function(){ |
78 | 78 | var index = self.vulns_indexes[vuln._id]; |
137 | 137 | }; |
138 | 138 | |
139 | 139 | vulnsManager.updateVuln = function(vuln, data) { |
140 | var deferred = $q.defer(); | |
140 | var deferred = $q.defer(), | |
141 | 141 | self = this; |
142 | 142 | vuln.update(data).then(function(){ |
143 | 143 | self.vulns[self.vulns_indexes[vuln._id]] = vuln; |