Codebase list python-faraday / upstream/1.0.14
Imported Upstream version 1.0.14 Sophie Brun 8 years ago
64 changed file(s) with 1155 addition(s) and 488 deletion(s). Raw diff Collapse all Expand all
88
99 New features in the latest update
1010 =====================================
11
12 Sep 10, 2015:
13 ---
14 * Adding filename path information of report imported in history command
15 * Remove old couchdb upgrade process
16 * Adding Iceweasel browser > 38.2.0 support
17 * Adding more navigability in differents GUI Web (Dashboard/Services/Views)
18 * Fixed bug copy clipboard offline (update path of ngClip dependeces)
19 * Added class to set colors to severities in new/edit vuln view
20 * Medusa, Hydra & Metasploit plug-in now added discovered weak credentials as a vulnerability
21 * Nmap plug-in applyies a severity depending on the result of a NSE script
22 * Fixed small bug for empty ease of resolution
23 * Adding more time to generation shells QT
24 * Added "Search in Shodan" links in different views (Status Report, Host View, Service View)
25 * Removed required of name field service bulk edition
26 * Added ng-disabled on Edit button if select more of 1 host on Host View WEB UI
27 * Refactored GUI Web:
28 Icon added for Modal Error
29 OS, Creator, Date for modal-services-by-host.html
30 Fixed typo in Host Edit, the popup message was wrong
31 First version for in estilos.css for clear mode
32 Also, added hover to grey boxes in the Dashboard.
33 * Added vulns count for Hosts in WEB UI
34 * Updated w3af plugin to support report version 1.7.6
35 * Ignored cwe database from updater and QT views
36 * Plugin for Nexpose XML Export 2.0
37 * Added masscan plugin (1.0.3)
1138
1239 Aug 19, 2015:
1340 ---
2148 * Clean dev log on plugins
2249 * w3af plugin refactoring
2350 * Fix Debian 7/8.1 install support
24
2551
2652 Aug 05, 2015:
2753 ---
0 1.0.13
0 1.0.14
11 <faraday>
22
33 <appname>Faraday - Penetration Test IDE</appname>
4 <version>1.0.13</version>
4 <version>1.0.14</version>
55 <debug_status>0</debug_status>
66 <font>-Misc-Fixed-medium-r-normal-*-12-100-100-100-c-70-iso8859-1</font>
77 <home_path>~/</home_path>
2626 CONST_FARADAY_BASE_CFG = "config/default.xml"
2727 CONST_FARADAY_USER_CFG = "config/config.xml"
2828 CONST_FARADAY_LIB_HELPERS = "shell/core/_helpers.so"
29 CONST_BLACKDBS = ('cwe','reports')
2930
3031 CONST_USER_HOME = "~"
3132 CONST_USER_ZSHRC = "~/.zshrc"
351351
352352 self.timer = qt.QTimer(self)
353353 self.connect(self.timer, qt.SIGNAL('timeout()'), self.createShellTab)
354 self.timer.start(200, True)
354 self.timer.start(1000, True)
355355
356356 for shell_widget in self._shell_widgets:
357357 shell_widget.show()
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
8 import os
9 import model.api
10 import threading
11 import time
12 import traceback
13 import re
14 import requests
15 try:
16 import xml.etree.cElementTree as ET
17
18 except ImportError:
19 print "cElementTree could not be imported. Using ElementTree instead"
20 import xml.etree.ElementTree as ET
21 from apis.rest.api import PluginControllerAPIClient
22
23 from utils.common import sha1OfFile
24
25 from config.configuration import getInstanceConfiguration
26 CONF = getInstanceConfiguration()
27
28 class NoReportsWatchException(Exception): pass
29
30 class ReportManager(threading.Thread):
31 def __init__(self, timer, plugin_controller, path=None):
32 threading.Thread.__init__(self)
33 self.setDaemon(True)
34 self.timer = timer
35 self._stop = False
36 self.path = path
37 self.plugin_controller = plugin_controller
38 self._report_path = None
39 self._report_ppath = None
40
41 def run(self):
42 tmp_timer = 0
43 while not self._stop:
44
45 time.sleep(1)
46 tmp_timer += 1
47 if tmp_timer == self.timer:
48 try:
49 self.syncReports()
50 except Exception:
51 model.api.devlog("An exception was captured while saving reports\n%s" % traceback.format_exc())
52 finally:
53 tmp_timer = 0
54
55 def stop(self):
56 self._stop = True
57
58 def watch(self, name):
59 self._report_path = os.path.join(CONF.getReportPath(), name)
60 self._report_ppath = os.path.join(self._report_path, "process")
61
62 if not os.path.exists(self._report_path):
63 os.mkdir(self._report_path)
64
65 if not os.path.exists(self._report_ppath):
66 os.mkdir(self._report_ppath)
67
68 def startWatch(self):
69 if not self._report_path:
70 raise NoReportsWatchException()
71 self.start()
72
73 def syncReports(self):
74 """
75 Synchronize report directory using the DataManager and Plugins online
76 We first make sure that all shared reports were added to the repo
77 """
78
79 for root, dirs, files in os.walk(self._report_path, False):
80
81 if root == self._report_path:
82 for name in files:
83 filename = os.path.join(root, name)
84 model.api.devlog( "Report file is %s" % filename)
85
86 parser = ReportXmlParser(filename)
87 if (parser.report_type is not None):
88 #TODO: get host and port from config
89 client = PluginControllerAPIClient("127.0.0.1", 9977)
90
91 model.api.log("Importing report type: %s , (%s) - (%s)" % (parser.report_type, filename, sha1OfFile(filename)))
92
93 command_string = "./%s report" % parser.report_type.lower()
94 model.api.devlog("Executing %s" % (command_string))
95
96 new_cmd, output_file = client.send_cmd(command_string)
97 client.send_output(command_string, filename)
98 else:
99 model.api.log("Report type not found: (%s)" % (filename))
100
101 os.rename(filename, os.path.join(self._report_ppath, name))
102
103 self.onlinePlugins()
104
105
106 def onlinePlugins(self):
107 """
108 Process online plugins
109 """
110 _pluginsOn={"MetasploitOn" : "./metasploiton online",}
111 _pluginsOn.update({"Beef" : "./beef online",})
112 _psettings=CONF.getPluginSettings()
113
114 for k,v in _pluginsOn.iteritems():
115 if k in _psettings:
116 if _psettings[k]['settings']['Enable'] == "1":
117 new_cmd = self.plugin_controller.processCommandInput("", "",
118 "",
119 v,
120 False)
121
122 self.plugin_controller.storeCommandOutput("")
123
124 self.plugin_controller.onCommandFinished()
125
126
127
128 class ReportXmlParser(object):
129
130 """Plugin that handles XML report files.
131
132 :param xml_filepath: Xml file.
133
134 :class:`.LoadReportXML`
135 """
136
137 def __init__(self, xml_report_path):
138 self.report_type = ""
139 root_tag,output = self.getRootTag(xml_report_path)
140
141 if root_tag:
142 self.report_type = self.rType(root_tag,output)
143 model.api.devlog(self.report_type)
144
145 def getRootTag(self, xml_file_path):
146 result = f = None
147 try:
148 f = open(xml_file_path, 'rb')
149 try:
150 for event, elem in ET.iterparse(f, ('start', )):
151 result = elem.tag
152 break
153 except SyntaxError, err:
154 self.report_type = None
155 model.api.devlog("Not an xml file.\n %s" % (err))
156
157 except IOError, err:
158 self.report_type = None
159 model.api.devlog("Error while opening file.\n%s. %s" % (err, xml_file_path))
160 finally:
161 f.seek(0)
162 output=f.read()
163 if f: f.close()
164
165 return result,output
166
167 def rType(self, tag, output):
168 """Compares report root tag with known root tags.
169
170 :param root_tag
171 :rtype
172 """
173 if "arachni_report" == tag:
174 return "arachni"
175 elif "nmaprun" == tag:
176 return "nmap"
177 elif "w3afrun" == tag:
178 return "w3af"
179 elif "NessusClientData_v2" == tag:
180 return "nessus"
181 elif "report" == tag:
182 if re.search("alertitem",output) is None:
183 return "openvas"
184 else:
185 return "zap"
186 elif "niktoscan" == tag:
187 return "nikto"
188 elif "MetasploitV4" == tag:
189 return "metasploit"
190 elif "MetasploitV5" == tag:
191 return "metasploit"
192 elif "issues" == tag:
193 return "burp"
194 elif "OWASPZAPReport" == tag:
195 return "zap"
196 elif "ScanGroup" == tag:
197 return "acunetix"
198 elif "session" == tag:
199 return "x1"
200 elif "landscapePolicy" == tag:
201 return "x1"
202 elif "entities" == tag:
203 return "impact"
204 elif "NeXposeSimpleXML" == tag:
205 return "nexpose"
206 elif "SCAN" == tag:
207 return "qualysguard"
208 elif "scanJob" == tag:
209 return "retina"
210 elif "netsparker" == tag:
211 return "netsparker"
212 else:
213 return None
214
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
8 import os
9 import model.api
10 import threading
11 import time
12 import traceback
13 import re
14 import requests
15 try:
16 import xml.etree.cElementTree as ET
17
18 except ImportError:
19 print "cElementTree could not be imported. Using ElementTree instead"
20 import xml.etree.ElementTree as ET
21 from apis.rest.api import PluginControllerAPIClient
22
23 from config.configuration import getInstanceConfiguration
24 CONF = getInstanceConfiguration()
25
26 class NoReportsWatchException(Exception): pass
27
28 class ReportManager(threading.Thread):
29 def __init__(self, timer, plugin_controller, path=None):
30 threading.Thread.__init__(self)
31 self.setDaemon(True)
32 self.timer = timer
33 self._stop = False
34 self.path = path
35 self.plugin_controller = plugin_controller
36 self._report_path = None
37 self._report_ppath = None
38
39 def run(self):
40 tmp_timer = 0
41 while not self._stop:
42
43 time.sleep(1)
44 tmp_timer += 1
45 if tmp_timer == self.timer:
46 try:
47 self.syncReports()
48 except Exception:
49 model.api.devlog("An exception was captured while saving reports\n%s" % traceback.format_exc())
50 finally:
51 tmp_timer = 0
52
53 def stop(self):
54 self._stop = True
55
56 def watch(self, name):
57 self._report_path = os.path.join(CONF.getReportPath(), name)
58 self._report_ppath = os.path.join(self._report_path, "process")
59
60 if not os.path.exists(self._report_path):
61 os.mkdir(self._report_path)
62
63 if not os.path.exists(self._report_ppath):
64 os.mkdir(self._report_ppath)
65
66 def startWatch(self):
67 if not self._report_path:
68 raise NoReportsWatchException()
69 self.start()
70
71 def syncReports(self):
72 """
73 Synchronize report directory using the DataManager and Plugins online
74 We first make sure that all shared reports were added to the repo
75 """
76
77 for root, dirs, files in os.walk(self._report_path, False):
78
79 if root == self._report_path:
80 for name in files:
81 filename = os.path.join(root, name)
82 model.api.devlog( "Report file is %s" % filename)
83
84 parser = ReportXmlParser(filename)
85 if (parser.report_type is not None):
86 #TODO: get host and port from config
87 client = PluginControllerAPIClient("127.0.0.1", 9977)
88
89 model.api.devlog("The file is %s, %s" % (filename,parser.report_type))
90
91 command_string = "./%s %s" % (parser.report_type.lower(), filename)
92 model.api.devlog("Executing %s" % (command_string))
93
94 new_cmd, output_file = client.send_cmd(command_string)
95 client.send_output(command_string, filename)
96 os.rename(filename, os.path.join(self._report_ppath, name))
97
98 self.onlinePlugins()
99
100
101 def onlinePlugins(self):
102 """
103 Process online plugins
104 """
105 _pluginsOn={"MetasploitOn" : "./metasploiton online",}
106 _pluginsOn.update({"Beef" : "./beef online",})
107 _psettings=CONF.getPluginSettings()
108
109 for k,v in _pluginsOn.iteritems():
110 if k in _psettings:
111 if _psettings[k]['settings']['Enable'] == "1":
112 new_cmd = self.plugin_controller.processCommandInput("", "",
113 "",
114 v,
115 False)
116
117 self.plugin_controller.storeCommandOutput("")
118
119 self.plugin_controller.onCommandFinished()
120
121
122
123 class ReportXmlParser(object):
124
125 """Plugin that handles XML report files.
126
127 :param xml_filepath: Xml file.
128
129 :class:`.LoadReportXML`
130 """
131
132 def __init__(self, xml_report_path):
133 self.report_type = ""
134 root_tag,output = self.getRootTag(xml_report_path)
135
136 if root_tag:
137 self.report_type = self.rType(root_tag,output)
138 model.api.devlog(self.report_type)
139
140 def getRootTag(self, xml_file_path):
141 result = f = None
142 try:
143 f = open(xml_file_path, 'rb')
144 try:
145 for event, elem in ET.iterparse(f, ('start', )):
146 result = elem.tag
147 break
148 except SyntaxError, err:
149 self.report_type = None
150 model.api.devlog("Not an xml file.\n %s" % (err))
151
152 except IOError, err:
153 self.report_type = None
154 model.api.devlog("Error while opening file.\n%s. %s" % (err, xml_file_path))
155 finally:
156 f.seek(0)
157 output=f.read()
158 if f: f.close()
159
160 return result,output
161
162 def rType(self, tag, output):
163 """Compares report root tag with known root tags.
164
165 :param root_tag
166 :rtype
167 """
168 if "arachni_report" == tag:
169 return "arachni"
170 elif "nmaprun" == tag:
171 return "nmap"
172 elif "w3af-run" == tag:
173 return "w3af"
174 elif "NessusClientData_v2" == tag:
175 return "nessus"
176 elif "report" == tag:
177 if re.search("alertitem",output) is None:
178 return "openvas"
179 else:
180 return "zap"
181 elif "niktoscan" == tag:
182 return "nikto"
183 elif "MetasploitV4" == tag:
184 return "metasploit"
185 elif "MetasploitV5" == tag:
186 return "metasploit"
187 elif "issues" == tag:
188 return "burp"
189 elif "OWASPZAPReport" == tag:
190 return "zap"
191 elif "ScanGroup" == tag:
192 return "acunetix"
193 elif "session" == tag:
194 return "x1"
195 elif "landscapePolicy" == tag:
196 return "x1"
197 elif "entities" == tag:
198 return "impact"
199 elif "NeXposeSimpleXML" == tag:
200 return "nexpose"
201 elif "NexposeReport" == tag:
202 return "nexpose-full"
203 elif "SCAN" == tag:
204 return "qualysguard"
205 elif "scanJob" == tag:
206 return "retina"
207 elif "netsparker" == tag:
208 return "netsparker"
209 else:
210 return None
1818 from managers.all import ViewsManager
1919
2020 #from persistence.change import change_factory
21
21 from config.globals import CONST_BLACKDBS
2222 from config.configuration import getInstanceConfiguration
2323 CONF = getInstanceConfiguration()
2424
522522
523523 #@trap_timeout
524524 def _loadDbs(self):
525 conditions = lambda x: not x.startswith("_") and x != 'reports'
525 conditions = lambda x: not x.startswith("_") and x not in CONST_BLACKDBS
526526 for dbname in filter(conditions, self.__serv.all_dbs()):
527527 if dbname not in self.dbs.keys():
528528 getLogger(self).debug(
2626 __email__ = "[email protected]"
2727 __status__ = "Development"
2828
29
30
31
29
30
31
3232
3333 class HydraParser(object):
3434 """
4343 reg = re.search("\[([^$]+)\]\[([^$]+)\] host: ([^$]+) login: ([^$]+) password: ([^$]+)",l)
4444 if reg:
4545 item = {'port' : reg.group(1), 'plugin' : reg.group(2), 'ip' : reg.group(3), 'login' : reg.group(4), 'password' : reg.group(5) }
46
46
4747 self.items.append(item)
4848
49
49
5050
5151
5252
8787 "-6":"prefer IPv6 addresses",
8888 "-v":"verbose mode / show login+pass combination for each attempt",
8989 "-V":"verbose mode / show login+pass combination for each attempt",
90 "-U":"service module usage details",
90 "-U":"service module usage details",
9191 }
9292
9393 global current_path
9494 self._output_file_path = os.path.join(self.data_path,
9595 "hydra_output-%s.txt" % self._rid)
96
97
96
97
9898
9999
100100 def parseOutputString(self, output, debug = False):
115115 for item in parser.items:
116116 service=item['plugin']
117117 port=item['port']
118
118
119119 if hosts.has_key(item['ip']) == False:
120120 hosts[item['ip']]=[]
121
121
122122 hosts[item['ip']].append([item['login'],item['password']])
123
123
124124 for k,v in hosts.iteritems():
125125 h_id = self.createAndAddHost(k)
126126 if self._isIPV4(k):
130130 s_id = self.createAndAddServiceToInterface(h_id,i_id,service,ports=[port],protocol="tcp",status="open")
131131 for cred in v:
132132 self.createAndAddCredToService(h_id,s_id, cred[0],cred[1])
133
133 self.createAndAddVulnToService(h_id, s_id, "Weak Credentials","[hydra found the following credentials]\nuser:%s\npass:%s" % (cred[0], cred[1]), severity="high")
134
134135 del parser
135136
136137 xml_arg_re = re.compile(r"^.*(-o\s*[^\s]+).*$")
137138 def processCommandString(self, username, current_path, command_string):
138139
139 self._output_file_path=os.path.join(self.data_path,"hydra_output-%s.txt" % random.uniform(1,10))
140 self._output_file_path=os.path.join(self.data_path,"hydra_output-%s.txt" % random.uniform(1,10))
140141 arg_match = self.xml_arg_re.match(command_string)
141142
142143 if arg_match is None:
145146 return re.sub(arg_match.group(1),
146147 r"-o %s" % self._output_file_path,
147148 command_string)
148
149
149150 def _isIPV4(self, ip):
150151 if len(ip.split(".")) == 4:
151152 return True
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
0 '''
1 Faraday Penetration Test IDE
2 Copyright (C) 2015 Infobyte LLC (http://www.infobytesec.com/)
3 See the file 'doc/LICENSE' for the license information
4
5 '''
6 from plugins.repo.nmap.plugin import NmapPlugin
7 import os
8 import re
9 import random
10
11 current_path = os.path.abspath(os.getcwd())
12
13
14 class CmdMasscanPlugin(NmapPlugin):
15 """
16 Example plugin to parse amap output.
17 """
18 def __init__(self):
19 NmapPlugin.__init__(self)
20 self.id = "Masscan"
21 self.name = "Masscan Output Plugin"
22 self.plugin_version = "0.0.1"
23 self.version = "1.0.3"
24 self.options = None
25 self._command_regex = re.compile(r'^(masscan|sudo masscan|\.\/masscan|sudo \.\/masscan).*?')
26 self._output_file_path = os.path.join(self.data_path,
27 "masscan_output-%s.xml" % self._rid)
28
29 def processCommandString(self, username, current_path, command_string):
30 """
31 Adds the -oX parameter to get xml output to the command string that the
32 user has set.
33 """
34 self._output_file_path = os.path.join(self.data_path,"masscan_output-%s.xml" % random.uniform(1,10))
35
36 arg_match = self.xml_arg_re.match(command_string)
37
38
39 if arg_match is None:
40 return re.sub(r"(^.*?masscan)",
41 r"\1 -oX %s" % self._output_file_path,
42 command_string)
43 else:
44 return re.sub(arg_match.group(1),
45 r"-oX %s" % self._output_file_path,
46 command_string)
47
48
49 def createPlugin():
50 return CmdMasscanPlugin()
150150 s_id = self.createAndAddServiceToInterface(h_id,i_id,item['service'],ports=[port],protocol="tcp",status="open")
151151
152152 self.createAndAddCredToService(h_id,s_id, item['user'],item['pass'])
153
153 self.createAndAddVulnToService(h_id, s_id, "Weak Credentials","[medusa found the following credentials]\nuser:%s\npass:%s" % (item['user'], item['pass']), severity="high")
154154 del parser
155155
156156 xml_arg_re = re.compile(r"^.*(-O\s*[^\s]+).*$")
388388 if s['port'] in item.credsByService:
389389 for c in item.credsByService[s['port']]:
390390 self.createAndAddCredToService(h_id,s_id,c.user,c.passwd)
391 self.createAndAddVulnToService(h_id, s_id, "Weak Credentials","[metasploit found the following credentials]\nuser:%s\npass:%s" % (c.user, c.passwd), severity="high")
391392
392393 n_id = None
393394 for v in item.vulnsByService[s['id']]:
194194 for c in cur.fetchall():
195195 self._checkDate(str(c[3]))
196196 self.createAndAddCredToService(h_id,s_id,c[4],c[5])
197 self.createAndAddVulnToService(h_id, s_id, "Weak Credentials","[metasploit found the following credentials]\nuser:%s\npass:%s" % (c[4], c[5]), severity="high")
197198
198199
199200
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
0 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 '''
4 Faraday Penetration Test IDE
5 Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
6 See the file 'doc/LICENSE' for the license information
7
8 '''
9 from __future__ import with_statement
10 from plugins import core
11 from model import api
12 import re
13 import os
14 import pprint
15 import sys
16
17 try:
18 import xml.etree.cElementTree as ET
19 import xml.etree.ElementTree as ET_ORIG
20 ETREE_VERSION = ET_ORIG.VERSION
21 except ImportError:
22 import xml.etree.ElementTree as ET
23 ETREE_VERSION = ET.VERSION
24
25 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
26
27 current_path = os.path.abspath(os.getcwd())
28
29 __author__ = "Micaela Ranea Sanchez"
30 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
31 __credits__ = ["Francisco Amato", "Federico Kirschbaum", "Micaela Ranea Sanchez", "German Riera"]
32 __license__ = ""
33 __version__ = "1.0.0"
34 __maintainer__ = "Micaela Ranea Sanchez"
35 __email__ = "[email protected]"
36 __status__ = "Development"
37
38
39 class NexposeFullXmlParser(object):
40 """
41 The objective of this class is to parse Nexpose's XML 2.0 Report.
42
43 TODO: Handle errors.
44 TODO: Test nexpose output version. Handle what happens if the parser doesn't support it.
45 TODO: Test cases.
46
47 @param xml_filepath A proper xml generated by nexpose
48 """
49 def __init__(self, xml_output):
50 tree = self.parse_xml(xml_output)
51 vulns = self.get_vuln_definitions(tree)
52
53 if tree:
54 self.items = self.get_items(tree, vulns)
55 else:
56 self.items = []
57
58 def parse_xml(self, xml_output):
59 """
60 Open and parse an xml file.
61
62 TODO: Write custom parser to just read the nodes that we need instead of
63 reading the whole file.
64
65 @return xml_tree An xml tree instance. None if error.
66 """
67 try:
68 tree = ET.fromstring(xml_output)
69 except SyntaxError, err:
70 print "SyntaxError: %s. %s" % (err, xml_output)
71 return None
72
73 return tree
74
75 def parse_html_type(self, node):
76 """
77 Parse XML element of type HtmlType
78
79 @return ret A string containing the parsed element
80 """
81 ret = ""
82 tag = node.tag.lower()
83
84 if tag == 'containerblockelement':
85 if len(list(node)) > 0:
86 for child in list(node):
87 ret += self.parse_html_type(child)
88 else:
89 ret += str(node.text).strip()
90 if tag == 'listitem':
91 if len(list(node)) > 0:
92 for child in list(node):
93 ret += self.parse_html_type(child)
94 else:
95 ret = str(node.text).strip()
96 if tag == 'orderedlist':
97 i = 1
98 for item in list(node):
99 ret += "\t" + str(i) + " " + self.parse_html_type(item) + "\n"
100 i += 1
101 if tag == 'paragraph':
102 if len(list(node)) > 0:
103 for child in list(node):
104 ret += self.parse_html_type(child)
105 else:
106 ret += str(node.text).strip()
107 if tag == 'unorderedlist':
108 for item in list(node):
109 ret += "\t" + "* " + self.parse_html_type(item) + "\n"
110 if tag == 'urllink':
111 if node.text:
112 ret += str(node.text).strip() + " "
113 last = ""
114 for attr in node.attrib:
115 if node.get(attr) != node.get(last):
116 ret += str(node.get(attr)) + " "
117 last = attr
118
119 return ret
120
121 def parse_tests_type(self, node, vulnsDefinitions):
122 """
123 Parse XML element of type TestsType
124
125 @return vulns A list of vulnerabilities according to vulnsDefinitions
126 """
127 vulns = list()
128
129 for tests in node.iter('tests'):
130 for test in tests.iter('test'):
131 vuln = dict()
132 if test.get('id').lower() in vulnsDefinitions:
133 vuln = vulnsDefinitions[test.get('id').lower()]
134 for desc in list(test):
135 vuln['desc'] += self.parse_html_type(desc)
136 vulns.append(vuln)
137
138 return vulns
139
140 def get_vuln_definitions(self, tree):
141 """
142 @returns vulns A dict of Vulnerability Definitions
143 """
144 vulns = dict()
145
146 for vulnsDef in tree.iter('VulnerabilityDefinitions'):
147 for vulnDef in vulnsDef.iter('vulnerability'):
148 vid = vulnDef.get('id').lower()
149 vector = vulnDef.get('cvssVector')
150
151 vuln = {
152 'desc': "",
153 'name': vulnDef.get('title'),
154 'refs': [ "vector: " + vector, vid],
155 'resolution': "",
156 'severity': (int(vulnDef.get('severity'))-1)/2,
157 'tags': list()
158 }
159
160 for item in list(vulnDef):
161 if item.tag == 'description':
162 for htmlType in list(item):
163 vuln['desc'] += self.parse_html_type(htmlType)
164 if item.tag == 'exploits':
165 for exploit in list(item):
166 vuln['refs'].append(str(exploit.get('title')).strip() + ' ' + str(exploit.get('link')).strip())
167 if item.tag == 'references':
168 for ref in list(item):
169 vuln['refs'].append(str(ref.text).strip())
170 if item.tag == 'solution':
171 for htmlType in list(item):
172 vuln['resolution'] += self.parse_html_type(htmlType)
173 """
174 # there is currently no method to register tags in vulns
175 if item.tag == 'tags':
176 for tag in list(item):
177 vuln['tags'].append(tag.text.lower())
178 """
179 vulns[vid] = vuln
180
181 return vulns
182
183 def get_items(self, tree, vulns):
184 """
185 @return hosts A list of Host instances
186 """
187
188 hosts = list()
189
190 for nodes in tree.iter('nodes'):
191 for node in nodes.iter('node'):
192 host = dict()
193 host['name'] = node.get('address')
194 host['hostnames'] = set()
195 host['os'] = ""
196 host['services'] = list()
197 host['vulns'] = self.parse_tests_type(node, vulns)
198
199 for names in node.iter('names'):
200 for name in list(names):
201 host['hostnames'].add(name.text)
202
203 for fingerprints in node.iter('fingerprints'):
204 os = fingerprints.find('os')
205 if os is not None:
206 host['os'] = os.get('product', "")
207 if os.get('version') is not None:
208 host['os'] += " " + os.get('version')
209
210 for endpoints in node.iter('endpoints'):
211 for endpoint in list(endpoints):
212 svc = {
213 'protocol': endpoint.get('protocol'),
214 'port': endpoint.get('port'),
215 'status': endpoint.get('status'),
216 }
217 for services in endpoint.iter('services'):
218 for service in list(services):
219 svc['name'] = service.get('name')
220 svc['vulns'] = self.parse_tests_type(service, vulns)
221 for configs in service.iter('configurations'):
222 for config in list(configs):
223 if "banner" in config.get('name'):
224 svc['version'] = config.get('name')
225
226 host['services'].append(svc)
227
228 hosts.append(host)
229
230 return hosts
231
232 class NexposeFullPlugin(core.PluginBase):
233 """
234 Example plugin to parse nexpose output.
235 """
236 def __init__(self):
237 core.PluginBase.__init__(self)
238 self.id = "NexposeFull"
239 self.name = "Nexpose XML 2.0 Report Plugin"
240 self.plugin_version = "0.0.1"
241 self.version = "Nexpose Enterprise 5.7.19"
242 self.framework_version = "1.0.0"
243 self.options = None
244 self._current_output = None
245 self._command_regex = re.compile(r'^(sudo nexpose|\.\/nexpose).*?')
246
247 global current_path
248 self._output_file_path = os.path.join(self.data_path,
249 "nexpose_full_output-%s.xml" % self._rid)
250
251 def parseOutputString(self, output, debug = False):
252 parser = NexposeFullXmlParser(output)
253
254 for item in parser.items:
255 h_id = self.createAndAddHost(item['name'], item['os'])
256 i_id = self.createAndAddInterface(h_id, item['name'], ipv4_address = item['name'], hostname_resolution = item['hostnames'])
257
258 for v in item['vulns']:
259 v_id = self.createAndAddVulnToHost(h_id, v['name'], v['desc'], v['refs'], v['severity'], v['resolution'])
260
261 for s in item['services']:
262 web = False
263 version = s.get("version", "")
264
265 s_id = self.createAndAddServiceToInterface(h_id, i_id, s['name'],
266 s['protocol'],
267 ports = [str(s['port'])],
268 status = s['status'],
269 version = version)
270 for v in s['vulns']:
271 v_id = self.createAndAddVulnToService(h_id, s_id, v['name'], v['desc'], v['refs'], v['severity'], v['resolution'])
272 del parser
273
274 def processCommandString(self, username, current_path, command_string):
275 return None
276
277
278 def setHost(self):
279 pass
280
281
282 def createPlugin():
283 return NexposeFullPlugin()
284
285 if __name__ == '__main__':
286 parser = NexposeFullXmlParser(sys.argv[1])
287 for item in parser.items:
288 if item.status == 'up':
289 print item
538538 description = srvname)
539539 note=True
540540 for v in port.vulns:
541 severity = 0
541542 desc=v.desc
542543 desc+="\nOutput: "+ v.response if v.response else ""
544
545 if re.search(r"VULNERABLE",desc):
546 severity = "high"
547 if re.search(r"ERROR",desc):
548 severity = "unclassified"
549 if re.search(r"Couldn't",desc):
550 severity = "unclassified"
543551 if v.web:
544552 if note:
545553 n_id = self.createAndAddNoteToService(h_id,s_id,"website","")
546554 n2_id = self.createAndAddNoteToNote(h_id,s_id,n_id,minterfase,"")
547555 note=False
548556 v_id = self.createAndAddVulnWebToService(h_id,s_id,v.name,desc=desc,
549 severity=0,website=minterfase)
557 severity=severity,website=minterfase)
550558 else:
551559 v_id = self.createAndAddVulnToService(h_id,s_id,v.name,desc=v.desc,
552 severity=0)
560 severity=severity)
553561
554562 del parser
555563
8686 bugtype=""
8787
8888
89 scaninfo = tree.findall('scaninfo')[0]
89 scaninfo = tree.findall('scan-info')[0]
9090 self.target = scaninfo.get('target')
9191 host = re.search("(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))[\:]*([0-9]+)*([/]*($|[a-zA-Z0-9\.\,\?\'\\\+&amp;%\$#\=~_\-]+)).*?$", self.target)
9292
153153 self.id=self.node.get('id')
154154 self.name = self.node.get('name')
155155 self.url = self.node.get('url')
156 self.url = self.url if self.url != 'None' else "/"
156157 self.plugin = self.node.get('plugin')
157158 self.detail = self.get_text_from_subnode('description')
159 self.resolution = self.get_text_from_subnode('fix-guidance')
160 self.fix_effort = self.get_text_from_subnode('fix-effort')
161 self.longdetail = self.get_text_from_subnode('description')
158162 self.severity = self.node.get('severity')
159163 self.method = self.node.get('method')
164 self.ref = []
160165 self.param = self.node.get('var') if self.node.get('var') != "None" else ""
166 for ref in self.node.findall('references/reference'):
167 self.ref.append(ref.get('url'))
168
161169 self.req = self.resp = ''
162170 for tx in self.node.findall('http-transactions/http-transaction'):
163
164 self.req = tx.find('httprequest/status').text
165
166 self.resp = tx.find('httpresponse/status').text
171 self.req = tx.find('http-request/status').text
172 for h in tx.findall('http-request/headers/header'):
173 self.req += "\n%s: %s" % (h.get('field'),h.get('content'))
174
175 self.resp = tx.find('http-response/status').text
176 for h in tx.findall('http-response/headers/header'):
177 self.resp += "\n%s: %s" % (h.get('field'),h.get('content'))
178 self.resp += "\n%s" % tx.find('http-response/body').text
179
167180
168181 def do_clean(self,value):
169182 myreturn =""
193206 core.PluginBase.__init__(self)
194207 self.id = "W3af"
195208 self.name = "W3af XML Output Plugin"
196 self.plugin_version = "0.0.1"
197 self.version = "1.2"
209 self.plugin_version = "0.0.2"
210 self.version = "1.7.6"
198211 self.framework_version = "1.0.0"
199212 self.options = None
200213 self._current_output = None
203216 self._completition = {
204217 "":"",
205218 "-h":"Display this help message.",
206 "-p":"-p &lt;profile&gt; Run with the selected &lt;profile&gt;",
207219 }
208220
209221 global current_path
229241 for item in parser.items:
230242 v_id = self.createAndAddVulnWebToService(h_id, s_id, item.name,
231243 item.detail, pname=item.param, path=item.url, website=parser.host, severity=item.severity,
232 method=item.method, request=item.req, response=item.resp)
244 method=item.method, request=item.req, resolution=item.resolution, ref=item.ref, response=item.resp)
233245 del parser
234246
235247
3636 logger.info('Installing missing dependencies in pip')
3737 pip.main(['install', '-r', CONST_REQUIREMENTS_FILE, '--user'])
3838
39 logger.info('Upgrading DBs to latest version')
40 DB().run()
39 # logger.info('Upgrading DBs to latest version')
40 # DB().run()
4141
4242 logger.info('Upgrading DBs to latest version')
4343 CouchViews().run()
7979 # if not query_yes_no("Faraday won't behave correctly with older versions, proceed?", 'no'):
8080 # return
8181
82 dbs = filter(lambda x: not x.startswith("_") and 'backup' not in x and \
83 'reports' not in x, serv.all_dbs())
82 dbs = filter(lambda x: not x.startswith("_") and 'backup' not in x and x not in CONST_BLACKDBS, serv.all_dbs())
8483 logger.info('Dbs to upgrade: %s' % (', '.join(dbs)))
8584
8685
172171 serv = couchdbkit.Server(source_server)
173172
174173 logger.info('We are about to upgrade dbs in Server [%s]' % source_server)
175 dbs = filter(lambda x: not x.startswith("_") and 'backup' not in x and 'reports' not in x, serv.all_dbs())
174 dbs = filter(lambda x: not x.startswith("_") and 'backup' not in x and x not in CONST_BLACKDBS, serv.all_dbs())
176175 logger.info('Dbs to upgrade: %s' % (', '.join(dbs)))
177176
178177 if not query_yes_no('Proceed?', 'no'):
11 /* Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) */
22 /* See the file 'doc/LICENSE' for the license information */
33 /*reset*/
4 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body {line-height:1}ol,ul {list-style:none}blockquote,q {quotes:none}:focus {outline:0}ins {text-decoration:none}del {text-decoration:line-through}table {border-collapse:collapse;border-spacing:0}ul,li {list-style:none}.clearfix:after{content:".";display:block;clear:both;visibility:hidden;line-height:0; height:0}
4 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {margin:0;padding:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body {line-height:1}ol,ul {list-style:none}blockquote,q {quotes:none}:focus {outline:0}ins {text-decoration:none}del {text-decoration:line-through}table {border-collapse:collapse;border-spacing:0}ul,li {list-style:none}.clearfix:after{content:".";display:block;clear:both;visibility:hidden;line-height:0; height:0}
55 .clearfix{display:inline-block}html[xmlns] .clearfix{display:block}* html .clearfix{height:1%}
66 /**/
7 @font-face {
8 font-family: 'Ubuntu';
9 font-style: normal;
10 font-weight: 300;
11 src: local('Ubuntu Light'), local('Ubuntu-Light'), url(fonts/ubuntu/_aijTyevf54tkVDLy-dlnLO3LdcAZYWl9Si6vvxL-qU.woff) format('woff');
12 }
13 @font-face {
14 font-family: 'Ubuntu';
15 font-style: normal;
16 font-weight: 400;
17 src: local('Ubuntu'), url(fonts/ubuntu/vRvZYZlUaogOuHbBTT1SNevvDin1pK8aKteLpeZ5c0A.woff) format('woff');
18 }
19 @font-face {
20 font-family: 'Ubuntu';
21 font-style: normal;
22 font-weight: 700;
23 src: local('Ubuntu Bold'), local('Ubuntu-Bold'), url(fonts/ubuntu/0ihfXUL2emPh0ROJezvraLO3LdcAZYWl9Si6vvxL-qU.woff) format('woff');
24 }
25 @font-face {
26 font-family: 'Ubuntu';
27 font-style: italic;
28 font-weight: 400;
29 src: local('Ubuntu Italic'), local('Ubuntu-Italic'), url(/fonts/ubuntu/kbP_6ONYVgE-bLa9ZRbvvnYhjbSpvc47ee6xR_80Hnw.woff) format('woff');
30 }
317 html#no-overflow{overflow-x:hidden;}
328 body {
33 font:62.5%/1.5 'Ubuntu',Helvetica,Arial,sans-serif!important;
9 font:62.5%/1.5 ,Helvetica,Arial,sans-serif!important;
3410 color: #2D2F31;
35 background: #E8EFF0!important;
11 background: #F5F5F5 !important;
3612 }
3713 ul{padding:0 0 0 0;margin-bottom: 20px;}
3814 a {
175151 text-align: left;
176152 }
177153 .seccion article header {
178 background: #3F4649;
154 background: #FFFFFF;
179155 min-height: 40px;
180156 text-align: left;
181157 }
182158 .seccion article header h2 {
183 color: #fff;
184 font-size: 17px;
159 color: #101010;
160 font-size: 14px;
185161 width: 100%;
186162 margin: 0 12px;
187163 padding: 0;
210186 }
211187 .sin_padding h2{padding-bottom: 16px;}
212188
213 /* ==== COLORES generales ==== */
214 /* Fondos */
189 /* ==== General COLORS ==== */
190 /* Backgrounds Legacy */
215191 .fondo-rojo, .fondo-high, .fondo-error {background-color: #DF3936 !important;}
216192 .fondo-negro {background-color: #000 !important;}
217193 .fondo-gris1, .fondo-critical {background-color: #932ebe !important;}
221197 .fondo-naranja, .fondo-med {background-color: #DFBF35 !important;}
222198 .fondo-amarillo, .fondo-low, .fondo-created{background-color: #A1CE31 !important;}
223199 .fondo-violeta {background-color: #932ebe !important;}
224 /* Textos*/
200 /* Backgrounds New */
201 .background-unclassified {
202 background-color: #ffffff !important;
203 border: solid 1px #999999;
204 }
205 .background-info {
206 background-color: #ffffff !important;
207 border: solid 1px #2e97bd;
208 }
209 .background-low {
210 background-color: #ffffff !important;
211 border: solid 1px #a1ce31;
212 }
213 .background-med {
214 background-color: #ffffff !important;
215 border: solid 1px #dfbf35;
216 }
217 .background-high {
218 background-color: #ffffff !important;
219 border: solid 1px #df3936;
220 }
221 .background-critical {
222 background-color: #ffffff !important;
223 border: solid 1px #932ebe;
224 }
225 /* Texts Legacy*/
225226 .texto-rojo {color: #DF3936;}
226227 .texto-negro {color: #000;}
227228 .texto-gris1 {color: #2D2F31;}
228 .texto-blanco {color: #fff;}
229
230 /* Home Menu grande */
229 .texto-blanco {color: #6B6565;}
230 /* Texts New*/
231 .text-unclassified {
232 color: #999999 !important;
233 }
234 .text-info {
235 color: #2e97bd !important;
236 }
237 .text-low {
238 color: #a1ce31 !important;
239 }
240 .text-med {
241 color: #dfbf35 !important;
242 }
243 .text-high {
244 color: #df3936 !important;
245 }
246 .text-critical {
247 color: #932ebe !important;
248 }
249 /* Opacity */
250 .opacity-low {
251 opacity: 0.6;
252 }
253 .opacity-med {
254 opacity: 0.8;
255 }
256 .opacity-high {
257 opacity: 1;
258 }
259 /* Big Home menu */
231260 .home-list {
232261 margin-top: 20px;
233262 }
305334
306335 /* Icons on Home */
307336 .icons-color-home{color: #B3B4B5;}
308 .fa.icons-size-home{font-size: 9em;}
337 .fa.host{font-size: 2.6em;}
309338
310339 /* Datos con nro grande, titulo y texto */
311340 .dato1 {
321350 .dato2 * {
322351 text-align: center;
323352 }
353 .dato2:hover {
354
355 }
324356 .dato2 .nro {
325357 font-size: 300%;
326 font-weight: 300;
358 font-weight: 400;
327359 letter-spacing: -.1em;
328360 }
329361 .dato2 .txt {
348380 margin: 5px;
349381 }
350382 table thead th a {
351 color: #bbb;
383 color: #2E91D8;
352384 font-weight: normal;
353385 }
354386 table thead th a:hover {
377409 cursor: pointer;
378410 }
379411 table.tablesorter thead tr th, table.tablesorter tfoot tr th {
380 background-color: #3F464C;
412 background-color: #FFFFFF;
381413 color: #fff;
382414 border: 1px solid #FFF;
383 font-size: 14px;
415 font-size: 12px;
384416 }
385417
386418 table.tablesorter tbody td {
456488 table.status-report tbody td {
457489 color: #3D3D3D;
458490 padding: 5px;
459 vertical-align: top;
460491 }
461492
462493 table.status-report tbody tr.odd td {
484515 background-color: #f2dede !important;
485516 }
486517
518 table.last-vuln th{text-align: center;}
519 #list .tablesorter thead th:first-child{width: 49%;}
487520 #list .tablesorter thead th {
488 width: 45%;
521 width: 36%;
522 text-align: center;
489523 border:1px solid;
490524 }
491525 #list tbody{display: block}
493527 #list .tablesorter tbody td {width: 51.6%}
494528 #list .tablesorter tbody td:nth-child(2){width: 51%;word-break: break-all;}
495529 #list .tablesorter thead th:last-child{width: 19%}
530 /* Fixed */
531 .table-fixed thead {
532 width: 100%;
533 }
534 .table-fixed tbody {
535 height: 230px;
536 overflow-y: auto;
537 width: 100%;
538 }
539 .table-fixed thead, .table-fixed tbody, .table-fixed tr, .table-fixed td, .table-fixed th {
540 display: block;
541 }
542 .table-fixed tbody td, .table-fixed thead > tr> th {
543 float: left;
544 border-bottom-width: 0;
545 }
546 .table-fixed th{text-align: center}
547 .table-fixed th{padding-right: 6%!important;}
496548 #compound tbody{display: block;max-height: 370px}
497 #compound .tablesorter tr {display: table-row;}
498 #compound .tablesorter tbody td {width: 48%}
499549 #compound .tablesorter tbody td span,#compound .tablesorter tbody td img{margin-right: 25px}
500 #compound .tablesorter thead th:first-child{width: 54%}
501 #compound .tablesorter thead th {
502 width: 27%;
503 float: left;
504 border:1px solid;
505 }
506 #compound .tablesorter thead th:last-child{width: 19%}
507550 article#compound.panel{
508551 height: 93px;
509552 padding-bottom: 428px;
611654 #treemap, #bar, #cake{height:195px}
612655 #vulns .columna{margin-left:2%}
613656 #vulns .main{width:100%;height:105px}
614 #vulns-by-price .main{width:100% !important;height: 180px !important;}
657 #vulns-by-price .main{width:100% !important;height: 140px !important;}
615658 #vulns .columna.unsexto{margin: auto;}
616659 #summarized .main{height:197px}
617660 #summarized .panel.panel-default,#byservices .panel.panel-default{max-height: 239px}
677720 .left_auths{margin:5px;float:right;margin-top: -52px;}
678721 .left_auth{margin:5px;float:right;margin-top: -40px;}
679722
680 div.box div.columna:nth-child(even){background-color: #DF3936; color: #000!important;}
681 div.box div.columna:nth-child(odd){background-color: #000; color: #DF3936!important;}
723 div.box div.columna {
724 background-color: #F5F5F5; color: #6B6565!important;
725 }
726 div.box div.columna:hover {
727 background-color: #E9E9E9; color: #6B6565!important;
728 }
682729 #merge, #delete, #new{margin:5px;float:right;}
683730 .input-sm{float: left;margin-bottom: 20px;}
684731 /* Media */
936983 font-weight: bold;
937984 }
938985 .text-center{text-align: center; width: 25px;}
986 .severities .color-unclassified, .severities .color-unclassified:hover{color: #999;}
987 .severities .color-info, .severities .color-info:hover{color: #2e97bd;}
988 .severities .color-low, .severities .color-low:hover{color: #A1CE31;}
989 .severities .color-med, .severities .color-med:hover{color: #DFBF35;}
990 .severities .color-high, .severities .color-high:hover{color: #DF3936;}
991 .severities .color-critical, .severities .color-critical:hover{color: #932ebe;}
992 .severities > button{
993 width: 100%;
994 text-align: left;
995 }
996 .severities > button > span{
997 color: #000;
998 float: right;
999 margin-top: 8px;
1000 }
1001 .severities > .dropdown-menu-left{left: 14px;}
1002 .severities button.button-error{
1003 border-color: #a94442;
1004 -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
1005 box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
1006 }
234234 || v.os.toLowerCase().indexOf("unix") > -1) icon = "linux";
235235 var os = "";
236236 if(icon === "") {
237 os = "<span class=\"glyphicon glyphicon-question-sign faraday-qtips\" title="+v.os+"></span>";
237 os = "<span class=\"fa fa-laptop faraday-qtips\" title="+v.os+"></span>";
238238 } else {
239239 os = "<img src=\"../././reports/images/"+icon+".png\" class=\"faraday-qtips\" title=\""+v.os+"\"/>";
240240 }
210210 || v.os.toLowerCase().indexOf("unix") > -1) icon = "linux";
211211 var os = "";
212212 if(icon === "") {
213 os = "<span class=\"glyphicon glyphicon-question-sign faraday-qtips\" title="+v.os+"></span>";
213 os = "<span class=\"fa fa-laptop faraday-qtips\" title="+v.os+"></span>";
214214 } else {
215215 os = "<img src=\"../././reports/images/"+icon+".png\" class=\"faraday-qtips\" title=\""+v.os+"\"/>";
216216 }
261261 || cleanOs.toLowerCase().indexOf("unix") > -1) icon = "linux";
262262 var os = "";
263263 if(icon === "") {
264 os = "<span class=\"glyphicon glyphicon-question-sign faraday-qtips\" title="+cleanOs+"></span>";
264 os = "<span class=\"fa fa-laptop faraday-qtips\" title="+cleanOs+"></span>";
265265 } else {
266266 os = "<img src=\"../././reports/images/"+icon+".png\" class=\"faraday-qtips\" title=\""+cleanOs+"\"/>";
267267 }
2424 })())
2525 .constant("SEVERITIES", (function() {
2626 var severities = [
27 "unclassified",
27 "critical",
28 "high",
29 "med",
30 "low",
2831 "info",
29 "low",
30 "med",
31 "high",
32 "critical"
32 "unclassified"
3333 ];
3434 return severities;
3535 })());
3636
37 faradayApp.config(['$routeProvider', function($routeProvider) {
37 faradayApp.config(['$routeProvider', 'ngClipProvider', function($routeProvider, ngClipProvider) {
38 ngClipProvider.setPath("script/ZeroClipboard.swf");
3839 $routeProvider.
3940 when('/dashboard/ws/:wsId', {
4041 templateUrl: 'scripts/dashboard/partials/dashboard.html',
55 <h5>{{msg}}</h5>
66 </div>
77 <div class="modal-body">
8 <select class="form-control" ng-model="data.property" ng-options="o as o for o in options">
9 </select>
8 <div class="form-group">
9 <div class="col-md-12 form-group severities">
10 <button type="button" class="btn btn-default dropdown-toggle color-{{data.property}}" data-toggle="dropdown" title="Change severity">
11 {{data.property || 'Edit severity'}} <span class="caret"></span>
12 </button>
13 <ul id="nav" class="dropdown-menu dropdown-menu-left" role="menu">
14 <li ng-repeat="o in options"><a href="" class="ws color-{{o}}" ng-click="data.property = o">{{o}}</a></li>
15 </ul><!-- WS navigation -->
16 </div>
17 </div>
1018 </div>
1119 <div class="modal-footer">
1220 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
3535 </small>
3636 </a>
3737 <a href="#/hosts" class="ws-link item animated flipInX">
38 <i class="fa fa-sitemap fa-5x icons-color-home icons-size-home"></i>
38 <i class="fa fa-sitemap fa-4x icons-color-home"></i>
3939 <span class="ws-name">Hosts</span>
4040 <small>
4141 Hosts and Services CRUD<br/>
22 <!-- See the file 'doc/LICENSE' for the license information -->
33
44 <div class="modal-header">
5 <h3 class="modal-title">Oops!</h3>
5 <h3 class="modal-title"><span class="glyphicon glyphicon-exclamation-sign"></span>Oops!</h3>
66 </div>
77 <div class="modal-body">
88 <h5>{{ msg }}</h5>
6767 .data(data)
6868 .enter()
6969 .append('rect')
70 .attr("class", "bar")
70 .attr("class", function(d) { return "id-" + d.key + " bar"; })
7171 .attr("x", function(d) { return x(d.key); })
7272 .attr("y", function(d) { return y(d.value - 0.5); })
7373 .style("fill", function(d) { return color(Math.random()*55); })
7474 .attr("height", function(d) { return height - margin.top - margin.bottom - y(d.value); })
7575 .attr("width", 30)
7676 .style('opacity', 0)
77 .on('mouseover', function(d){
78 workspace = $routeParams.wsId;
79 var hurl = "/" + workspace + "/_design/hosts/_view/hosts";
80 hosts = get_obj(hurl);
81 var name = hosts[d.key].name;
82 document.getElementById("barText").innerHTML = "<div style='background-color:" + d.color + "'><b>" + name + '</b></div>' + d.value;
83
77 .on('mouseover', function(d) {
78 workspace = $routeParams.wsId;
79 var hurl = "/" + workspace + "/_design/hosts/_view/hosts";
80 hosts = get_obj(hurl);
81 var name = hosts[d.key].name;
82 document.getElementById("barText").innerHTML = "<div style='background-color:" + d.color + "'><b>" + name + '</b></div>' + d.value;
8483 })
85 .on('mouseleave', function(){
86 document.getElementById("barText").innerHTML = "";
84 .on('mouseenter', function(d) {
85 var line = d3.select('.id-'+d.key)
86 .style("opacity", 1);
87 })
88 .on('mouseleave', function(d) {
89 document.getElementById("barText").innerHTML = "";
90 var line = d3.select('.id-'+d.key)
91 .style("opacity", 0.8);
8792 })
8893 .transition()
8994 .duration(1250)
90 .style('opacity', 1);
95 .style('opacity', 0.8);
9196
9297 function get_obj(ourl) {
9398 var ls = {};
8888 .attr("display", function(d) { return d.depth ? null : "none"; })
8989 .attr("d", arc)
9090 .attr("fill-rule", "evenodd")
91 .attr("class", function(d) {
92 var key = "";
93 if(d.key) {
94 key = "cake-" + d.key;
95 }
96 return key;
97 })
9198 .style("fill", function(d) {return d.color; })
9299 .style("stroke-width", "0.5")
93100 .style("opacity", 0)
94 .on('mouseover', function(d){
95 document.getElementById("cakeText").innerHTML = "<div style='background-color:" + d.color + "'><b>" + d.key + '</b></div>' + d.value;
101 .on('mouseover', function(d) {
102 document.getElementById("cakeText").innerHTML = "<div style='background-color:" + d.color + "'><b>" + d.key + '</b></div>' + d.value;
96103 })
97 .on('mouseleave', function(){
98 document.getElementById("cakeText").innerHTML = "";
104 .on('mouseenter', function(d) {
105 var slice = d3.select('.cake-'+d.key)
106 .style("opacity", 1);
107 })
108 .on('mouseleave', function(d) {
109 var slice = d3.select('.cake-'+d.key)
110 .style("opacity", 0.8);
111 document.getElementById("cakeText").innerHTML = "";
99112 })
100113 .transition()
101114 .duration(1250)
102 .style('opacity', 1);
115 .style('opacity', 0.8);
103116
104117 // Get total size of the tree = value of root node from partition.
105118 totalSize = path.node().__data__.value;
2727 d3.select('.stackedbars').selectAll('svg').remove();
2828
2929 var margins = {
30 top: 12,
31 left: 24,
32 right: 12,
33 bottom: 12
30 top: 5,
31 left: 15,
32 right: 5,
33 bottom: 5
3434 };
3535
3636 // get parent width to calculate graphic width
3737 var pwidth = ele.parent().width(),
3838 width = pwidth * 0.9,
39 height = 80 - margins.top - margins.bottom;
39 height = 30 - margins.top - margins.bottom;
4040
4141 var dataset = data.map(function(d) {
4242 return [{
116116 .attr('tooltip-append-to-body', true)
117117 .attr('tooltip', function(d) {
118118 return d.k + " sums $" + d.x;
119 })
120 .attr('class', function(d) {
121 return "sb-" + d.k;
122 })
123 .style('opacity', 0.8)
124 .on('mouseenter', function(d) {
125 var line = d3.select('.sb-'+d.k)
126 .style("opacity", 1);
127 })
128 .on('mouseleave', function(d) {
129 var line = d3.select('.sb-'+d.k)
130 .style("opacity", 0.8);
119131 });
120132
121133 ele.removeAttr("d3-horizontal-stacked-bar");
6161 var node = div.datum(data_cp).selectAll(".node")
6262 .data(treemap.nodes)
6363 .enter().append("div")
64 .attr("class", "node treemap-tooltip")
64 .attr("class", function(d) {
65 var ret = "node treemap-tooltip";
66 if(d.key) ret += " tm-" + d.key;
67 return ret;
68 })
6569 .call(position)
6670 .style("background", function(d) { return d.color; })
6771 .style('opacity', 0)
7882 document.getElementById("treemapTextModel").innerHTML = "<div style='background-color:" + d.color + "'>" + d.key + '</div>' + d.value;
7983 }
8084 })
81 .on('mouseleave', function(){
85 .on('mouseenter', function(d) {
86 var line = d3.select('.tm-'+d.key)
87 .style("opacity", 1);
88 })
89 .on('mouseleave', function(d) {
90 var line = d3.select('.tm-'+d.key)
91 .style("opacity", 0.8);
8292 document.getElementById("treemapText").innerHTML = "";
8393 })
8494 .transition()
8595 .duration(1250)
86 .style('opacity', 1);
96 .style('opacity', 0.8);
8797
8898 };
8999 });
260260 }
261261 };
262262
263 $scope.showServices = function(host_id) {
263 $scope.showServices = function(host) {
264264 if ($scope.workspace != undefined){
265265 var modal = $modal.open({
266266 templateUrl: 'scripts/dashboard/partials/modal-services-by-host.html',
267267 controller: 'summarizedCtrlServicesModal',
268268 size: 'lg',
269269 resolve: {
270 host_id: function(){
271 return host_id
270 host: function() {
271 return host
272272 },
273 workspace: function(){
273 workspace: function() {
274274 return $scope.workspace;
275275 }
276276 }
355355
356356 angular.module('faradayApp')
357357 .controller('summarizedCtrlServicesModal',
358 ['$scope', '$modalInstance', 'dashboardSrv', 'workspace', 'host_id',
359 function($scope, $modalInstance, dashboardSrv, workspace, host_id) {
360
358 ['$scope', '$modalInstance', 'dashboardSrv', 'workspace', 'host',
359 function($scope, $modalInstance, dashboardSrv, workspace, host) {
360
361 $scope.host = host
361362 $scope.sortField = 'port';
362363 $scope.sortReverse = false;
363364
377378 $scope.sortReverse = !$scope.sortReverse;
378379 }
379380
380 dashboardSrv.getServicesByHost(workspace, host_id).then(function(services){
381 dashboardSrv.getName(workspace, host_id).then(function(name){
381 dashboardSrv.getServicesByHost(workspace, host._id).then(function(services){
382 dashboardSrv.getName(workspace, host._id).then(function(name){
382383 $scope.name = name;
383384 $scope.services = services;
384385 })
0 <article id='compound' class='panel panel-default'>
0 <article id="compound" class='panel panel-default'>
11 <header>
22 <h2><a href="#/hosts/ws/{{workspace}}">Hosts</a>
33 <span class="glyphicon glyphicon-info-sign" tooltip="All hosts, each one showing its service count and operating system. By clicking on a host IP you can access a list with all of its services"></span>
1010 </button>
1111 <p>No hosts found yet.</p>
1212 </div>
13 <table id="hosts" ng-if="hosts.length > 0" class="tablesorter table table-striped">
13 <table id="hosts" ng-if="hosts.length > 0" class="tablesorter table table-striped table-fixed">
1414 <thead>
1515 <tr>
16 <th><a href="" ng-click="hostToggleSort('name')">Host</a></th>
17 <th><a href="" ng-click="hostToggleSort('servicesCount')">Services</a></th>
18 <th><a href="" ng-click="hostToggleSort('os')">OS</a></th>
16 <th class="col-xs-6"><a href="" ng-click="hostToggleSort('name')">Host</a></th>
17 <th class="col-xs-4"><a href="" ng-click="hostToggleSort('servicesCount')">Services</a></th>
18 <th class="col-xs-2"><a href="" ng-click="hostToggleSort('os')">OS</a></th>
1919 </tr>
2020 </thead>
2121 <tbody>
2222 <tr ng-repeat="host in hosts | orderBy:hostSortField:hostSortReverse |
2323 startFrom:currentPage*pageSize | limitTo:pageSize">
24 <td><a href="" class="host" ng-click="showServices(host.id)">{{host.name}}</a></td>
25 <td>{{host.servicesCount}}</td>
26 <td>
24 <td class="col-xs-6">
25 <a href="" class="host" ng-click="showServices(host)">{{host.name}}</a>
26 <a href="//www.shodan.io/search?query={{host.name}}" tooltip="Search in Shodan" target="_blank">
27 <img ng-src="../././reports/images/shodan.png" height="15px" width="15px" />
28 </a>
29 </td>
30 <td class="col-xs-6">{{host.servicesCount}}</td>
31 <td class="col-xs-4">
2732 <img ng-if="host.icon != undefined" ng-src="../././reports/images/{{host.icon}}.png" tooltip="{{host.os}}"/>
28 <span ng-if="host.icon == undefined" class="glyphicon glyphicon-question-sign" tooltip="{{host.os}}"></span>
33 <span ng-if="host.icon == undefined" class="fa fa-laptop" tooltip="{{host.os}}"></span>
2934 </td>
3035 </tr>
3136 </tbody>
4449 </form>
4550 </div>
4651 </div>
47 </article>
52 </article>
55 <div class="right-main">
66 <div id="reports-main" class="fila clearfix">
77 <h2 class="ws-label">
8 <span id="ws-name" class="label label-default"
9 title="Current workspace">Dashboard for {{ workspace }}</span><!-- WS name -->
8 <span id="ws-name" title="Current workspace">Dashboard for {{ workspace }}</span><!-- WS name -->
109 <div id="ws-control" class="btn-group">
1110 <button id="refresh" type="button" class="btn btn-danger" title="Refresh current workspace" ng-click="location.reload()">
1211 <span class="glyphicon glyphicon-refresh"></span>
2424 <tbody>
2525 <tr ng-repeat="vuln in vulns | orderObjectBy:vulnSortField:vulnSortReverse | limitTo:5">
2626 <td>{{vuln.metadata.create_time * 1000 | date:"MM/dd/yyyy 'at' h:mma"}}</td>
27 <td>{{vuln.target}}</td>
27 <td>
28 {{vuln.target}}
29 <a href="//www.shodan.io/search?query={{vuln.target}}" tooltip="Search in Shodan" target="_blank">
30 <img ng-src="../././reports/images/shodan.png" height="15px" width="15px" />
31 </a>
32 </td>
2833 <td>{{vuln.severity}}</td>
2934 <td class="wrapword">{{vuln.name}}</td>
3035 <td>
1717 <tbody>
1818 <tr ng-repeat="host in hosts | orderBy:sortField:sortReverse">
1919 <td><input disabled type="checkbox" ng-model="host.owned"/></td>
20 <td>{{host.name}}</td>
20 <td>
21 {{host.name}}
22 <a href="//www.shodan.io/search?query={{host.name}}" tooltip="Search in Shodan" target="_blank">
23 <img ng-src="../././reports/images/shodan.png" height="15px" width="15px" />
24 </a>
25 </td>
2126 <td>{{host.os}}</td>
2227 </tr>
2328 </tbody>
2934
3035 <div class="modal-footer">
3136 <button class="btn btn-success" ng-click="ok()">OK</button>
32 </div>
37 </div>
1818 </thead>
1919 <tbody>
2020 <tr ng-repeat="srv in services | orderBy:sortField:sortReverse">
21 <td>{{srv.name}}</a></td>
21 <td>
22 {{srv.name}}
23 <a href="//www.shodan.io/search?query={{srv.name}}" tooltip="Search in Shodan" target="_blank">
24 <img ng-src="../././reports/images/shodan.png" height="15px" width="15px" />
25 </a>
26 </td>
2227 <td>{{srv.description}}</td>
23 <td>{{srv.port}}</td>
28 <td>
29 <li ng-repeat="p in srv.ports">
30 {{p}}
31 <a href="//www.shodan.io/search?query=port:{{p}}" tooltip="Search in Shodan" target="_blank">
32 <img ng-src="../././reports/images/shodan.png" height="15px" width="15px" />
33 </a>
34 </li>
35 </td>
2436 <td>{{srv.protocol}}</td>
2537 <td>{{srv.status}}</td>
2638 </tr>
2739 </tbody>
40 <div class="col md-12" style="border-top:1px solid #e5e5e5">
41 <h5><span class="fa fa-laptop"></span> Operating System: <b>{{host.os}}</b></h5>
42 <h6><span class="glyphicon glyphicon-user"></span> Created on the <b>{{host.metadata.create_time * 1000 | date:'MM/dd/yyyy'}} </b></h6>
43 </div><!-- .col md-12 -->
2844 </table>
2945 </div>
3046
3147 <div class="modal-footer">
3248 <button class="btn btn-success" ng-click="ok()">OK</button>
33 </div>
49 </div>
5252 <div class='box'>
5353 <div ng-repeat="obj in objectsCount" class="columna unquinto">
5454 <article class="dato2">
55 <section>
56 <div class="nro">{{obj.value}}</div>
55 <div ng-switch on="obj.key">
56 <div class="nro" ng-switch-when="total vulns"><a href="#/status/ws/{{workspace}}">{{obj.value}}</a></div>
57 <div class="nro" ng-switch-when="hosts"><a href="#/hosts/ws/{{workspace}}">{{obj.value}}</a></div>
58 <div class="nro" ng-switch-when="web vulns"><a href="#/status/ws/{{workspace}}/search/type=VulnerabilityWeb">{{obj.value}}</a></div>
59 <div class="nro" ng-switch-when="vulns"><a href="#/status/ws/{{workspace}}/search/type=!VulnerabilityWeb">{{obj.value}}</a></div>
60 <!--#/status/ws/cscan/search/severity=high -->
61 <div class="nro" ng-switch-default>{{obj.value}}</div>
62 </div>
5763 <div class="txt texto-blanco">{{obj.key}}</div>
5864 </section>
5965 </article>
1212 <p>No vulnerabilities found yet.</p>
1313 </div>
1414 <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>
15 <div class="center-lg-6"><h4><i class="fa fa-money"></i> {{workspaceWorth | currency}} total</h4></div>
1616 <div d3-horizontal-stacked-bar data="vulnsCount" class="stackedbars"></div>
1717 <div id="vulns-by-price-reference" class="center-lg-6">
1818 <ul class="label-list">
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>
19 <li ng-repeat="(severity, price) in vulnPrices" tooltip="Click on number to edit price">
20 <span class="label vuln fondo-{{severity}}">
21 {{severity}} $
22 <span contenteditable="true" ng-model="vulnPrices[severity]"></span>
23 </span>
24 </li>
2025 </ul>
2126 </div><!-- #vulns-by-price-reference .center-lg-6 -->
2227 </div>
1313 </div>
1414 <div class='main box'>
1515 <div ng-repeat="vuln in vulnsCount" class="columna unsexto cursor">
16 <article class="dato2 fondo-{{vuln.key}}" ng-click="navigate('/status/ws/'+workspace+'/search/severity='+vuln.key)">
16 <article class="dato2 background-{{vuln.key}}" ng-click="navigate('/status/ws/'+workspace+'/search/severity='+vuln.key)">
1717 <section>
18 <div class="nro texto-blanco">{{vuln.value}}</div>
19 <div class="txt texto-blanco">{{vuln.key}}</div>
18 <div class="nro text-{{vuln.key}}">{{vuln.value}}</div>
19 <div class="txt text-{{vuln.key}}">{{vuln.key}}</div>
2020 </section>
2121 </article>
2222 </div>
55 .controller('hostCtrl',
66 ['$scope', '$filter', '$route', '$routeParams', '$modal', 'hostsManager', 'workspacesFact', 'dashboardSrv', 'servicesManager',
77 function($scope, $filter, $route, $routeParams, $modal, hostsManager, workspacesFact, dashboardSrv, servicesManager) {
8
98
109 init = function() {
1110 $scope.selectall = false;
2322 });
2423 // services by host
2524 $scope.services = [];
26 dashboardSrv.getServicesByHost($scope.workspace, hostId).then(function(services){
27 services.forEach(function(service){
28 servicesManager.getService(service.id, $scope.workspace, true).then(function(s){
29 $scope.services.push(s);
25 dashboardSrv.getServicesByHost($scope.workspace, hostId)
26 .then(function(services) {
27 services.forEach(function(service) {
28 servicesManager.getService(service.id, $scope.workspace, true)
29 .then(function(s) {
30 $scope.services.push(s);
31 });
3032 });
3133 });
32 });
34
35 hostsManager.getAllVulnsCount($scope.workspace)
36 .then(function(vulns) {
37 $scope.vulnsCount = {};
38 vulns.forEach(function(vuln) {
39 $scope.vulnsCount[vuln.key] = vuln.value;
40 });
41 })
42 .catch(function(e) {
43 console.log(e);
44 });
3345 };
3446
3547 $scope.new = function() {
112124 size: 'sm',
113125 resolve: {
114126 msg: function() {
115 return 'No hosts were selected to edit';
127 return 'No services were selected to edit';
116128 }
117129 }
118130 });
33
44 angular.module('faradayApp')
55 .controller('hostsCtrl',
6 ['$scope', '$filter', '$route', '$routeParams', '$modal', 'hostsManager', 'workspacesFact',
7 function($scope, $filter, $route, $routeParams, $modal, hostsManager, workspacesFact) {
6 ['$scope', '$filter', '$route', '$routeParams', '$modal', 'hostsManager', 'workspacesFact',
7 function($scope, $filter, $route, $routeParams, $modal, hostsManager, workspacesFact) {
88
99 init = function() {
1010 $scope.selectall = false;
1717 $scope.workspaces = wss;
1818 });
1919
20 hostsManager.getHosts($scope.workspace).then(function(hosts) {
21 $scope.hosts = hosts;
22 $scope.loadIcons();
23 });
20 hostsManager.getHosts($scope.workspace)
21 .then(function(hosts) {
22 $scope.hosts = hosts;
23 $scope.loadIcons();
24 });
25
26 hostsManager.getAllVulnsCount($scope.workspace)
27 .then(function(vulns) {
28 $scope.vulnsCount = {};
29 vulns.forEach(function(vuln) {
30 var parts = vuln.key.split("."),
31 parent = parts[0];
32
33 if(parts.length > 1) $scope.vulnsCount[vuln.key] = vuln.value;
34 if($scope.vulnsCount[parent] == undefined) $scope.vulnsCount[parent] = 0;
35 $scope.vulnsCount[parent] += vuln.value;
36 });
37 })
38 .catch(function(e) {
39 console.log(e);
40 });
2441 };
2542
2643 $scope.loadIcons = function() {
6178
6279 $scope.delete = function() {
6380 var selected = [];
64
65 for(var i=0; i < $scope.hosts.length; i++) {
66 var host = $scope.hosts[i];
67 if(host.selected) {
68 selected.push(host._id);
69 }
70 };
81 $scope.selectedHosts().forEach(function(select) {
82 selected.push(select._id);
83 });
7184
7285 if(selected.length == 0) {
7386 $modal.open(config = {
148161 }
149162
150163 $scope.edit = function() {
151 var selected_host = null;
152
153 $scope.hosts.forEach(function(host) {
154 if(host.selected) {
155 // if more than one host was selected,
156 // we only use the last one, for now
157 selected_host = host;
158 }
159 });
160
161 if(selected_host) {
164
165 if($scope.selectedHosts().length == 1) {
162166 var modal = $modal.open({
163167 templateUrl: 'scripts/hosts/partials/modalEdit.html',
164168 controller: 'hostsModalEdit',
165169 size: 'lg',
166170 resolve: {
167171 host: function(){
168 return selected_host;
172 return $scope.selectedHosts()[0];
169173 }
170174 }
171175 });
173177 modal.result.then(function(data) {
174178 hostdata = data[0];
175179 interfaceData = data[1];
176 $scope.update(selected_host, hostdata, interfaceData);
180 $scope.update($scope.selectedHosts()[0], hostdata, interfaceData);
177181 });
178182 } else {
179183 $modal.open(config = {
234238 return interfaceData;
235239 };
236240
241 $scope.selectedHosts = function() {
242 selected = [];
243 $scope.hosts.forEach(function(host) {
244 if(host.selected === true) {
245 selected.push(host);
246 }
247 });
248 return selected;
249 };
250
237251 $scope.checkAll = function() {
238252 $scope.selectall = !$scope.selectall;
239253
55
66 <div class="right-main"><div id="reports-main" class="fila clearfix">
77 <h2 class="ws-label">
8 <span id="ws-name" class="label label-default"
9 title="Hosts">Hosts for {{workspace}} ({{hosts.length}})</span><!-- WS name -->
8 <span id="ws-name" title="Hosts">Hosts for {{workspace}} ({{hosts.length}})</span><!-- WS name -->
109 <div id="ws-control" class="btn-group">
1110 <button id="refresh" type="button" class="btn btn-danger" title="Refresh current workspace" ng-click="location.reload()">
1211 <span class="glyphicon glyphicon-refresh"></span>
2221 <span class="glyphicon glyphicon-trash"></span>
2322 Delete
2423 </button>
25 <button id="merge" type="button" class="btn btn-default" title="Edit selected hosts" ng-click="edit()">
24 <button id="merge" type="button" class="btn btn-default" title="Edit selected hosts" ng-disabled="selectedHosts().length > 1" ng-click="edit()">
2625 <span class="glyphicon glyphicon-pencil"></span>
2726 Edit
2827 </button>
4645 <a href="" ng-click="toggleSort('description')">Description</a>
4746 </th>
4847 <th>
48 <a href="" ng-click="toggleSort('vulns')">Vulns</a>
49 </th>
50 <th>
4951 <a href="" ng-click="toggleSort('os')">OS</a>
5052 </th>
5153 <th>
5759 <tr ng-repeat="host in hosts | filter:query | orderBy:sortField:reverse"
5860 selection-model selection-model-type="checkbox"
5961 selection-model-mode="multiple-additive"
60 selection-model-selected-class="multi-selected">
62 selection-model-selected-class="multi-selected"
63 selection-model-on-change="selectedHosts()">
6164 <td><input type="checkbox" name="{{host._id}}"/></td>
6265 <td><a href="#/host/ws/{{workspace}}/hid/{{host._id}}">View</a></td>
63 <td ng-bind="host.name"></td>
66 <td>
67 {{host.name}}
68 <a href="//www.shodan.io/search?query={{host.name}}" tooltip="Search in Shodan" target="_blank">
69 <img ng-src="../././reports/images/shodan.png" height="15px" width="15px" />
70 </a>
71 </td>
6472 <td ng-bind="host.description || '-'"></td>
73 <td> <a ng-href="#/status/ws/{{workspace}}/search/target={{host.name}}" ng-bind="vulnsCount[host._id] || '-'"></a></td>
6574 <td>
6675 <img ng-if="host.icon != undefined" ng-src="../././reports/images/{{host.icon}}.png" tooltip="{{host.os}}"/>
67 <span ng-if="host.icon == undefined" class="glyphicon glyphicon-question-sign" tooltip="{{host.os}}"></span>
76 <span ng-if="host.icon == undefined" class="fa fa-laptop" tooltip="{{host.os}}"></span>
6877 </td>
6978 <td ng-bind="host.owned"></td>
7079 </tr>
1111 </div>
1212 <div class="modal-body">
1313 <div class="form-horizontal">
14 <div class="form-group">
14 <div class="form-group" ng-class="{'has-error': form.name.$invalid }">
1515 <div class="col-md-12">
1616 <label class="sr-only" for="name">Name</label>
17 <input type="text" class="form-control" id="name" placeholder="Name" ng-model="host.name" required/>
17 <input type="text" class="form-control" id="name" name="name" placeholder="Name" ng-model="host.name" required/>
1818 <span class="help-block normal-size">
1919 Example: 192.168.0.1
2020 </span>
1111 </div>
1212 <div class="modal-body">
1313 <div class="form-horizontal">
14 <div class="form-group">
14 <div class="form-group" ng-class="{'has-error': form.name.$invalid }">
1515 <div class="col-md-12">
1616 <label class="sr-only" for="name">Name</label>
17 <input type="text" class="form-control" id="name" placeholder="Name" ng-model="hostdata.name" required/>
17 <input type="text" class="form-control" id="name" name="name" placeholder="Name" ng-model="hostdata.name" required/>
1818 <span class="help-block normal-size">
1919 Example: 192.168.0.1
2020 </span>
5959 </div>
6060 </div><!-- .form-group -->
6161 <div class="form-group">
62 <div class="col-md-6">
62 <div class="col-md-6" ng-class="{'has-error': form.ipv6.$invalid }">
6363 <label class="sr-only" for="ipv4">IP v4</label>
64 <input type="text" class="form-control" id="ipv4" placeholder="IP v4" ng-model="interfaceData.ipv4" ng-required="!interfaceData.ipv6"/>
64 <input type="text" class="form-control" id="ipv4" name="ipv6" placeholder="IP v4" ng-model="interfaceData.ipv4" ng-required="!interfaceData.ipv6"/>
6565 </div>
66 <div class="col-md-6">
66 <div class="col-md-6" ng-class="{'has-error': form.ipv4.$invalid }">
6767 <label class="sr-only" for="ipv6">IP v6</label>
68 <input type="text" class="form-control" id="ipv6" placeholder="IP v6" ng-model="interfaceData.ipv6" ng-required="!interfaceData.ipv4"/>
68 <input type="text" class="form-control" id="ipv6" name="ipv4" placeholder="IP v6" ng-model="interfaceData.ipv6" ng-required="!interfaceData.ipv4"/>
6969 </div>
7070 </div><!-- .form-group -->
7171 <div class="form-group">
169169 return deferred.promise;
170170 };
171171
172 hostsManager.getAllVulnsCount = function(ws) {
173 var deferred = $q.defer();
174
175 var url = BASEURL + ws + '/_design/vulns/_view/byhost?group=true';
176
177 $http.get(url)
178 .success(function(vulns) {
179 deferred.resolve(vulns.rows);
180 })
181 .error(function() {
182 deferred.reject("Unable to load Vulnerabilities");
183 });
184
185 return deferred.promise;
186 };
187
172188 hostsManager.getInterfaces = function(ws, id) {
173189 var deferred = $q.defer(),
174190 self = this;
6464
6565 $scope.loadCurrentWorkspace();
6666
67 if(navigator.userAgent.toLowerCase().indexOf('iceweasel') > -1) {
68 $scope.isIceweasel = "Your browser is not supported, please use Firefox or Chrome";
69 }
67 // if(navigator.userAgent.toLowerCase().indexOf('iceweasel') > -1) {
68 // $scope.isIceweasel = "Your browser is not supported, please use Firefox or Chrome";
69 // }
7070
7171 }]);
2020 </li>
2121 <li>
2222 <a href="#/hosts/ws/{{workspace}}" class="workspaces" style="color: #ffffff !important" tooltip="Hosts" tooltip-placement="right">
23 <i class="fa fa-sitemap fa-5x"></i>
23 <i class="fa fa-sitemap host"></i>
2424 </a>
2525 </li>
2626 </ul>
3636 var date = new Date(),
3737 timestamp = date.getTime()/1000.0;
3838
39 $scope.service.ports.forEach(function(port){
40 ports.push(port.key);
41 });
39 if($scope.service.ports.length !== 0) {
40 $scope.service.ports.forEach(function(port){
41 ports.push(port.key);
42 });
43 $scope.service.ports = ports.filter(Boolean);
44 } else {
45 delete $scope.service.ports;
46 }
4247
43 $scope.service.ports = ports.filter(Boolean);
4448 $modalInstance.close($scope.service);
4549 };
4650
55
66 <div class="right-main"><div id="reports-main" class="fila clearfix">
77 <h2 class="ws-label">
8 <span id="ws-name" class="label label-default"
9 title="Hosts">Services from {{host.name}}</span><!-- WS name -->
8 <span id="ws-name" title="Hosts">Services from {{host.name}}</span><!-- WS name -->
109 <div id="ws-control" class="btn-group">
1110 <button id="refresh" type="button" class="btn btn-danger" title="Refresh current workspace" ng-click="location.reload()">
1211 <span class="glyphicon glyphicon-refresh"></span>
7473 <th>
7574 <a href="" ng-click="toggleSort('status')">Status</a>
7675 </th>
76 <th>
77 <a href="" ng-click="toggleSort('vulns')">Vulns</a>
78 </th>
7779 </tr>
7880 </thead>
7981 <tbody>
8284 selection-model-mode="multiple-additive"
8385 selection-model-selected-class="multi-selected">
8486 <td><input type="checkbox" name="{{s._id}}"/></td>
85 <td ng-bind="service.name"></td>
87 <td>
88 {{service.name}}
89 <a href="//www.shodan.io/search?query={{service.name}}" tooltip="Search in Shodan" target="_blank">
90 <img ng-src="../././reports/images/shodan.png" height="15px" width="15px" />
91 </a>
92 </td>
8693 <td ng-bind="service.description || '-'"></td>
87 <td ng-bind="service.ports"></td>
94 <td>
95 <li ng-repeat="p in service.ports">
96 {{p}}
97 <a href="//www.shodan.io/search?query=port:{{p}}" tooltip="Search in Shodan" target="_blank">
98 <img ng-src="../././reports/images/shodan.png" height="15px" width="15px" />
99 </a>
100 </li>
101 </td>
88102 <td ng-bind="service.protocol"></td>
89103 <td ng-bind="service.status"></td>
104 <td ng-bind="vulnsCount[service._id] || '-'"></td>
90105 </tr>
91106 </tbody>
92107 </table><!-- #hosts -->
1111 </div>
1212 <div class="modal-body">
1313 <div class="form-horizontal">
14 <div class="form-group">
14 <div class="form-group" ng-class="{'has-error': form.name.$invalid }">
1515 <div class="col-md-12">
1616 <label class="sr-only" for="name">Name</label>
17 <input type="text" class="form-control" id="name" placeholder="Name" ng-model="service.name" required/>
17 <input type="text" class="form-control" id="name" name="name" placeholder="Name" ng-model="service.name" />
1818 </div>
1919 </div><!-- .form-group -->
2020 <div class="form-group">
1111 </div>
1212 <div class="modal-body">
1313 <div class="form-horizontal">
14 <div class="form-group">
14 <div class="form-group" ng-class="{'has-error': form.name.$invalid }">
1515 <div class="col-md-12">
1616 <label class="sr-only" for="service">Name</label>
17 <input type="text" class="form-control" id="service" placeholder="Name" ng-model="service.name" required/>
17 <input type="text" class="form-control" id="service" name="name" placeholder="Name" ng-model="service.name" required/>
1818 </div>
1919 </div><!-- .form-group -->
2020 <div class="form-group">
3737 <div class="col-md-3">
3838 <h5>Ports</h5>
3939 <span class="input-group-addon button-radius" ng-click="newPort($event)">Add Port</span>
40 <div class="input-margin" ng-repeat="port in service.ports">
40 <div class="input-margin" ng-repeat="port in service.ports" ng-class="{'has-error': form.port.$invalid }">
4141 <div class="input-group margin-bottom-sm">
4242 <label class="sr-only" for="port">Ports</label>
43 <input type="number" class="form-control" id="port" placeholder="Port" ng-model="port.key" required/>
43 <input type="number" class="form-control" id="port" name="port" placeholder="Port" ng-model="port.key" required/>
4444 <span class="input-group-addon" ng-click="service.ports.splice($index, 1)" ng-hide="service.ports.length == 1"><i class="fa fa-minus-circle"></i></span>
4545 </div>
4646 </div>
4747 </div>
48 <div class="col-md-3 protocol">
48 <div class="col-md-3 protocol" ng-class="{'has-error': form.protocol.$invalid }">
4949 <h5>Protocol</h5>
5050 <label class="sr-only" for="protocol">Protocol</label>
51 <input type="text" class="form-control" id="protocol" placeholder="Protocol" ng-model="service.protocol" required/>
51 <input type="text" class="form-control" id="protocol" name="protocol" placeholder="Protocol" ng-model="service.protocol" required/>
5252 </div>
5353 <div class="col-md-3">
5454 <h5>Version</h5>
479479 }
480480 }
481481 }
482 return encodeURI(encode.slice(1));
482 return encode.slice(1);
483483 };
484484
485485 // decodes search parameters to object in order to use in filter
486486 $scope.decodeSearch = function(search) {
487487 var i = -1,
488488 decode = {},
489 params = decodeURI(search).split("&");
489 params = search.split("&");
490490
491491 params.forEach(function(param) {
492492 i = param.indexOf("=");
44 <form name="formEdit" novalidate>
55 <div class="modal-header">
66 <div class="modal-button">
7 <button class="btn btn-success" ng-click="modal.ok()" ng-disabled="formEdit.$invalid">OK</button>
7 <button class="btn btn-success" ng-click="modal.ok()" ng-disabled="formEdit.$invalid || modal.data.severity === undefined">OK</button>
88 <button class="btn btn-danger" ng-click="modal.cancel()">Cancel</button>
99 </div>
1010 <h3 class="modal-title">Vuln edit</h3>
2323 </div>
2424 </div>
2525 <div class="form-group">
26 <div class="col-md-6">
26 <div class="col-md-6 severities">
2727 <h5>Severity</h5>
28 <select class="form-control" ng-model="modal.data.severity" ng-options="s as s for s in modal.severities" required>
29 </select>
28 <button type="button" class="btn btn-default dropdown-toggle color-{{modal.data.severity}}" name="severity" data-toggle="dropdown" title="Change severity" ng-class="{'button-error': modal.data.severity === undefined}">
29 {{modal.data.severity || 'Edit severity'}} <span class="caret" style="color:#000"></span>
30 </button>
31 <ul id="nav" class="dropdown-menu dropdown-menu-left" role="menu">
32 <li ng-repeat="s in modal.severities"><a href="" class="ws color-{{s}}" ng-click="modal.data.severity=s">{{s}}</a></li>
33 </ul><!-- WS navigation -->
3034 </div>
3135 <div class="col-md-6">
3236 <h5>Ease of Resolution</h5>
3539 </select>
3640 </div>
3741 </div><!-- .form-group -->
38 <div class="form-group">
42 <div class="form-group" ng-class="{'has-error': formEdit.name.$invalid }">
3943 <div class="col-md-12">
4044 <label class="sr-only" for="vuln-name">Vuln name</label>
41 <input type="text" class="form-control" id="vuln-name" placeholder="Name" ng-model="modal.data.name" required/>
45 <input type="text" class="form-control" id="vuln-name" name="name" placeholder="Name" ng-model="modal.data.name" required/>
4246 </div>
4347 </div><!-- .form-group -->
44 <div class="form-group">
48 <div class="form-group" ng-class="{'has-error': formEdit.desc.$invalid }">
4549 <div class="col-md-12">
4650 <label class="sr-only" for="vuln-desc">Vuln description</label>
47 <textarea class="form-control" id="vuln-desc" placeholder="Description" ng-model="modal.data.desc" required></textarea>
51 <textarea class="form-control" id="vuln-desc" name="desc" placeholder="Description" ng-model="modal.data.desc" required></textarea>
4852 </div>
4953 </div><!-- .form-group -->
5054 <div class="form-group">
44 <form name="form" novalidate>
55 <div class="modal-header">
66 <div class="modal-button">
7 <button class="btn btn-success" ng-click="modal.ok()" ng-disabled="form.$invalid">OK</button>
7 <button class="btn btn-success" ng-click="modal.ok()" ng-disabled="form.$invalid || modal.data.severity === undefined">OK</button>
88 <button class="btn btn-danger" ng-click="modal.cancel()">Cancel</button>
99 </div>
1010 <h3 class="modal-title">Vulnerability creation</h3>
6868 <select class="form-control" ng-model="modal.data.type" ng-options="option.value as option.name for option in modal.vuln_types">
6969 </select>
7070 </div>
71 <div class="col-md-4">
71 <div class="col-md-4 severities">
7272 <h5>Severity</h5>
73 <select class="form-control" ng-model="modal.data.severity" ng-options="s for s in modal.severities" required>
74 </select>
73 <button type="button" class="btn btn-default dropdown-toggle color-{{modal.data.severity}}" name="severity" data-toggle="dropdown" title="Change severity" ng-class="{'button-error': modal.data.severity === undefined}">
74 {{modal.data.severity || 'Add severity'}} <span class="caret"></span>
75 </button>
76 <ul id="nav" class="dropdown-menu dropdown-menu-left" role="menu">
77 <li ng-repeat="s in modal.severities"><a href="" class="ws color-{{s}}" ng-click="modal.data.severity=s">{{s}}</a></li>
78 </ul><!-- WS navigation -->
7579 </div>
7680 <div class="col-md-4">
7781 <h5>Ease of Resolution</h5>
8084 </select>
8185 </div>
8286 </div><!-- .form-group -->
83 <div class="form-group">
87 <div class="form-group" ng-class="{'has-error': form.name.$invalid }">
8488 <div class="col-md-12">
8589 <label class="sr-only" for="vuln-name">Vuln name</label>
86 <input type="text" class="form-control" id="vuln-name" placeholder="Name" ng-model="modal.data.name" required/>
87 </div>
88 </div><!-- .form-group -->
89 <div class="form-group">
90 <input type="text" class="form-control" id="vuln-name" name="name" placeholder="Name" ng-model="modal.data.name" required/>
91 </div>
92 </div><!-- .form-group -->
93 <div class="form-group" ng-class="{'has-error': form.desc.$invalid }">
9094 <div class="col-md-12">
9195 <label class="sr-only" for="vuln-desc">Vuln description</label>
92 <textarea class="form-control" id="vuln-desc" placeholder="Description" ng-model="modal.data.desc" required></textarea>
96 <textarea class="form-control" id="vuln-desc" name="desc" placeholder="Description" ng-model="modal.data.desc" required></textarea>
9397 </div>
9498 </div><!-- .form-group -->
9599 <div class="form-group">
55 <div class="right-main">
66 <div id="reports-main" class="fila clearfix">
77 <div class="ws-label">
8 <h2><span id="ws-name" class="label label-default"
9 title="Current workspace">Status report for {{ workspace }} ({{vulns.length}} vulns)</span></h2><!-- WS name -->
8 <h2><span id="ws-name" title="Current workspace">Status report for {{ workspace }} ({{vulns.length}} vulns)</span></h2><!-- WS name -->
109 </div><!-- .ws-label -->
1110 <div id="ws-control" class="btn-group btn-small-margin">
1211 <button file-exporter="csv()" type="button" class="btn btn-success" title="Download CSV for current workspace">
199198 <td class="text-center"><span ng-click="editVuln(v)" class="glyphicon glyphicon-pencil cursor" tooltip="Edit"></span></td>
200199 <td class="text-center"><span ng-click="deleteVuln(v)" class="glyphicon glyphicon-trash cursor" tooltip="Delete"></span></td>
201200 <td ng-if="columns.date">{{v.metadata.create_time * 1000 | date:'MM/dd/yyyy'}}</td>
202 <td ng-if="columns.target">{{v.target}}</td>
201 <td ng-if="columns.target">
202 <a href="#/status/ws/{{workspace}}/search/target={{v.target}}">{{v.target}}</a>
203 <a href="//www.shodan.io/search?query={{v.target}}" tooltip="Search in Shodan" target="_blank">
204 <img ng-src="../././reports/images/shodan.png" height="15px" width="15px" />
205 </a>
206 </td>
203207 <td ng-if="columns.status">Vulnerable</td>
204 <td ng-if="columns.severity"><span class="label vuln fondo-{{v.severity}}">{{v.severity}}</span></td>
205 <td ng-if="columns.name">{{v.name}}</td>
208 <td ng-if="columns.severity"><a href="#/status/ws/{{workspace}}/search/severity={{v.severity}}"><span class="label vuln fondo-{{v.severity}}">{{v.severity}}</span></a></td>
209 <td ng-if="columns.name"><a href="#/status/ws/{{workspace}}/search/name={{v.name | encodeURIComponent | encodeURIComponent}}">{{v.name}}</a></td>
206210 <td ng-if="columns.desc" text-collapse text-collapse-max-length="150" text-collapse-text="{{v.desc}}"></td>
207211 <td ng-if="columns.data" text-collapse text-collapse-max-length="150" text-collapse-text="{{v.data}}"></td>
208 <td ng-if="columns.method">{{v.method}}</td>
209 <td ng-if="columns.path">{{v.path}}</td>
210 <td ng-if="columns.pname">{{v.pname}}</td>
212 <td ng-if="columns.method"><a href="#/status/ws/{{workspace}}/search/method={{v.method}}">{{v.method}}</a></td>
213 <td ng-if="columns.path"><a href="#/status/ws/{{workspace}}/search/path={{v.path}}">{{v.path}}</a></td>
214 <td ng-if="columns.pname"><a href="#/status/ws/{{workspace}}/search/pname={{v.pname}}">{{v.pname}}</a></td>
211215 <td ng-if="columns.params">{{v.params}}</td>
212 <td ng-if="columns.query">{{v.query}}</td>
216 <td ng-if="columns.query"><a href="#/status/ws/{{workspace}}/search/query={{v.query}}">{{v.query}}</a></td>
213217 <td ng-if="columns.request" text-collapse text-collapse-max-length="100" text-collapse-text="{{v.request}}"></td>
214218 <td ng-if="columns.response" text-collapse text-collapse-max-length="100" text-collapse-text="{{v.response}}"></td>
215219 <td ng-if="columns.resolution">{{v.resolution}}</td>
217221 <span class="glyphicon glyphicon-ok" ng-show="v.type === 'VulnerabilityWeb'"></span>
218222 <span class="glyphicon glyphicon-remove" ng-show="v.type !== 'VulnerabilityWeb'"></span>
219223 </td>
220 <td ng-if="columns.website">{{v.website}}</td>
224 <td ng-if="columns.website"><a href="#/status/ws/{{workspace}}/search/website={{v.website}}">{{v.website}}</a></td>
221225 <td ng-if="columns.refs"><p ng-repeat="refs in v.refs track by $index">{{refs}}</p></td>
222226 <td ng-if="columns.evidence">
223227 <div ng-repeat="(name, file) in v._attachments track by $index">
229233 <p ng-if="rating">{{impact}}</p>
230234 </div>
231235 </td>
232 <td ng-if="columns.easeofresolution">{{v.easeofresolution}}</td>
233 <td ng-if="columns.hostnames"><p ng-repeat="hostname in v.hostnames track by $index">{{hostname}}</p></td>
236 <td ng-if="columns.easeofresolution"><a href="#/status/ws/{{workspace}}/search/easeofresolution={{v.easeofresolution}}">{{v.easeofresolution}}</a></td>
237 <td ng-if="columns.hostnames">
238 <p ng-repeat="hostname in v.hostnames track by $index">
239 <a href="#/status/ws/{{workspace}}/search/hostnames={{hostname}}">{{hostname}}</a>
240 <a href="//www.shodan.io/search?query={{hostname}}" tooltip="Search in Shodan" target="_blank">
241 <img ng-src="../././reports/images/shodan.png" height="15px" width="15px" />
242 </a>
243 </p>
244 </td>
234245 </tr>
235246 </tbody>
236247 </table><!-- #hosts -->
55 <section id="main" class="seccion clearfix">
66 <div class="right-main"><div id="reports-main" class="fila clearfix">
77 <h2 class="ws-label">
8 <span id="ws-name" class="label label-default"
9 title="Workspaces">Workspaces</span><!-- WS name -->
8 <span id="ws-name" title="Workspaces">Workspaces</span><!-- WS name -->
109 <button id="delete" type="button" class="btn btn-default" title="Delete selected Workspaces" ng-click="delete()">
1110 <span class="glyphicon glyphicon-trash"></span>
1211 Delete
3534 <tbody>
3635 <tr ng-repeat="ws in workspaces | filter:query | orderBy:sortField:reverse"
3736 selection-model selection-model-selected-class="multi-selected">
38 <td><span ng-class-even="'label label-unclassified'" ng-class-odd="'label label-high'">{{ws.name}}</span></td>
37 <td><a href="#/{{hash}}dashboard/ws/{{ws.name}}"><span ng-class-even="'label label-unclassified'" ng-class-odd="'label label-high'">{{ws.name}}</span></td>
3938 <td ng-bind="ws.duration.start || '-' | date:'MM/dd/yyyy'"></td>
4039 <td ng-bind="ws.duration.end || '-' | date:'MM/dd/yyyy'"></td>
41 <td ng-bind="objects[ws.name]['total vulns']"></td>
42 <td ng-bind="objects[ws.name]['hosts']"></td>
40 <td><a href="#/status/ws/{{ws.name}}">{{objects[ws.name]['total vulns']}}</a></td>
41 <td><a href="#/hosts/ws/{{ws.name}}">{{objects[ws.name]['hosts']}}</a></td>
4342 <td ng-bind="objects[ws.name]['services']"></td>
4443 </tr>
4544 </tbody>
1616 <label class="sr-only" for="vuln-desc">Workspace Description</label>
1717 <textarea class="form-control" id="vuln-desc"
1818 placeholder="Description" value={{workspace.description}}
19 ng-model="workspace.description" required></textarea>
19 ng-model="workspace.description"></textarea>
2020 </div>
2121 </div><!-- .form-group -->
2222 <div class="form-group">
1111 </div>
1212 <div class="modal-body">
1313 <div class="form-horizontal">
14 <div class="form-group">
14 <div class="form-group" ng-class="{'has-error': form.name.$invalid }">
1515 <div class="col-md-12">
1616 <ng-form name="form" novalidate>
1717 <label class="sr-only" for="wsp-name">Workspace Name</label>
1818 <input type="text" class="form-control"
19 ng-pattern=/^[a-z][a-z0-9\_\$\(\)\+\-\/]*$/ id="vuln-name" placeholder="Workspace Name"
19 ng-pattern=/^[a-z][a-z0-9\_\$\(\)\+\-\/]*$/ id="vuln-name" name="name" placeholder="Workspace Name"
2020 ng-model="workspace.name" required/>
2121 <div ng-if="form.$invalid">
2222 <div class="alert alert-danger target_not_selected" role="alert" ng-hide="">
22 // See the file 'doc/LICENSE' for the license information
33 function(doc) {
44 if(doc.type == "Vulnerability" || doc.type == "VulnerabilityWeb"){
5 var easeofresolution = "trivial",
5 var easeofresolution = "",
66 impact = {
77 "accountability": false,
88 "availability": false,
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 function(doc) {
4 if(doc.type == "Vulnerability" || doc.type == "VulnerabilityWeb"){
5 emit(doc.parent, 1);
6 }
7 }
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 function (key, values) {
6
7 return values.reduce(function(previousValue, currentValue, index, array){
8 return previousValue + currentValue;
9 });
10
11 }
22 // See the file 'doc/LICENSE' for the license information
33 function(doc) {
44 if(doc.type == "Vulnerability"){
5 var easeofresolution = "trivial",
5 var easeofresolution = "",
66 impact = {
77 "accountability": false,
88 "availability": false,
22 // See the file 'doc/LICENSE' for the license information
33 function(doc) {
44 if(doc.type == "VulnerabilityWeb"){
5 var easeofresolution = "trivial",
5 var easeofresolution = "",
66 impact = {
77 "accountability": false,
88 "availability": false,