Codebase list python-faraday / 32e374f
New upstream version 2.6.1 Sophie Brun 6 years ago
52 changed file(s) with 1023 addition(s) and 434 deletion(s). Raw diff Collapse all Expand all
88 * Franco Linares
99 * German Riera
1010 * Joaquín López Pereyra
11 * Leonardo Lazzaro
1112 * Martín Rocha
1213 * Matias Ariel Ré Medina
14 * Matias Lang
1315 * Micaela Ranea Sánchez
16 * Sebastian Kulesz
1417
1518 Project contributors
1619
1922 * Andres Tarantini
2023 * Brice Samulenok
2124 * Elian Gidoni
25 * Endrigo Antonini
2226 * Federico Fernandez
2327 * James Jara
28 * Jorge Luis Gonzalez Iznaga
2429 * Juan Urbano
2530 * Korantin Auguste
2631 * Martin Tartarelli
2732 * Ronald Iraheta
2833 * Roberto Focke
29 * Sebastian Kulesz
3034 * Sliim
3135 * Thierry Beauquier
3236 * tsxltjecwb
66
77 New features in the latest update
88 =====================================
9
10 August 7, 2017:
11 ---
12 * Updated Core Impact plugin to be compatible with 2016 version
13 * Improved loading of fields request and website in Burp Plugin
14 * Improved Nexpose Full plugin
15 * Improved Acunetix plugin to avoid conflicts and missing imported data, and to correctly parse URLs and resolutions
16
17 July 19, 2017:
18 ---
19 * Added the ability to select more than one target when creating a vuln in the Web UI
20 * Merged PR #182 - problems with zonatransfer.me
21 * Fixed bug in Download CSV of Status report with old versions of Firefox.
22 * Fixed formula injection vulnerability in export to CSV feature
23 * Fixed DOM-based XSS in the Top Services widget of the dashboard
24 * Fix in AppScan plugin.
25 * Fix HTML injection in Vulnerability template.
26 * Add new plugin: Junit XML
27 * Improved pagination in new vuln modal of status report
28 * Added "Policy Violations" field for Vulnerabilities
929
1030 May 24, 2017:
1131 ---
0 2.5.0
0 2.6.1
11 <faraday>
22
33 <appname>Faraday - Penetration Test IDE</appname>
4 <version>2.5.0</version>
4 <version>2.6.1</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>
11 # Faraday Penetration Test IDE
22 # Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/)
33 # See the file 'doc/LICENSE' for the license information
4 import os
5 import sys
46 import argparse
5 import os
67 import subprocess
7 import sys
88
99 import server.config
1010 import server.couchdb
1212 from server.utils import daemonize
1313 from utils import dependencies
1414 from utils.user_input import query_yes_no
15 from faraday import FARADAY_BASE
1516
1617 logger = server.utils.logger.get_logger(__name__)
1718
8687
8788
8889 def main():
90 os.chdir(FARADAY_BASE)
8991 parser = argparse.ArgumentParser()
9092 parser.add_argument('--ssl', action='store_true', help='enable HTTPS')
9193 parser.add_argument('--debug', action='store_true', help='run Faraday Server in debug mode')
10281028 self.confirmed = vuln.get('confirmed', False)
10291029 self.resolution = vuln.get('resolution')
10301030 self.status = vuln.get('status', "opened")
1031 self.policyviolations = vuln.get('policyviolations', list())
10311032
10321033 def setID(self, parent_id):
10331034 ModelBase.setID(self, parent_id, self.name, self.description)
10991100 return severity
11001101
11011102 def updateAttributes(self, name=None, desc=None, data=None,
1102 severity=None, resolution=None, refs=None, status=None):
1103 severity=None, resolution=None, refs=None, status=None, policyviolations=None):
11031104 if name is not None:
11041105 self.name = name
11051106 if desc is not None:
11141115 self.refs = refs
11151116 if status is not None:
11161117 self.setStatus(status)
1118 if policyviolations is not None:
1119 self.policyviolations = policyviolations
11171120
11181121 def getID(self): return self.id
11191122 def getDesc(self): return self.desc
11231126 def getConfirmed(self): return self.confirmed
11241127 def getResolution(self): return self.resolution
11251128 def getStatus(self): return self.status
1129 def getPolicyViolations(self): return self.policyviolations
11261130
11271131 def setStatus(self, status):
11281132 self.status = status
11541158 self.tags = vuln_web.get('tags')
11551159 self.target = vuln_web.get('target')
11561160 self.parent = vuln_web.get('parent')
1161 self.policyviolations = vuln_web.get('policyviolations', list())
11571162
11581163 def setID(self, parent_id):
11591164 ModelBase.setID(self, parent_id, self.name, self.website, self.path, self.description)
11771182
11781183 def updateAttributes(self, name=None, desc=None, data=None, website=None, path=None, refs=None,
11791184 severity=None, resolution=None, request=None,response=None, method=None,
1180 pname=None, params=None, query=None, category=None, status=None):
1185 pname=None, params=None, query=None, category=None, status=None, policyviolations=None):
11811186
11821187 super(self.__class__, self).updateAttributes(name, desc, data, severity, resolution, refs, status)
11831188
11991204 self.query = query
12001205 if category is not None:
12011206 self.category = category
1207 if policyviolations is not None:
1208 self.policyviolations = policyviolations
12021209
12031210 def getDescription(self): return self.description
12041211 def getPath(self): return self.path
12191226 def getTags(self): return self.tags
12201227 def getTarget(self): return self.target
12211228 def getParent(self): return self.parent
1229 def getPolicyViolations(self): return self.policyviolations
12221230
12231231 def tieBreakable(self, key):
12241232 """
99 from __future__ import with_statement
1010 from plugins import core
1111 from model import api
12 from urlparse import urlsplit
1213 import socket
1314 import sys
1415 import re
124125 self.node = item_node
125126
126127 self.url = self.get_text_from_subnode('StartURL')
127 mregex = re.search(
128 "(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)"
129 "*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]"
130 ")\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0"
131 ")\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0"
132 ")\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|"
133 "localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil"
134 "|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))[\:"
135 "]*([0-9]+)*([/]*($|[a-zA-Z0-9\.\,\?\'\\\+&amp;%\$#\=~_\-]+)).*?$",
136 self.url)
137
138 self.protocol = mregex.group(1)
139 self.host = mregex.group(4)
140 self.port = 80
141 if self.protocol == 'https':
142 self.port = 443
143 if mregex.group(11) is not None:
144 self.port = mregex.group(11)
128 url_data = urlsplit(self.url)
129
130 self.protocol = url_data.scheme
131 self.host = url_data.hostname
132
133 # Use the port in the URL if it is defined, or 80 or 443 by default
134 self.port = url_data.port or (443 if url_data.scheme == "https"
135 else 80)
145136
146137 self.ip = self.resolve(self.host)
147138 self.os = self.get_text_from_subnode('Os')
193184 self.desc = self.get_text_from_subnode('Description')
194185
195186 if self.get_text_from_subnode('Recommendation'):
196 self.desc += "\nSolution: " + self.get_text_from_subnode(
197 'Recommendation')
187 self.resolution = self.get_text_from_subnode('Recommendation')
198188 else:
199 self.desc += ""
189 self.resolution = ""
200190
201191 if self.get_text_from_subnode('reference'):
202192 self.desc += "\nDetails: " + self.get_text_from_subnode('Details')
203193 else:
204194 self.desc += ""
195
196 # Add path and params to the description to create different IDs if at
197 # least one of this fields is different
198 if self.uri:
199 self.desc += '\nPath: ' + self.uri
200 if self.parameter:
201 self.desc += '\nParameter: ' + self.parameter
205202
206203 self.ref = []
207204 for n in item_node.findall('References/Reference'):
291288 item.desc,
292289 website=site.host,
293290 severity=item.severity,
291 resolution=item.resolution,
294292 path=item.uri,
295293 params=item.parameter,
296294 request=item.request,
4343 self.obj_xml = objectify.fromstring(output)
4444
4545 def parse_issues(self):
46
4746 for issue in self.obj_xml["issue-type-group"]["item"]:
4847 url_list = []
4948 obj_issue = {}
5150 obj_issue["name"] = issue["name"].text
5251 obj_issue['advisory'] = issue["advisory"]["ref"].text
5352
54 if(issue["cve"]):
53 if("cve" in issue):
5554 obj_issue['cve'] = issue["cve"].text
5655
5756 for threat in self.obj_xml["url-group"]["item"]:
6463 for item in self.obj_xml["issue-group"]["item"]:
6564
6665 if int(item["url"]["ref"]) == int(threat.get('id')):
67 if item["issue-type"]["ref"] == threat['issue-type']:
66 if "test-http-traffic" in item["variant-group"]["item"] and item["issue-type"]["ref"] == threat['issue-type']:
6867
6968 http_traffic = item["variant-group"]["item"]["test-http-traffic"].text.split("\n\n")
7069
7574
7675 obj_issue["severity"] = item["severity"].text
7776 obj_issue["cvss_score"] = item["cvss-score"].text
78 obj_issue["issue_description"] = item["variant-group"]["item"]["issue-information"]["issue-tip"].text
77 if ("issue-tip" in item["variant-group"]["item"]["issue-information"]):
78 obj_issue["issue_description"] = item["variant-group"]["item"]["issue-information"]["issue-tip"].text
7979 break
8080
8181 for recomendation in self.obj_xml["fix-recommendation-group"]["item"]:
5555 for line in output.split('\n'):
5656 vals = line.split("\t")
5757
58 if len(vals[0].split(".")) == 4:
58 if len(vals) == 3:
5959
60 host = vals[0]
61 h_id = self.createAndAddHost(host)
62 i_id = self.createAndAddInterface(
63 h_id, host, ipv4_address=host, mac=vals[1])
64 n_id = self.createAndAddNoteToHost(
65 h_id, "NIC VENDOR:", vals[2])
60 if len(vals[0].split(".")) == 4:
61
62 host = vals[0]
63 h_id = self.createAndAddHost(host)
64 i_id = self.createAndAddInterface(h_id, host, ipv4_address=host, mac=vals[1])
65 n_id = self.createAndAddNoteToHost(h_id, "NIC VENDOR:", vals[2])
6666
6767 return True
6868
1010 from bs4 import BeautifulSoup, Comment
1111 from plugins import core
1212 from model import api
13 from urlparse import urlsplit
1314 import distutils.util
1415 import re
1516 import os
135136 path = item_node.findall('path')[0]
136137 location = item_node.findall('location')[0]
137138 severity = item_node.findall('severity')[0]
138 request = item_node.findall('./requestresponse/request')[0].text if len(
139 item_node.findall('./requestresponse/request')) > 0 else ""
140 response = ""
141
142 if len(item_node.findall('./requestresponse/response')) > 0:
143 response_node = item_node.findall('./requestresponse/response')[0]
144
145 if "base64" in response_node.attrib:
146 if distutils.util.strtobool(response_node.get("base64")):
147 response = response_node.text.decode("base64", "strict")
148 else:
149 response = response_node.text
139 request = self.decode_binary_node('./requestresponse/request')
140 response = self.decode_binary_node('./requestresponse/response')
150141
151142 detail = self.do_clean(item_node.findall('issueDetail'))
152143 remediation = self.do_clean(item_node.findall('remediationBackground'))
154145
155146 self.url = host_node.text
156147
157 rhost = re.search(
158 "(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;%\$#\=~_\-]+)).*?$",
159 self.url)
160
161 self.protocol = rhost.group(1)
162 self.host = rhost.group(4)
163
164 self.port = 80
165 if self.protocol == 'https':
166 self.port = 443
167
168 if rhost.group(11) is not None:
169 self.port = rhost.group(11)
148 url_data = urlsplit(self.url)
149
150 self.protocol = url_data.scheme
151 self.host = url_data.hostname
152
153 # Use the port in the URL if it is defined, or 80 or 443 by default
154 self.port = url_data.port or (443 if url_data.scheme == "https"
155 else 80)
170156
171157 self.name = name.text
172158 self.location = location.text
188174 if len(value) > 0:
189175 myreturn = value[0].text
190176 return myreturn
177
178 def decode_binary_node(self, path):
179 """
180 Finds a subnode matching `path` and returns its inner text if
181 it has no base64 attribute or its base64 decoded inner text if
182 it has it.
183 """
184 nodes = self.node.findall(path)
185 try:
186 subnode = nodes[0]
187 except IndexError:
188 return ""
189 encoded = distutils.util.strtobool(subnode.get('base64', 'false'))
190 if encoded:
191 return subnode.text.decode('base64', 'strict')
192 else:
193 return subnode.text
191194
192195 def get_text_from_subnode(self, subnode_xpath_expr):
193196 """
6666 self.items.append(item)
6767
6868 self.isZoneVuln = False
69 output= output.replace('\\$', '')
6970 r = re.search(
70 "Whoah, it worked - misconfigured DNS server found:\r\n([^$]+)There isn't much point continuing, you have everything.",
71 output)
71 "Whoah, it worked - misconfigured DNS server found:([^$]+)\There isn't much point continuing, you have everything.", output)
7272
7373 if r is not None:
7474
77
88 '''
99 from __future__ import with_statement
10 from plugins import core
11 from model import api
1210 import re
1311 import os
14 import pprint
1512 import sys
13 import logging
14
15 from plugins import core
16
17 logger = logging.getLogger(__name__)
1618
1719 try:
1820 import xml.etree.cElementTree as ET
6567 """
6668 try:
6769 tree = ET.fromstring(xml_output)
68 except SyntaxError, err:
69 print "SyntaxError: %s. %s" % (err, xml_output)
70 except SyntaxError as err:
71 logger.error("SyntaxError: %s. %s" % (err, xml_output))
7072 return None
7173
7274 return tree
101103 "property/[@key='os']/property/[@key='entity name']")
102104
103105 self.ports = []
104
106 self.services = []
107 self.process_ports(item_node)
108 self.process_services(item_node)
109
110 self.agent = False
111
112 for node in parent.findall("entity/[@class='agent']"):
113
114 self.node = node
115 agentip = node.get('name').split("/")[1]
116
117 if self.ip == agentip:
118
119 self.agentip = agentip
120
121 self.ipfrom = self.get_text_from_subnode(
122 "property/[@key='Connection Properties']/property/[@key='ip']") or agentip
123
124 self.agentype = node.get("type")
125
126 self.agentport = self.get_text_from_subnode(
127 "property/[@key='Connection Properties']//property/[@key='port']") or ""
128
129 self.agentsubtype = self.get_text_from_subnode(
130 "property/[@key='Connection Properties']//property/[@key='subtype']") or ""
131
132 self.agentcon = self.get_text_from_subnode(
133 "property/[@key='Connection Properties']//property/[@key='type']") or ""
134
135 self.agent = True
136 break
137
138 self.results = self.getResults(item_node)
139
140 def process_ports(self, item_node):
105141 for p in item_node.findall("property/[@key='tcp_ports']/property/[@type='port']"):
106
107142 self.ports.append({'port': p.get('key'),
108143 'protocol': "tcp",
109144 'status': "open" if p.text == "listen" else p.text})
110145
111146 for p in item_node.findall("property/[@key='udp_ports']/property/[@type='port']"):
112
113147 self.ports.append({'port': p.get('key'),
114148 'protocol': "udp",
115149 'status': "open" if p.text == "listen" else p.text})
116150
117 self.agent = False
118
119 for node in parent.findall("entity/[@class='agent']"):
120
121 self.node = node
122 agentip = node.get('name').split("/")[1]
123
124 if self.ip == agentip:
125
126 self.agentip = agentip
127
128 self.ipfrom = self.get_text_from_subnode(
129 "property/[@key='Connection Properties']/property/[@key='ip']")
130
131 self.agentype = node.get("type")
132
133 self.agentport = self.get_text_from_subnode(
134 "property/[@key='Connection Properties']//property/[@key='port']")
135
136 self.agentsubtype = self.get_text_from_subnode(
137 "property/[@key='Connection Properties']//property/[@key='subtype']")
138
139 self.agentcon = self.get_text_from_subnode(
140 "property/[@key='Connection Properties']//property/[@key='type']")
141
142 self.agent = True
143 break
144
145 self.results = self.getResults(item_node)
151 def process_services(self, item_node):
152 for service in item_node.findall("property/[@key='services']/property"):
153 service_name = service.get("key")
154 port, protocol = service.findall('property')[0].get('key').split('-')
155 self.services.append({
156 "name": service_name,
157 "protocol": protocol,
158 "port": port
159 })
146160
147161 def getResults(self, tree):
148162 """
149163 :param tree:
150164 """
151165 for self.issues in tree.findall("property/[@key='Vulnerabilities']/property/[@type='container']"):
166 yield Results(self.issues)
167 # 2017R1 compatibility
168 for self.issues in tree.findall("property/[@key='exposures']/property/[@type='container']"):
152169 yield Results(self.issues)
153170
154171 def get_text_from_subnode(self, subnode_xpath_expr):
167184 class Results():
168185
169186 def __init__(self, issue_node):
170
171187 self.node = issue_node
172 self.ref = issue_node.get('key')
188 self.ref = [issue_node.get("key")]
189 self.severity = ""
190 self.port = "Unknown"
191 self.service_name = "n/a"
192 self.protocol = "tcp?"
173193 vuln = issue_node.find("property/property")
174 self.name = vuln.get("key")
175 self.node = vuln
176 self.desc = self.get_text_from_subnode("property/[@key='description']")
177 self.port = self.get_text_from_subnode("property/[@key='port']")
194 if not vuln:
195 # 2017R1 compatibility
196 self.ref = []
197 vuln = issue_node.find("property")
198 self.name = self.get_text_from_subnode("property/[@key='title']")
199 self.desc = self.get_text_from_subnode("property/[@key='description']")
200 self.severity = self.get_text_from_subnode("property/[@key='severity']")
201 self.service_name = self.get_text_from_subnode("property/[@key='service']")
202 else:
203 # 2013R3 xml version
204 self.name = vuln.get("key")
205 self.node = vuln
206 self.desc = self.get_text_from_subnode("property/[@key='description']")
207 self.port = self.get_text_from_subnode("property/[@key='port']")
178208
179209 def get_text_from_subnode(self, subnode_xpath_expr):
180210 """
198228 core.PluginBase.__init__(self)
199229 self.id = "Core Impact"
200230 self.name = "Core Impact XML Output Plugin"
201 self.plugin_version = "0.0.1"
202 self.version = "Core Impact 2013R1"
231 self.plugin_version = "0.0.2"
232 self.version = "Core Impact 2013R1/2017R2"
203233 self.framework_version = "1.0.0"
204234 self.options = None
205235 self._current_output = None
210240 "impact_output-%s.xml" % self._rid)
211241
212242 def parseOutputString(self, output, debug=False):
213
214243 parser = ImpactXmlParser(output)
244 mapped_services = {}
245 mapped_ports = {}
215246 for item in parser.items:
216247
217248 h_id = self.createAndAddHost(
218249 item.ip,
219250 item.os + " " + item.arch)
220
251
221252 i_id = self.createAndAddInterface(
222253 h_id,
223 item.ip,
224 ipv4_address=item.ip,
254 item.ip,
255 ipv4_address=item.ip,
225256 hostname_resolution=item.host)
226257
258 for service in item.services:
259 s_id = self.createAndAddServiceToInterface(
260 h_id,
261 i_id,
262 service['name'],
263 service['protocol'],
264 ports=[service['port']],
265 status='open')
266 mapped_services[service['name']] = s_id
267 mapped_ports[service['port']] = s_id
268
269 if item.agent:
270 desc = "Agent Type: " + item.agentype
271 desc += "\nConn from:" + item.ipfrom
272 desc += "\nPort:" + item.agentport
273 desc += "\nProtocol:" + item.agentsubtype
274 desc += "\nConn:" + item.agentcon
275
276 self.createAndAddVulnToHost(
277 h_id,
278 "Core Impact Agent",
279 desc=desc,
280 severity="HIGH")
281
282 for v in item.results:
283 if v.service_name == "n/a" and v.port == "Unknown":
284 self.createAndAddVulnToHost(
285 h_id,
286 v.name,
287 desc=v.desc,
288 severity=v.severity,
289 ref=v.ref)
290 else:
291 s_id = mapped_services.get(v.service_name) or mapped_ports.get(v.port)
292 print(v.service_name)
293 print(s_id)
294 self.createAndAddVulnToService(
295 h_id,
296 s_id,
297 v.name,
298 desc=v.desc,
299 severity=v.severity,
300 ref=v.ref)
301
227302 for p in item.ports:
228
229303 s_id = self.createAndAddServiceToInterface(
230304 h_id,
231305 i_id,
233307 p['protocol'],
234308 ports=[p['port']],
235309 status=p['status'])
236
237 if item.agent:
238 desc = "Agent Type: " + item.agentype
239 desc += "\nConn from:" + item.ipfrom
240 desc += "\nPort:" + item.agentport
241 desc += "\nProtocol:" + item.agentsubtype
242 desc += "\nConn:" + item.agentcon
243
244 v_id = self.createAndAddVulnToHost(
245 h_id,
246 "Core Impact Agent",
247 desc=desc,
248 severity="HIGH")
249
250 for v in item.results:
251
252 if v.port == "Unknown":
253 v_id = self.createAndAddVulnToHost(
254 h_id,
255 v.name,
256 desc=v.desc,
257 ref=v.ref)
258 else:
259 s_id = self.createAndAddServiceToInterface(
260 h_id,
261 i_id,
262 v.port,
263 ports=[str(v.port)],
264 status="open")
265
266 v_id = self.createAndAddVulnToService(
267 h_id,
268 s_id,
269 v.name,
270 desc=v.desc,
271 ref=v.ref)
272310 del parser
273311
274312 def processCommandString(self, username, current_path, command_string):
280318
281319 def createPlugin():
282320 return ImpactPlugin()
321
283322
284323 if __name__ == '__main__':
285324 parser = ImpactXmlParser(sys.argv[1])
286325 for item in parser.items:
287326 if item.status == 'up':
288 print item
327 print(item)
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 '''
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 from lxml import etree
17
18 try:
19 import xml.etree.cElementTree as ET
20 import xml.etree.ElementTree as ET_ORIG
21 ETREE_VERSION = ET_ORIG.VERSION
22 except ImportError:
23 import xml.etree.ElementTree as ET
24 ETREE_VERSION = ET.VERSION
25
26 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
27
28 current_path = os.path.abspath(os.getcwd())
29
30 __author__ = "Thierry Beauquier"
31 __license__ = ""
32 __version__ = "1.0.0"
33 __maintainer__ = "Thierry Beauquier"
34 __email__ = "[email protected]"
35 __status__ = "Development"
36
37 '''
38 This plugin has been designed to be used with python-unittest2/paramiko script to perform security compliancy verification. It enables to have displayed both security scans results (nmap,
39 nessus, ..) and security verification compliancy (CIS-CAT, compagny's product security requirement) by Faraday-IPE
40
41 This plugin requires that a element "host" is added to <testcase/> (sed -i 's/<testcase/<testcase host=\"192.168.1.1\"/' junit.xml)
42
43 <testsuite errors="0" failures="1" name="AccountsWithSuperuserPrivilegesShallBeDisabledByDefault-20170118090010" skipped="0" tests="1" time="0.144">
44 <testcase host="192.168.1.1" classname="AccountsWithSuperuserPrivilegesShallBeDisabledByDefault" name="test_sshdRootLogin" time="0.144">
45 <failure message="SSH for root account is not disabled: '' matches '' in ''" type="AssertionError">
46 <![CDATA[Traceback (most recent call last):
47 File "bsr-ci.py", line 514, in test_sshdRootLogin
48 self.assertNotRegexpMatches(_ssh('cat /etc/ssh/sshd_config | egrep "^PermitRootLogin" | awk \'{print $2}\' | egrep "no|No|NO"',host),'', 'SSH for root account is not disabled')
49 AssertionError: SSH for root account is not disabled: '' matches '' in ''
50 ]]> </failure>
51 </testcase>
52 <system-out>
53 <![CDATA[]]> </system-out>
54 <system-err>
55 <![CDATA[]]> </system-err>
56 </testsuite>
57
58
59 '''
60
61 class JunitXmlParser(object):
62 """
63 The objective of this class is to parse an xml file generated by the junit.
64
65 @param junit_xml_filepath A proper xml generated by junit
66 """
67
68 def __init__(self, xml_output):
69
70 tree = self.parse_xml(xml_output)
71 if tree:
72 self.items = [data for data in self.get_items(tree)]
73 else:
74 self.items = []
75
76 def parse_xml(self, xml_output):
77 """
78 Open and parse an xml file.
79
80 @return xml_tree An xml tree instance. None if error.
81 """
82 try:
83 # return ET.fromstring(xml_output)
84 tree = etree.fromstring(xml_output)
85 except SyntaxError, err:
86 print "SyntaxError: %s. %s" % (err, xml_output)
87 return None
88 return tree
89
90 def get_items(self, tree):
91 """
92 @return items A list of Failure instances
93 """
94
95 for node in tree.findall('testsuite/testcase/failure'):
96 yield Testsuite(node)
97
98
99 class Testsuite(object):
100
101 def __init__(self, testsuite_node):
102 self.node = testsuite_node
103
104 self.parent = self.node.getparent()
105 self.name = self.parent.get('name')
106 self.host = self.parent.get('host')
107 if self.host is None:
108 print 'host element is missing'
109 self.host = ''
110
111 self.message = self.get_text_from_subnode('message')
112
113 def get_text_from_subnode(self, subnode_xpath_expr):
114 """
115 Finds a subnode in the host node and the retrieves a value from it.
116
117 @return An attribute value
118 """
119 sub_node = self.node.get(subnode_xpath_expr)
120 if sub_node is not None:
121 return sub_node
122
123 return None
124
125 class JunitPlugin(core.PluginBase):
126 """
127 Example plugin to parse junit output.
128 """
129
130 def __init__(self):
131 core.PluginBase.__init__(self)
132 self.id = "Junit"
133 self.name = "Junit XML Output Plugin"
134 self.plugin_version = "0.0.1"
135 self.version = ""
136 self.framework_version = "1.0.0"
137 self.options = None
138 self._current_output = None
139 self._command_regex = None
140
141 def parseOutputString(self, output, debug=False):
142
143 parser = JunitXmlParser(output)
144 for item in parser.items:
145 h_id = self.createAndAddHost(item.host, os="Linux")
146 i_id = self.createAndAddInterface(h_id, item.host, ipv4_address=item.host)
147 self.createAndAddVulnToHost(h_id, name=item.name, desc=item.message, ref=[], severity="High")
148 del parser
149
150 def createPlugin():
151 return JunitPlugin()
152
153 if __name__ == '__main__':
154 parser = JunitXmlParser(sys.argv[1])
155 for item in parser.items:
156 if item.status == 'up':
157 print item
5050
5151 def __init__(self, xml_output):
5252 tree = self.parse_xml(xml_output)
53 vulns = self.get_vuln_definitions(tree)
53 self.vulns = self.get_vuln_definitions(tree)
5454
5555 if tree:
56 self.items = self.get_items(tree, vulns)
56 self.items = self.get_items(tree, self.vulns)
5757 else:
5858 self.items = []
5959
8989 ret += self.parse_html_type(child)
9090 else:
9191 ret += node.text.encode(
92 "ascii", errors="backslashreplace").strip() if node.get('text') else ""
92 "ascii", errors="backslashreplace").strip() if node.text else ""
9393 if tag == 'listitem':
9494 if len(list(node)) > 0:
9595 for child in list(node):
9696 ret += self.parse_html_type(child)
9797 else:
9898 ret = node.text.encode(
99 "ascii", errors="backslashreplace").strip() if node.get('text') else ""
99 "ascii", errors="backslashreplace").strip() if node.text else ""
100100 if tag == 'orderedlist':
101101 i = 1
102102 for item in list(node):
108108 ret += self.parse_html_type(child)
109109 else:
110110 ret += node.text.encode("ascii",
111 errors="backslashreplace") if node.get('text') else ""
111 errors="backslashreplace") if node.text else ""
112112 if tag == 'unorderedlist':
113113 for item in list(node):
114114 ret += "\t" + "* " + self.parse_html_type(item) + "\n"
133133 """
134134 vulns = list()
135135
136 for tests in node.iter('tests'):
136 for tests in node.findall('tests'):
137137 for test in tests.iter('test'):
138138 vuln = dict()
139139 if test.get('id').lower() in vulnsDefinitions:
140 vuln = vulnsDefinitions[test.get('id').lower()]
140 vuln = vulnsDefinitions[test.get('id').lower()].copy()
141 key = test.get('key', '')
142 if key.startswith('/'):
143 # It has the path where the vuln was found
144 # Example key: "/comments.asp||content"
145 vuln['path'] = key[:key.find('|')]
141146 for desc in list(test):
142147 vuln['desc'] += self.parse_html_type(desc)
143148 vulns.append(vuln)
161166 'refs': ["vector: " + vector, vid],
162167 'resolution': "",
163168 'severity': (int(vulnDef.get('severity')) - 1) / 2,
164 'tags': list()
169 'tags': list(),
170 'is_web': vid.startswith('http-')
165171 }
166172
167173 for item in list(vulnDef):
178184 vuln['refs'].append(title + ' ' + link)
179185 if item.tag == 'references':
180186 for ref in list(item):
181 if ref.get('text'):
182 rf = ref.get('text').encode(
187 if ref.text:
188 rf = ref.text.encode(
183189 "ascii", errors="backslashreplace").strip()
184190 vuln['refs'].append(rf)
185191 if item.tag == 'solution':
290296 status=s['status'],
291297 version=version)
292298 for v in s['vulns']:
293 v_id = self.createAndAddVulnToService(h_id, s_id, v['name'], v['desc'], v[
294 'refs'], v['severity'], v['resolution'])
299 if v['is_web']:
300 v_id = self.createAndAddVulnWebToService(
301 h_id, s_id, v['name'], v['desc'], v['refs'],
302 v['severity'], v['resolution'],
303 path=v.get('path',''))
304 else:
305 v_id = self.createAndAddVulnToService(
306 h_id, s_id, v['name'], v['desc'], v['refs'],
307 v['severity'], v['resolution'])
295308 del parser
296309
297310 def processCommandString(self, username, current_path, command_string):
55 sqlalchemy>=1.0.12
66 pyopenssl>=16.0.0
77 service_identity>=16.0.0
8 pyasn1-modules
1010 from server.dao.service import ServiceDAO
1111 from server.dao.interface import InterfaceDAO
1212 from server.dao.note import NoteDAO
13 from server.utils.web import gzipped, validate_workspace, get_basic_auth, validate_admin_perm, validate_database, build_bad_request_response
14 from server.couchdb import list_workspaces_as_user, get_workspace, get_auth_info
13 from server.utils.web import (
14 gzipped,
15 validate_workspace,
16 get_basic_auth,
17 validate_admin_perm,
18 build_bad_request_response
19 )
20 from server.couchdb import (
21 list_workspaces_as_user,
22 get_workspace
23 )
1524 from server.database import get_manager
1625
1726
2130 return flask.jsonify(
2231 list_workspaces_as_user(
2332 flask.request.cookies, get_basic_auth()))
33
2434
2535 @app.route('/ws/<workspace>/summary', methods=['GET'])
2636 @gzipped
4757
4858 return flask.jsonify(response)
4959
60
5061 @app.route('/ws/<workspace>', methods=['GET'])
5162 @gzipped
5263 def workspace(workspace):
5566 flask.request.cookies, get_basic_auth())['workspaces']
5667 ws = get_workspace(workspace, flask.request.cookies, get_basic_auth()) if workspace in workspaces else None
5768 # TODO: When the workspace DAO is ready, we have to remove this next line
58 if not ws.get('fdate') and ws.get('duration'): ws['fdate'] = ws.get('duration').get('end')
59 if not ws.get('description'): ws['description'] = ''
69 if not ws.get('fdate') and ws.get('duration'):
70 ws['fdate'] = ws.get('duration').get('end')
71 if not ws.get('description'):
72 ws['description'] = ''
6073 return flask.jsonify(ws)
74
6175
6276 @app.route('/ws/<workspace>', methods=['PUT'])
6377 @gzipped
86100 elif workspace not in db_manager and not is_update_request:
87101 res = db_manager.create_workspace(document)
88102 else:
89 abort(400)
103 flask.abort(400)
90104
91105 if not res:
92106 response = flask.jsonify({'error': "There was an error {0} the workspace".format("updating" if is_update_request else "creating")})
94108 return response
95109
96110 return flask.jsonify({'ok': True})
111
97112
98113 @app.route('/ws/<workspace>', methods=['DELETE'])
99114 @gzipped
5050 "web": [],
5151 "issuetracker": [],
5252 "creator": [EntityMetadata.creator],
53 "command_id": [EntityMetadata.command_id]
53 "command_id": [EntityMetadata.command_id],
54 "policyviolations": [Vulnerability.policyviolations]
5455 }
5556
5657 STRICT_FILTERING = ["type", "service", "couchid", "hostid", "serviceid", 'interfaceid', 'id', 'status', 'command_id']
7980 Vulnerability.method, Vulnerability.params, Vulnerability.pname, Vulnerability.query,\
8081 EntityMetadata.couchdb_id, EntityMetadata.revision, EntityMetadata.create_time, EntityMetadata.creator,\
8182 EntityMetadata.owner, EntityMetadata.update_action, EntityMetadata.update_controller_action,\
82 EntityMetadata.update_time, EntityMetadata.update_user, EntityMetadata.document_type, EntityMetadata.command_id, Vulnerability.attachments)
83 EntityMetadata.update_time, EntityMetadata.update_user, EntityMetadata.document_type, EntityMetadata.command_id, \
84 Vulnerability.attachments, Vulnerability.policyviolations)
8385 service_bundle = Bundle('service', Service.name.label('s_name'), Service.ports, Service.protocol, Service.id)
8486 host_bundle = Bundle('host', Host.name)
8587
171173 'owned': vuln.owned,
172174 'owner': vuln.owner,
173175 'parent': get_parent_id(vuln.couchdb_id),
176 'policyviolations': json.loads(vuln.policyviolations),
174177 'refs': json.loads(vuln.refs),
175178 'status': vuln.status,
176179 'website': vuln.website,
88 from sqlalchemy.ext.declarative import declarative_base
99
1010
11 SCHEMA_VERSION = 'W.2.5.0'
11 SCHEMA_VERSION = 'W.2.6.1'
1212
1313 Base = declarative_base()
1414
308308 severity = Column(String(50))
309309 owned = Column(Boolean)
310310 attachments = Column(Text(), nullable=True)
311 policyviolations = Column(Text())
311312
312313 impact_accountability = Column(Boolean)
313314 impact_availability = Column(Boolean)
346347 self.severity=document.get('severity')
347348 self.owned=document.get('owned', False)
348349 self.attachments = json.dumps(document.get('_attachments', {}))
350 self.policyviolations = json.dumps(document.get('policyviolations', []))
349351 self.impact_accountability=document.get('impact', {}).get('accountability')
350352 self.impact_availability=document.get('impact', {}).get('availability')
351353 self.impact_confidentiality=document.get('impact', {}).get('confidentiality')
793793 .reference{margin-top: 5px;}
794794 div.form-group.editArray{margin-bottom: 0px}
795795 div.modal-footer.editArray{margin-top: 0px}
796 input#vuln-refs{border-radius: 5px 0 0 5px}
796 input#vuln-refs, input#vuln-policyviolations {border-radius: 5px 0 0 5px}
797797 i.fa.fa-plus-circle{color: green;}
798798 i.fa.fa-minus-circle{color: red;cursor: pointer;}
799799 span.input-group-addon.button-radius{
11361136 .header_right {
11371137 float: right;
11381138 margin: 8px;
1139 }
1140
1141 .accordion-expand-button {
1142 color: #008000;
1143 right: 10px;
1144 top: -25px !important;
1145 }
1146
1147 .accordion-expand-button-disabled {
1148 display: none !important;
11391149 }
6464 <div id="cont">
6565 <div class="wrapper" ng-controller="indexCtrl">
6666 <header class="head">
67 <a href="#" class="ws-dashboard" uib-tooltip="{{version}}" tooltip-placement="bottom"><img class="logo animated fadeInDown" title="{{version}}" src="images/logo-faraday.svg" alt="Faraday home | WS Dashboard"/></a>
67 <a href="#" class="ws-dashboard" uib-tooltip="{{version}}" tooltip-placement="bottom"><img class="logo animated fadeInDown" src="images/logo-faraday.svg" alt="Faraday home | WS Dashboard"/></a>
6868 <div class="btn-group dropdown header_right" uib-dropdown="" is-open="status.isopen">
6969 <button id="single-button" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle="" ng-disabled="disabled" aria-haspopup="true" aria-expanded="true">
7070 <i class="fa fa-cog fa-lg"></i> <span class="caret"></span>
260260 templateUrl: 'scripts/commons/partials/commercial.html',
261261 controller: 'commercialCtrl'
262262 }).
263 when('/taskgroup', {
264 templateUrl: 'scripts/commons/partials/commercial.html',
265 controller: 'commercialCtrl',
266 title: 'Methodologies | '
267 }).
263268 otherwise({
264269 templateUrl: 'scripts/commons/partials/home.html'
265270 });
1111 <span class="input-group-addon cursor" ng-click="newValue()"><i class="fa fa-plus-circle"></i></span>
1212 </div>
1313 <div class="input-group margin-bottom-sm reference" ng-repeat="v in data.property">
14 <input type="text" class="form-control" ng-model="v.value"/>
14 <input type="text" class="form-control" ng-model="v.value" disabled/>
1515 <span class="input-group-addon cursor" ng-click="data.property.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
1616 </div>
1717 </div>
5050 <strong>Manage reports</strong>
5151 </small>
5252 </a>
53 <a href="#/taskgroup" class="ws-link item animated flipInX">
54 <i class="fa fa-tasks fa-4x icons-color-home"></i>
55 <span class="ws-name">Tasks</span>
56 <small>
57 Control all your tasks.<br/>
58 <strong>Plan your Job</strong>
59 </small>
60 </a>
5361 <a href="#/communication" class="ws-link item animated flipInX">
5462 <img src="images/ico-communication.svg" />
5563 <span class="ws-name">Chat</span>
3333 object[prop] = "";
3434 }
3535 if(prop === "date") object[prop] = parseDate(v["metadata"]["create_time"] * 1000);
36 if(prop === "creator") object[prop] = v["metadata"]["creator"];
36 if(prop === "creator") object[prop] = excelEscape(v["metadata"]["creator"]);
3737 if(prop === "web") {
3838 if(v.type === "Vulnerability") {
3939 object[prop] = false;
5858 };
5959
6060 cleanCSV = function(field) {
61 return field.replace(/\"/g, "\"\"");
61 return excelEscape(field.replace(/\"/g, "\"\""));
6262 };
6363
6464 parseObject = function(object) {
7676 });
7777 }
7878 parsedData = parsedData.substring(0, parsedData.length - 1);
79 return parsedData;
79 return excelEscape(parsedData);
8080 };
8181
8282 parseDate = function(date) {
8383 var d = new Date(date);
84 return d.getMonth()+1 +"/" + d.getDate() + "/" + d.getFullYear();
84 return excelEscape(d.getMonth()+1 +"/" + d.getDate() + "/" + d.getFullYear());
8585 };
86
87 excelEscape = function(data){
88 // Patch possible formula injection attacks
89 // See https://www.contextis.com/resources/blog/comma-separated-vulnerabilities/ for more info.
90 if(data.startsWith('=') || data.startsWith('+')
91 || data.startsWith('-')
92 || data.startsWith('@')){
93 return "'" + data
94 }else{
95 return data
96 }
97 }
8698
8799 return csvService;
88100 });
22 // See the file 'doc/LICENSE' for the license information
33
44 angular.module('faradayApp')
5 .factory('cweFact', ['BASEURL', '$http', '$q', 'vulnModelsManager', function(BASEURL, $http, $q, vulnModelsManager) {
5 .factory('cweFact', ['BASEURL', '$http', '$q', 'vulnModelsManager', 'commonsFact', function(BASEURL, $http, $q, vulnModelsManager, commonsFact) {
66 var cweFact = {};
77
88 // XXX: this is still not using the server
1919 var c = {
2020 id: obj.id,
2121 cwe: obj.doc.cwe,
22 name: obj.doc.name,
23 desc: description,
22 name: commonsFact.htmlentities(obj.doc.name),
23 desc: commonsFact.htmlentities(description),
2424 resolution: obj.doc.resolution,
2525 exploitation: obj.doc.exploitation,
2626 refs: obj.doc.references
7979 var hurl = "/" + workspace + "/_design/hosts/_view/hosts";
8080 hosts = get_obj(hurl);
8181 var name = hosts[d.key].name;
82 document.getElementById("barText").innerHTML = "<div style='background-color:" + d.color + "'><b>" + name + '</b></div>' + d.value;
82 var element = document.getElementById("barText");
83 var colored = document.createElement('div');
84 colored.style = "background-color:" + d.color; // Color is safe (its value is in a whitelist)
85 colored.innerText = name;
86 while (element.firstChild) {
87 // https://stackoverflow.com/questions/3955229/remove-all-child-elements-of-a-dom-node-in-javascript
88 element.removeChild(element.firstChild);
89 }
90 element.appendChild(colored);
91 element.appendChild(document.createTextNode(d.value));
8392 })
8493 .on('mouseenter', function(d) {
8594 var line = d3.select('.id-'+d.key)
9999 .style("stroke-width", "0.5")
100100 .style("opacity", 0)
101101 .on('mouseover', function(d) {
102 document.getElementById("cakeText").innerHTML = "<div style='background-color:" + d.color + "'><b>" + d.key + '</b></div>' + d.value;
102 var element = document.getElementById("cakeText");
103 var colored = document.createElement('div');
104 colored.style = "background-color:" + d.color; // Color is safe (its value is in a whitelist)
105 colored.innerText = d.key;
106 while (element.firstChild) {
107 // https://stackoverflow.com/questions/3955229/remove-all-child-elements-of-a-dom-node-in-javascript
108 element.removeChild(element.firstChild);
109 }
110 element.appendChild(colored);
111 element.appendChild(document.createTextNode(d.value));
103112 })
104113 .on('mouseenter', function(d) {
105114 var slice = d3.select('.cake-'+d.key)
22 // See the file 'doc/LICENSE' for the license information
33
44 angular.module('faradayApp')
5 .directive('d3Treemap', ['d3Service',
5 .directive('d3Treemap', ['d3Service',
66 function(d3Service) {
77 return {
88 restrict: 'EA',
6060 .sticky(true)
6161 .value(function(d) {return d.count});
6262
63 function nameToClassSafeName(name) {
64 // Remove non alphanumeric characters to safely use the (modified)
65 // name as a class name
66 return name.replace(/[^0-9a-zA-Z]/g, '');
67 }
68
6369 var node = div.datum(data_cp).selectAll(".node")
6470 .data(treemap.nodes)
6571 .enter().append("div")
6672 .attr("class", function(d) {
6773 var ret = "node treemap-tooltip";
68 if(d.name) ret += " tm-" + d.name;
74 if(d.name) ret += " tm-" + nameToClassSafeName(d.name);
6975 return ret;
7076 })
7177 .call(position)
7884 }
7985 })
8086 .on('mouseover', function(d){
81 if (!data.width){
82 document.getElementById("treemapText").innerHTML = "<div style='background-color:" + d.color + "'>" + d.name + '</div>' + d.count;
83 }else{
84 document.getElementById("treemapTextModel").innerHTML = "<div style='background-color:" + d.color + "'>" + d.name + '</div>' + d.count;
85 }
87 if(typeof(d.name) === 'undefined') return; // I don't know why this happens
88 if (!data.width){
89 var element = document.getElementById("treemapText");
90 //.innerHTML = "<div style='background-color:" + d.color + "'>" + d.name + '</div>' + d.count;
91 }else{
92 var element = document.getElementById("treemapTextModel");
93 }
94 var colored = document.createElement('div');
95 colored.style = "background-color:" + d.color; // Color is safe (its value is in a whitelist)
96 colored.innerText = d.name;
97 while (element.firstChild) {
98 // https://stackoverflow.com/questions/3955229/remove-all-child-elements-of-a-dom-node-in-javascript
99 element.removeChild(element.firstChild);
100 }
101 element.appendChild(colored);
102 element.appendChild(document.createTextNode(d.count));
86103 })
87104 .on('mouseenter', function(d) {
88 var line = d3.select('.tm-'+d.name)
105 if(typeof(d.name) === 'undefined') return; // I don't know why this happens
106 var line = d3.select('.tm-'+nameToClassSafeName(d.name))
89107 .style("opacity", 1);
90108 })
91109 .on('mouseleave', function(d) {
92 var line = d3.select('.tm-'+d.name)
110 if(typeof(d.name) === 'undefined') return; // I don't know why this happens
111 var line = d3.select('.tm-'+nameToClassSafeName(d.name))
93112 .style("opacity", 0.8);
94113 document.getElementById("treemapText").innerHTML = "";
95114 })
3131 a_href = element.find('a')[0];
3232
3333 $click.on(a_href);
34 $timeout(function() {$blob.revoke(url);});
34
35 //Delay is necesary only for old versions of firefox browser.
36 //Ref: https://stackoverflow.com/questions/30694453/blob-createobjecturl-download-not-working-in-firefox-but-works-when-debugging
37 $timeout(function() {$blob.revoke(url);}, 1000);
3538
3639 element[0].removeChild(a_href);
3740 });
2626 <li>
2727 <a href="#/executive" class="executive-report" style="color: #ffffff !important" uib-tooltip="Executive Report" tooltip-placement="right">
2828 <img src="images/ico-executive-menu.svg" alt="Executive Report"/>
29 </a>
30 </li>
31 <li>
32 <a href="#/taskgroup" class="executive-report" style="color: #ffffff !important" uib-tooltip="Tasks" tooltip-placement="right">
33 <i class="fa fa-tasks host"></i>
2934 </a>
3035 </li>
3136 <li>
1010 vm.saveAsModelDisabled = false;
1111 vm.easeofresolution;
1212 vm.new_ref;
13 vm.new_policyviolation;
1314 vm.icons;
1415 vm.cweList;
1516 vm.cweLimit;
2627 vm.severities = severities;
2728 vm.statuses = STATUSES;
2829 vm.new_ref = "";
30 vm.new_policyviolation = "";
2931 vm.icons = {};
3032
3133 vm.cweList = [];
6264 response: "",
6365 website: "",
6466 status: "opened",
67 policyviolations: []
6568 };
6669
6770 vm.vuln = angular.copy(vuln);
8992 vm.file_name_error = true;
9093 }
9194 });
92 vm.icons = commons.loadIcons(vm._attachments);
95 vm.icons = commons.loadIcons(vm._attachments);
9396 }
9497
9598 vm.removeEvidence = function(name) {
100103 vm.toggleImpact = function(key) {
101104 vm.data.impact[key] = !vm.data.impact[key];
102105 };
103
106
104107 vm.ok = function() {
105108 // add the ref in new_ref, if there's any
106109 vm.newReference();
110113 refs.push(ref.value);
111114 });
112115 vm.data.refs = refs;
116
117 // add the policy violation in new_policyviolation, if there's any
118 vm.newPolicyViolation();
119 // convert policy violations to an array of strings
120 var policyviolations = [];
121 vm.data.policyviolations.forEach(function(policyviolation) {
122 policyviolations.push(policyviolation.value);
123 });
124 vm.data.policyviolations = policyviolations;
113125 $modalInstance.close(vm.data);
114126 };
115127
127139 }
128140 }
129141
142 vm.newPolicyViolation = function() {
143 if (vm.new_policyviolation != "") {
144 // we need to check if the policy violation already exists
145 if (vm.data.policyviolations.filter(function(policyviolation) {return policyviolation.value === vm.new_policyviolation}).length == 0) {
146 vm.data.policyviolations.push({value: vm.new_policyviolation});
147 vm.new_policyviolation = "";
148 }
149 }
150 }
151
130152 vm.populate = function(item) {
131153 for (var key in vm.data) {
132 if (key != "refs" && item.hasOwnProperty(key) && vm.data.hasOwnProperty(key)) {
154 if (key != "refs" && key != "policyviolations" && item.hasOwnProperty(key) && vm.data.hasOwnProperty(key)) {
133155 vm.data[key] = item[key];
134156 }
135157 }
139161 refs.push({value: ref});
140162 });
141163 vm.data.refs = refs;
164
165 // convert policyviolations to an array of objects
166 var policyviolations = [];
167 item.policyviolations.forEach(function(policyviolation) {
168 policyviolations.push({value: policyviolation});
169 });
170 vm.data.policyviolations = policyviolations;
142171 }
143172
144173 init();
1212 vm.easeofresolution;
1313 vm.workspace;
1414 vm.new_ref;
15 vm.new_policyviolation;
1516 vm.icons;
1617 vm.cweList;
1718 vm.cweLimit;
2324 vm.newCurrentPage;
2425 vm.pageSize;
2526
26 vm.targets;
27 vm.targets;
2728 vm.target_filter;
2829
2930 vm.data;
31
32 // true if all the parents in data.parents are type Host
33 vm.host_parents;
3034
3135 init = function() {
3236 vm.vuln_types = [
3741 vm.severities = severities;
3842 vm.workspace = workspace;
3943 vm.new_ref = "";
44 vm.new_policyviolation = "";
4045 vm.icons = {};
46
47 vm.host_parents = false;
4148
4249 vm.cweList = [];
4350 cweFact.get().then(function(data) {
4754 vm.cwe_filter = "";
4855
4956 vm.file_name_error = false;
50
57
5158 vm.pageSize = 5;
5259 vm.currentPage = 0;
5360 vm.newCurrentPage = 0;
5461
5562 vm.data = {
5663 _attachments: {},
57 type: "Vulnerability",
5864 data: "",
5965 desc: "",
6066 easeofresolution: undefined,
6470 confidentiality: false,
6571 integrity: false
6672 },
73 method: "",
6774 name: "",
6875 owned: false,
69 parent: undefined,
76 params: "",
77 parents: [],
78 path: "",
79 pname: "",
80 policyviolations: [],
81 query: "",
7082 refs: [],
83 request: "",
7184 resolution: "",
85 response: "",
7286 severity: undefined,
73 method: "",
74 path: "",
75 pname: "",
76 params: "",
77 query: "",
78 request: "",
79 response: "",
87 type: "Vulnerability",
8088 website: ""
8189 };
8290
110118 };
111119
112120 vm.ok = function() {
113 if (!(vm.data.type === "VulnerabilityWeb" && vm.data.parent.type === "Host")) {
114 // add the ref in new_ref, if there's any
115 vm.newReference();
116
117 // convert refs to an array of strings
118 var refs = [];
119 vm.data.refs.forEach(function(ref) {
120 refs.push(ref.value);
121 });
122 vm.data.refs = refs;
123
124 // delete selection
125 delete vm.data.parent.selected_modalNewCtrl;
126
127 vm.data.parent = vm.data.parent._id;
128
129 $modalInstance.close(vm.data);
130 }
121 // add the ref in new_ref, if there's any
122 vm.newReference();
123 vm.newPolicyViolation();
124
125 // convert refs to an array of strings
126 var refs = [];
127 vm.data.refs.forEach(function(ref) {
128 refs.push(ref.value);
129 });
130 vm.data.refs = refs;
131
132 var policyviolations = [];
133 vm.data.policyviolations.forEach(function(violation) {
134 policyviolations.push(violation.value);
135 });
136 vm.data.policyviolations = policyviolations;
137
138 var parents = vm.data.parents;
139 vm.data.parents = [];
140 parents.forEach(function(parent) {
141 vm.data.parents.push(parent._id);
142 });
143
144 $modalInstance.close(vm.data);
131145 };
132146
133147 vm.cancel = function() {
134148 $modalInstance.dismiss('cancel');
135149 };
136150
151 vm.setTargets = function(filter, start, size) {
152 var end = start + size,
153 targets = vm.targets;
154
155 if(filter) {
156 targets = vm.targets_filtered;
157 }
158
159 vm.data.parents = targets.slice(start, end);
160
161 vm.host_parents = vm.data.parents.some(function(elem, ind, arr) {
162 return elem.type === 'Host';
163 });
164 };
165
137166 vm.setTarget = function(target) {
138 if (vm.data.parent != undefined) {
139 delete vm.data.parent.selected_modalNewCtrl;
140 }
141 target.selected_modalNewCtrl = true;
142 vm.data.parent = target;
167 var index = vm.data.parents.indexOf(target);
168
169 if(index >= 0) {
170 // if target already selected, user is deselecting
171 vm.data.parents.splice(index, 1);
172 } else {
173 // else, add to parents list
174 vm.data.parents.push(target);
175 }
176
177 // refresh host_parents var
178 vm.host_parents = vm.data.parents.some(function(elem, ind, arr) {
179 return elem.type === 'Host';
180 });
143181 }
144182
145183 vm.go = function() {
146184 vm.currentPage = 0;
147 if(vm.newCurrentPage <= parseInt(vm.targets.length/vm.pageSize)
148 && vm.newCurrentPage > -1) {
149 vm.currentPage = vm.newCurrentPage;
185 if((vm.newCurrentPage-1) <= parseInt(vm.targets.length/vm.pageSize)
186 && (vm.newCurrentPage-1) > -1) {
187 vm.currentPage = (vm.newCurrentPage-1);
150188 }
151189 }
152190
160198 }
161199 }
162200
201 vm.newPolicyViolation = function() {
202 if (vm.new_policyviolation != "") {
203 // we need to check if the policy violation already exists
204 if (vm.data.policyviolations.filter(function(policyviolation) {return policyviolation.value === vm.new_policyviolation}).length == 0) {
205 vm.data.policyviolations.push({value: vm.new_policyviolation});
206 vm.new_policyviolation = "";
207 }
208 }
209 }
210
163211 vm.populate = function(item, model, label) {
164212
165213 for (var key in item) {
166 if (key != "refs" && vm.data.hasOwnProperty(key)) {
214 if(key != "refs" && key != "policyviolations" && vm.data.hasOwnProperty(key)) {
167215 vm.data[key] = item[key];
168216 }
169217 }
174222 refs.push({value: ref});
175223 });
176224 vm.data.refs = refs;
225
226 var policyviolations = [];
227 item.policyviolations.forEach(function(policyviolation) {
228 policyviolations.push({value: policyviolation});
229 });
230 vm.data.policyviolations = policyviolations;
177231 }
178232
179233 init();
174174 "query": false,
175175 "response": false,
176176 "web": false,
177 "creator": false
177 "creator": false,
178 "policyviolations": false
178179 };
179180
180181 // created object for columns cookie columns
392393 width: '100',
393394 sort: getColumnSort('metadata.creator'),
394395 visible: $scope.columns["creator"]
396 });
397 $scope.gridOptions.columnDefs.push({ name : 'policyviolations',
398 displayName : "policy violations",
399 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/policyviolationscolumn.html',
400 headerCellTemplate: header,
401 width: '100',
402 sort: getColumnSort('policyviolations'),
403 visible: $scope.columns["policyviolations"]
395404 });
396405 };
397406
733742 'Enter the new easeofresolution:',
734743 'easeofresolution',
735744 {options: EASEOFRESOLUTION});
745 };
746
747 $scope.editPolicyviolations = function() {
748 editProperty(
749 'scripts/commons/partials/editArray.html',
750 'commonsModalEditArray',
751 'Enter the new policy violations:',
752 'policyviolations',
753 {callback: function (vuln, policyviolations) {
754 var violations = vuln.policyviolations.concat([]);
755 policyviolations.forEach(function(policyviolation) {
756 if(vuln.policyviolations.indexOf(policyviolation) == -1){
757 violations.push(policyviolation);
758 }
759 });
760
761 return {'policyviolations': violations};
762 }}
763 );
736764 };
737765
738766 $scope.editReferences = function() {
0 <div class="panel panel-default">
1 <div role="tab" id="{{::headingId}}" aria-selected="{{isOpen}}" class="panel-heading" ng-keypress="toggleOpen($event)">
2 <h4 class="panel-title">
3 <span uib-accordion-transclude="heading" class="accordion-toggle" uib-tabindex-toggle>
4 <span uib-accordion-header ng-class="{'text-muted': isDisabled}">
5 {{heading}}
6 </span>
7 <i class="pull-right glyphicon accordion-expand-button" ng-class="{'glyphicon glyphicon-minus-sign': isOpen, 'glyphicon glyphicon-plus-sign': !isOpen, 'accordion-expand-button-disabled': isDisabled}" ng-disabled="isDisabled" role="button" data-toggle="collapse" href aria-expanded="{{isOpen}}" aria-controls="{{::panelId}}" tabindex="0" ng-click="toggleOpen()"></i>
8 </span>
9 </h4>
10 </div>
11 <div id="{{::panelId}}" aria-labelledby="{{::headingId}}" aria-hidden="{{!isOpen}}" role="tabpanel" class="panel-collapse collapse" uib-collapse="!isOpen">
12 <div class="panel-body" ng-transclude></div>
13 </div>
14 </div>
7474 <div class="col-md-12 reference" ng-repeat="reference in modal.data.refs">
7575 <div class="input-group margin-bottom-sm">
7676 <label class="sr-only" for="vuln-refs">References</label>
77 <input type="text" class="form-control" id="vuln-refs" placeholder="Reference" ng-model="reference.value"/>
77 <input type="text" class="form-control" id="vuln-refs" placeholder="Reference" ng-model="reference.value" disabled/>
7878 <span class="input-group-addon cursor" ng-click="modal.data.refs.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
7979 </div>
8080 </div>
8383 <div class="col-md-12">
8484 <label class="sr-only" for="vuln-resolution">Vuln Resolution</label>
8585 <textarea class="form-control" id="vuln-resolution" placeholder="Resolution" ng-model="modal.data.resolution"></textarea>
86 </div>
87 </div><!-- .form-group -->
88 <div class="form-group">
89 <div class="col-md-12">
90 <div class="input-group margin-bottom-sm">
91 <label class="sr-only" for="vuln-policyviolations">Policy Violations</label>
92 <input type="text" class="form-control" id="vuln-policyviolations" placeholder="Policy Violations" ng-model="modal.new_policyviolation"/>
93 <span class="input-group-addon cursor" ng-click="modal.newPolicyViolation()"><i class="fa fa-plus-circle"></i></span>
94 </div>
95 </div>
96 <div class="col-md-12 reference" ng-repeat="policyviolation in modal.data.policyviolations">
97 <div class="input-group margin-bottom-sm">
98 <label class="sr-only" for="vuln-policyviolations">Policy Violation</label>
99 <input type="text" class="form-control" id="vuln-policyviolations" placeholder="Policy Violation" ng-model="policyviolation.value" disabled/>
100 <span class="input-group-addon cursor" ng-click="modal.data.policyviolations.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
101 </div>
86102 </div>
87103 </div><!-- .form-group -->
88104 <div ng-if="modal.vuln.type === 'VulnerabilityWeb'">
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 || modal.data.severity === undefined">OK</button>
7 <button class="btn btn-success" ng-click="modal.ok()" ng-disabled="form.$invalid || modal.data.severity === undefined || (modal.data.type === 'VulnerabilityWeb' && modal.host_parents)">OK</button>
88 <button class="btn btn-danger" ng-click="modal.cancel()">Cancel</button>
99 </div>
1010 <h3 class="modal-title">Vulnerability creation</h3>
1111 </div>
1212 <div class="modal-body">
1313 <div class="form-horizontal">
14 <div class="form-group">
15 <div class="col-md-12">
14 <h5>Target</h5>
15 <div class="form-group">
16 <div class="col-md-10">
1617 <div class="form-group input-accordion">
17 <input type="text" ng-model="modal.target_filter" class="form-control input-sm" placeholder="Search" ng-change="modal.currentPage = 0">
18 </div>
18 <input type="text" ng-model="modal.target_filter" class="form-control input-sm" placeholder="Search targets" ng-change="modal.currentPage = 0">
19 </div>
20 </div>
21 <div class="col-md-2">
22 <div class="btn-group btn-small-margin">
23 <button type="button" class="btn btn-default btn-sm" title="Select page" ng-click="modal.setTargets(true, modal.currentPage*modal.pageSize, modal.pageSize)">
24 Select page
25 </button>
26 <button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" title="Select options">
27 <span class="caret"></span>
28 </button>
29 <ul class="dropdown-menu dropdown-menu-right" role="menu">
30 <li ng-show="modal.target_filter && modal.targets_filtered.length > 0">
31 <a class="ws" ng-click="modal.setTargets(true, 0, modal.targets_filtered.length)">Select all hosts in search</a>
32 </li>
33 <li>
34 <a class="ws" ng-click="modal.setTargets(false, 0, modal.targets.length)">Select all hosts</a>
35 </li>
36 <li>
37 <a class="ws" ng-click="modal.setTargets(false, 0, 0)">Clear selection</a>
38 </li>
39 </ul>
40 </div><!-- .btn-group -->
41 </div>
42 </div>
43 <div class="form-group">
44 <div class="col-md-12">
1945 <uib-accordion close-others="true">
20 <uib-accordion-group is-open="isopen" ng-repeat="host in modal.targets_filtered = (modal.targets | filter:modal.target_filter) | startFrom:modal.currentPage*modal.pageSize | limitTo:modal.pageSize">
21 <uib-accordion-heading>
22 <a ng-click="modal.setTarget(host)" ng-class="{'multi-selected': host.selected_modalNewCtrl == true}">{{host.name}} ({{host.hostnames[0]}})</a>
23 <i class="pull-right glyphicon"
24 ng-class="{'glyphicon glyphicon-minus-sign': isopen, 'glyphicon glyphicon-plus-sign': !isopen}"></i>
25 </uib-accordion-heading>
26 <div class="panel-body" ng-repeat="service in host.services">
27 <a ng-model="service" ng-click="modal.setTarget(service)" ng-class="{'multi-selected': service.selected_modalNewCtrl == true}">{{service.name}} {{service.ports}}</a>
28 </div>
46 <uib-accordion-group is-open="isopen" ng-repeat="host in modal.targets_filtered = (modal.targets | filter:modal.target_filter) | startFrom:modal.currentPage*modal.pageSize | limitTo:modal.pageSize" template-url="scripts/statusReport/partials/accordion-group.html" is-disabled="host.services.length < 1">
47 <uib-accordion-heading>
48 <a ng-click="modal.setTarget(host)" ng-class="{'multi-selected': modal.data.parents.indexOf(host) >= 0}">{{host.name}} ({{host.hostnames[0]}})</a>
49 </uib-accordion-heading>
50 <div class="panel-body" ng-repeat="service in host.services">
51 <a ng-model="service" ng-click="modal.setTarget(service)" ng-class="{'multi-selected': modal.data.parents.indexOf(service) >= 0}">{{service.name}} {{service.ports}}</a>
52 </div>
2953 </uib-accordion-group>
3054 </uib-accordion>
3155 <div class="showPagination" ng-show="modal.targets_filtered.length > modal.pageSize">
3256 <div class="form-group">
3357 <ul class="pagination">
3458 <li><a ng-hide="modal.currentPage <= 0" ng-click="modal.currentPage = modal.currentPage - 1"><span aria-hidden="true">&laquo;</span><span class="sr-only">Previous</span></a></li>
35 <li><a>{{modal.currentPage}}/{{ ((modal.targets_filtered.length / modal.pageSize) | integer)}}</a></li>
59 <li><a>{{modal.currentPage+1}}/{{ ((modal.targets_filtered.length / modal.pageSize) | integer) + 1}}</a></li>
3660 <li><a ng-hide="modal.currentPage >= ((modal.targets_filtered.length / modal.pageSize) | integer)" ng-click="modal.currentPage = modal.currentPage + 1"><span aria-hidden="true">&raquo;</span><span class="sr-only">Next</span></a></li>
3761 </ul>
3862 <ng-form name="goToPage">
4569 </div>
4670 </div>
4771 </div>
48 </div>
49
50 <div class="alert alert-danger target_not_selected" role="alert" ng-hide="modal.data.parent != undefined">
51 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
52 <span class="sr-only">Error:</span>
53 There is no target selected
54 </div>
55 <div class="alert alert-danger target_not_selected" role="alert" ng-show="modal.data.type === 'VulnerabilityWeb' && modal.data.parent.type === 'Host'">
56 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
57 <span class="sr-only">Error:</span>
58 Vulnerability incompatible with host target, please select a service
59 </div>
72 <div class="alert alert-danger target_not_selected" role="alert" ng-hide="modal.data.parents.length > 0">
73 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
74 <span class="sr-only">Error:</span>
75 There is no target selected
76 </div>
77 <div class="alert alert-danger target_not_selected" role="alert" ng-show="modal.data.type === 'VulnerabilityWeb' && modal.host_parents">
78 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
79 <span class="sr-only">Error:</span>
80 Trying to create a Web Vulnerability with one or more Host parents. Please deselect the Host targets or <a href="" ng-click="modal.resetTarget()">click here to deselect all targets</a>
81 </div>
82 </div>
83
6084 <div class="form-horizontal">
6185 <div class="form-group">
6286 <div class="col-md-12">
63 <h5>Search vulnerability database templates <a href="https://github.com/infobyte/faraday/wiki/vulnerabilities-database" target="_blank"><span class="glyphicon glyphicon-question-sign" title="Read more about vulnerability templates in Faraday Documentation"></span></a></h5>
87 <h5>Search vulnerability database templates <a href="https://github.com/infobyte/faraday/wiki/vulnerabilities-database" target="_blank"><span class="glyphicon glyphicon-question-sign" title="Read more about vulnerability templates in the official Faraday Documentation"></span></a></h5>
6488 <input type="text" ng-model="modal.cwe_selected" class="form-control input-sm" placeholder="Search for vulnerability templates" uib-typeahead="cwe as cwe.name for cwe in modal.cweList | filter:{name: $viewValue} | limitTo:10" typeahead-on-select="modal.populate($item, $model, $label)">
6589 </div>
6690 </div>
115139 <div class="col-md-12 reference" ng-repeat="reference in modal.data.refs">
116140 <div class="input-group margin-bottom-sm">
117141 <label class="sr-only" for="vuln-refs">References</label>
118 <input type="text" class="form-control" id="vuln-refs" placeholder="Reference" ng-model="reference.value"/>
142 <input type="text" class="form-control" id="vuln-refs" placeholder="Reference" ng-model="reference.value" disabled/>
119143 <span class="input-group-addon cursor" ng-click="modal.data.refs.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
120144 </div>
121145 </div>
124148 <div class="col-md-12">
125149 <label class="sr-only" for="vuln-resolution">Vuln Resolution</label>
126150 <textarea class="form-control" id="vuln-resolution" placeholder="Resolution" ng-model="modal.data.resolution"></textarea>
151 </div>
152 </div><!-- .form-group -->
153 <div class="form-group">
154 <div class="col-md-12">
155 <div class="input-group margin-bottom-sm">
156 <label class="sr-only" for="vuln-policyviolations">Policy Violations</label>
157 <input type="text" class="form-control" id="vuln-policyviolations" placeholder="Policy Violations" ng-model="modal.new_policyviolation"/>
158 <span class="input-group-addon cursor" ng-click="modal.newPolicyViolation()"><i class="fa fa-plus-circle"></i></span>
159 </div>
160 </div>
161 <div class="col-md-12 reference" ng-repeat="policyviolation in modal.data.policyviolations">
162 <div class="input-group margin-bottom-sm">
163 <label class="sr-only" for="vuln-policyviolations">Policy Violation</label>
164 <input type="text" class="form-control" id="vuln-policyviolations" placeholder="Policy Violation" ng-model="policyviolation.value" disabled/>
165 <span class="input-group-addon cursor" ng-click="modal.data.policyviolations.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
166 </div>
127167 </div>
128168 </div><!-- .form-group -->
129169 </div>
208248 </div><!-- .modal-body -->
209249 <div class="modal-footer">
210250 <div class="modal-button">
211 <button class="btn btn-success" ng-click="modal.ok()" ng-disabled="form.$invalid || modal.data.severity === undefined">OK</button>
251 <button class="btn btn-success" ng-click="modal.ok()" ng-disabled="form.$invalid || modal.data.severity === undefined || (modal.data.type === 'VulnerabilityWeb' && modal.host_parents)">OK</button>
212252 <button class="btn btn-danger" ng-click="modal.cancel()">Cancel</button>
213253 </div>
214254 </div>
5858 <li><a class="ws" ng-click="editReferences()">Add references</a></li>
5959 <li><a class="ws" ng-click="editImpact()">Edit impact</a></li>
6060 <li><a class="ws" ng-click="editStatus()">Edit status</a></li>
61 <li><a class="ws" ng-click="editPolicyviolations()">Edit policy violations</a></li>
6162 <li><a class="ws" ng-click="editConfirm()">Confirm/Change to false positive</a></li>
6263 <li ng-show="vulnWebSelected" role="separator" class="divider"></li>
6364 <li ng-show="vulnWebSelected"><a class="ws" ng-click="editString('method')">Edit method</a></li>
0 <div ng-if="row.entity._id != undefined">
1 <div class="ui-grid-cell-contents center overflow-cell">
2 <p ng-repeat="policyviolation in COL_FIELD" class='pos-middle crop-text'><a href='{{grid.appScope.processReference(policyviolation)}}' target="_blank">{{policyviolation}}</a></p>
3 </div>
4 </div>
5 <div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{COL_FIELD.split('(')[0] !== ' ' ? COL_FIELD : 'EMPTY' + COL_FIELD}}</div>
4444 this.type = "Vulnerability";
4545 this.ws = "";
4646 this.status = "opened";
47 this.policyviolations = "";
4748
4849 if(data) {
4950 if(data.name === undefined || data.name === "") {
5455 };
5556
5657 var public_properties = [
57 '_attachments', 'confirmed', 'data', 'desc', 'easeofresolution',
58 'impact', 'name', 'owned', 'refs', 'resolution', 'severity',
59 'status',
58 '_attachments', 'confirmed', 'data', 'desc', 'easeofresolution',
59 'impact', 'name', 'owned', 'policyviolations', 'refs', 'resolution',
60 'severity', 'status',
6061 ];
6162
6263 var saved_properties = public_properties.concat(
8586
8687 if(data.owner !== undefined) self.owner = data.owner;
8788 self.ws = ws;
88 if(data.parent !== undefined) self.parent = data.parent;
89 if(data.parent !== undefined) self.parent = data.parent;
8990
9091 self.public_properties.forEach(function(property) {
9192 if(data[property] !== undefined) self[property] = data[property];
88 var vulnsManager = {};
99
1010 vulnsManager.createVuln = function(ws, data) {
11 if(data.type == "Vulnerability") {
12 var vuln = new Vuln(ws, data);
13 } else {
14 var vuln = new WebVuln(ws, data);
15 }
11 var parents = data.parents,
12 promises = [];
1613
17 return vuln.save();
14 delete data.parents;
15
16 parents.forEach(function(parent_id) {
17 data.parent = parent_id;
18
19 if(data.type == "Vulnerability") {
20 var vuln = new Vuln(ws, data);
21 } else {
22 var vuln = new WebVuln(ws, data);
23 }
24
25 promises.push(vuln.save());
26 });
27
28 return $q.all(promises);
1829 };
1930
2031 vulnsManager.deleteVuln = function(vuln) {
44 See the file 'doc/LICENSE' for the license information
55
66 '''
7 from model.hosts import Host, Interface, Service, ModelObjectVuln
7 from server.models import Host, Interface, Service, Vulnerability
88 import random
99 def new_random_workspace_name():
1010 return ("aworkspace" + "".join(random.sample([chr(i) for i in range(65, 90)
2727 return service
2828
2929 def create_host_vuln(self, host, name, desc, severity):
30 vuln = ModelObjectVuln(name, desc, severity)
30 vuln = Vulnerability(name, desc, severity)
3131 self.model_controller.addVulnToHostSYNC(host.getID(), vuln)
3232
3333 return vuln
3434
3535 def create_int_vuln(self, host, interface, name, desc, severity):
36 vuln = ModelObjectVuln(name, desc, severity)
36 vuln = Vulnerability(name, desc, severity)
3737 self.model_controller.addVulnToInterfaceSYNC( host.getID(), interface.getID(), vuln)
3838
3939 return vuln
4040
4141 def create_serv_vuln(self, host, service, name, desc, severity):
42 vuln = ModelObjectVuln(name, desc, severity)
42 vuln = Vulnerability(name, desc, severity)
4343 self.model_controller.addVulnToServiceSYNC( host.getID(), service.getID(), vuln)
4444
4545 return vuln
1212 import os
1313 sys.path.append(os.path.abspath(os.getcwd()))
1414 from plugins.repo.acunetix.plugin import AcunetixPlugin
15 from model.common import (
16 factory, ModelObjectVuln, ModelObjectCred,
17 ModelObjectVulnWeb, ModelObjectNote
18 )
19 from model.hosts import (
20 Host, Service, Interface
15 from model.common import factory
16 from persistence.server.models import (
17 Vuln,
18 Credential,
19 VulnWeb,
20 Note,
21 Host,
22 Service,
23 Interface
2124 )
2225 from plugins.modelactions import modelactions
2326
3134 factory.register(Host)
3235 factory.register(Interface)
3336 factory.register(Service)
34 factory.register(ModelObjectVuln)
35 factory.register(ModelObjectVulnWeb)
36 factory.register(ModelObjectNote)
37 factory.register(ModelObjectCred)
37 factory.register(Vuln)
38 factory.register(VulnWeb)
39 factory.register(Note)
40 factory.register(Credential)
3841
3942 def test_Plugin_creates_apropiate_objects(self):
4043 self.plugin.processReport(self.cd + '/acunetix_xml')
4144 action = self.plugin._pending_actions.get(block=True)
42 self.assertEqual(action[0], modelactions.CADDHOST)
43 self.assertEqual(action[1], "87.230.29.167")
45 self.assertEqual(action[0], modelactions.ADDHOST)
46 self.assertEqual(action[1].name, "5.175.17.140")
4447 action = self.plugin._pending_actions.get(block=True)
45 self.assertEqual(action[0], modelactions.CADDINTERFACE)
46 self.assertEqual(action[2], "87.230.29.167")
48 self.assertEqual(action[0], modelactions.ADDINTERFACE)
49 self.assertEqual(action[2].name, "5.175.17.140")
4750 action = self.plugin._pending_actions.get(block=True)
48 self.assertEqual(action[0], modelactions.CADDSERVICEINT)
49 self.assertEqual(action[5], ['80'])
50 self.assertEqual(action[3], 'http')
51 self.assertEqual(action[4], 'tcp')
51 self.assertEqual(action[0], modelactions.ADDSERVICEINT)
52 self.assertEqual(action[3].ports, [80])
53 self.assertEqual(action[3].name, 'http')
54 self.assertEqual(action[3].protocol, 'tcp')
5255 action = self.plugin._pending_actions.get(block=True)
53 self.assertEqual(action[0], modelactions.CADDNOTESRV)
56 self.assertEqual(action[0], modelactions.ADDNOTESRV)
5457 action = self.plugin._pending_actions.get(block=True)
5558 action = self.plugin._pending_actions.get(block=True)
56 self.assertEqual(action[0], modelactions.CADDVULNWEBSRV)
57 self.assertEqual(action[3], "ASP.NET error message")
59 self.assertEqual(action[0], modelactions.ADDVULNWEBSRV)
60 self.assertEqual(action[3].name, "ASP.NET error message")
61
5862
5963 if __name__ == '__main__':
6064 unittest.main()
1212 import os
1313 sys.path.append(os.path.abspath(os.getcwd()))
1414 from plugins.repo.burp.plugin import BurpPlugin
15 from model.common import (
16 factory, ModelObjectVuln, ModelObjectCred,
17 ModelObjectVulnWeb, ModelObjectNote
18 )
19 from model.hosts import (
20 Host, Service, Interface
15 from model.common import factory
16 from persistence.server.models import (
17 Vuln,
18 VulnWeb,
19 Credential,
20 Note,
21 Host,
22 Service,
23 Interface
2124 )
2225 from plugins.modelactions import modelactions
2326 import test_common
3235 factory.register(Host)
3336 factory.register(Interface)
3437 factory.register(Service)
35 factory.register(ModelObjectVuln)
36 factory.register(ModelObjectVulnWeb)
37 factory.register(ModelObjectNote)
38 factory.register(ModelObjectCred)
38 factory.register(Vuln)
39 factory.register(VulnWeb)
40 factory.register(Note)
41 factory.register(Credential)
3942
4043 def test_Plugin_creates_adecuate_objects(self):
4144 self.plugin.processReport(self.cd + '/burp_xml')
4245 action = self.plugin._pending_actions.get(block=True)
43 self.assertEqual(action[0], modelactions.CADDHOST)
44 self.assertEqual(action[1], "200.20.20.201")
46 self.assertEqual(action[0], modelactions.ADDHOST)
47 self.assertEqual(action[1].name, "200.20.20.201")
4548 action = self.plugin._pending_actions.get(block=True)
46 self.assertEqual(action[0], modelactions.CADDINTERFACE)
47 self.assertEqual(action[2], "200.20.20.201")
49 self.assertEqual(action[0], modelactions.ADDINTERFACE)
50 self.assertEqual(action[2].name, "200.20.20.201")
4851 action = self.plugin._pending_actions.get(block=True)
49 self.assertEqual(action[0], modelactions.CADDSERVICEINT)
50 self.assertEqual(action[3], 'http')
51 self.assertEqual(action[4], 'tcp')
52 self.assertEqual(action[5], ['80'])
53 self.assertEqual(action[6], 'open')
54 test_common.skip(self, 2)
52 self.assertEqual(action[0], modelactions.ADDSERVICEINT)
53 self.assertEqual(action[3].name, 'http')
54 self.assertEqual(action[3].protocol, 'tcp')
55 self.assertEqual(action[3].ports, [80])
56 self.assertEqual(action[3].status, 'open')
5557 action = self.plugin._pending_actions.get(block=True)
56 self.assertEqual(action[0], modelactions.CADDVULNWEBSRV)
57 self.assertEqual(action[3], 'Cleartext submission of password')
58 self.assertEqual(action[0], modelactions.ADDNOTESRV)
59 # TODO: Fix broken test
60 # self.assertEqual(action[3], 'Cleartext submission of password')
5861
5962 if __name__ == '__main__':
6063 unittest.main()
1212 import os
1313 sys.path.append(os.path.abspath(os.getcwd()))
1414 from plugins.repo.nessus.plugin import NessusPlugin
15 from model.common import (
16 factory, ModelObjectVuln, ModelObjectCred,
17 ModelObjectVulnWeb, ModelObjectNote
18 )
19 from model.hosts import (
20 Host, Service, Interface
15 from model.common import factory
16 from persistence.server.models import (
17 Vuln,
18 Credential,
19 VulnWeb,
20 Note,
21 Host,
22 Service,
23 Interface
2124 )
2225 from plugins.modelactions import modelactions
2326 import test_common
27
2428
2529 class NessusParserTest(unittest.TestCase):
2630 cd = os.path.dirname(os.path.realpath(__file__))
3034 factory.register(Host)
3135 factory.register(Interface)
3236 factory.register(Service)
33 factory.register(ModelObjectVuln)
34 factory.register(ModelObjectVulnWeb)
35 factory.register(ModelObjectNote)
36 factory.register(ModelObjectCred)
37 factory.register(Vuln)
38 factory.register(VulnWeb)
39 factory.register(Note)
40 factory.register(Credential)
3741
3842 def test_Plugin_Calls_createAndAddHost(self):
3943 self.plugin.processReport(self.cd + '/nessus_xml')
4044 action = self.plugin._pending_actions.get(block=True)
41 self.assertEqual(action[0], modelactions.CADDHOST)
42 self.assertEqual(action[1], "12.233.108.201")
45 self.assertEqual(action[0], modelactions.ADDHOST)
46 self.assertEqual(action[1].name, "12.233.108.201")
4347 action = self.plugin._pending_actions.get(block=True)
44 self.assertEqual(action[0], modelactions.CADDINTERFACE)
45 self.assertEqual(action[2], "12.233.108.201")
48 self.assertEqual(action[0], modelactions.ADDINTERFACE)
49 self.assertEqual(action[2].name, "12.233.108.201")
4650 action = self.plugin._pending_actions.get(block=True)
47 self.assertEqual(action[0], modelactions.CADDVULNHOST)
48 self.assertEqual(action[2], "Nessus Scan Information")
51 self.assertEqual(action[0], modelactions.ADDVULNHOST)
52 self.assertEqual(action[2].name, "Nessus Scan Information")
4953 test_common.skip(self, 4)
5054 action = self.plugin._pending_actions.get(block=True)
51 self.assertEqual(action[0], modelactions.CADDSERVICEINT)
52 self.assertEqual(action[5], ['443'])
53 self.assertEqual(action[3], 'https?')
54 self.assertEqual(action[4], 'tcp')
55 self.assertEqual(action[0], modelactions.ADDSERVICEINT)
56 self.assertEqual(action[3].ports, [443])
57 self.assertEqual(action[3].name, 'https?')
58 self.assertEqual(action[3].protocol, 'tcp')
59
5560
5661 if __name__ == '__main__':
5762 unittest.main()
1515 import importlib
1616 plugin = importlib.import_module('plugins.repo.nexpose-full.plugin')
1717 NexposeFullPlugin = plugin.NexposeFullPlugin
18 from model.common import (
19 factory, ModelObjectVuln, ModelObjectCred,
20 ModelObjectVulnWeb, ModelObjectNote
21 )
22 from model.hosts import (
23 Host, Service, Interface
18 from model.common import factory
19 from persistence.server.models import (
20 Vuln,
21 Credential,
22 VulnWeb,
23 Note,
24 Host,
25 Service,
26 Interface
2427 )
2528 from plugins.modelactions import modelactions
2629
3336 factory.register(Host)
3437 factory.register(Interface)
3538 factory.register(Service)
36 factory.register(ModelObjectVuln)
37 factory.register(ModelObjectVulnWeb)
38 factory.register(ModelObjectNote)
39 factory.register(ModelObjectCred)
39 factory.register(Vuln)
40 factory.register(VulnWeb)
41 factory.register(Note)
42 factory.register(Credential)
4043
4144 def test_Plugin_creates_apropiate_objects(self):
4245 self.plugin.processReport(self.cd + '/nexpose_full_xml')
4346 action = self.plugin._pending_actions.get(block=True)
44 self.assertEqual(action[0], modelactions.CADDHOST)
45 self.assertEqual(action[1], "192.168.1.1")
47 self.assertEqual(action[0], modelactions.ADDHOST)
48 self.assertEqual(action[1].name, "192.168.1.1")
4649 action = self.plugin._pending_actions.get(block=True)
47 self.assertEqual(action[0], modelactions.CADDINTERFACE)
48 self.assertEqual(action[2], "192.168.1.1")
50 self.assertEqual(action[0], modelactions.ADDINTERFACE)
51 self.assertEqual(action[2].name, "192.168.1.1")
4952 for i in range(131):
5053 action = self.plugin._pending_actions.get(block=True)
51 self.assertEqual(action[0], modelactions.CADDVULNHOST)
54 self.assertEqual(action[0], modelactions.ADDVULNHOST)
5255 action = self.plugin._pending_actions.get(block=True)
53 self.assertEqual(action[0], modelactions.CADDSERVICEINT)
56 self.assertEqual(action[0], modelactions.ADDSERVICEINT)
5457 for i in range(15):
5558 action = self.plugin._pending_actions.get(block=True)
56 self.assertEqual(action[0], modelactions.CADDVULNSRV)
59 self.assertEqual(action[0], modelactions.ADDVULNSRV)
60
5761
5862 if __name__ == '__main__':
5963 unittest.main()
1212 import os
1313 sys.path.append(os.path.abspath(os.getcwd()))
1414 from plugins.repo.nmap.plugin import NmapPlugin
15 from model.common import (
16 factory, ModelObjectVuln, ModelObjectCred,
17 ModelObjectVulnWeb, ModelObjectNote
18 )
19 from model.hosts import (
20 Host, Service, Interface
15 from model.common import factory
16 from persistence.server.models import (
17 Vuln,
18 Credential,
19 VulnWeb,
20 Note,
21 Host,
22 Service,
23 Interface
2124 )
2225 from plugins.modelactions import modelactions
2326
5457 factory.register(Host)
5558 factory.register(Interface)
5659 factory.register(Service)
57 factory.register(ModelObjectVuln)
58 factory.register(ModelObjectVulnWeb)
59 factory.register(ModelObjectNote)
60 factory.register(ModelObjectCred)
60 factory.register(Vuln)
61 factory.register(VulnWeb)
62 factory.register(Note)
63 factory.register(Credential)
6164
6265 def test_Plugin_Calls_createAndAddHost(self):
6366 self.plugin.parseOutputString(self.xml_output)
6467 action = self.plugin._pending_actions.get(block=True)
65 self.assertEqual(action[0], modelactions.CADDHOST)
66 self.assertEqual(action[1], "198.38.82.159")
68 self.assertEqual(action[0], modelactions.ADDHOST)
69 self.assertEqual(action[1].name, "198.38.82.159")
6770 action = self.plugin._pending_actions.get(block=True)
68 self.assertEqual(action[0], modelactions.CADDINTERFACE)
69 self.assertEqual(action[2], "198.38.82.159")
71 self.assertEqual(action[0], modelactions.ADDINTERFACE)
72 self.assertEqual(action[2].name, "198.38.82.159")
7073
7174 def test_Plugin_Calls_createAndAddService(self):
7275 self.plugin.parseOutputString(self.xml_output)
7376 action = self.plugin._pending_actions.get(block=True)
74 self.assertEqual(action[0], modelactions.CADDSERVICEINT)
75 self.assertEqual(action[5], ['21'])
76 self.assertEqual(action[3], 'ftp')
77 self.assertEqual(action[4], 'tcp')
7877 action = self.plugin._pending_actions.get(block=True)
79 action = self.plugin._pending_actions.get(block=True)
80 action = self.plugin._pending_actions.get(block=True)
81 self.assertEqual(action[0], modelactions.CADDSERVICEINT)
82 self.assertEqual(action[5], ['80'])
83 self.assertEqual(action[3], 'http')
84 self.assertEqual(action[4], 'tcp')
78 self.assertEqual(action[0], modelactions.ADDSERVICEINT)
79 self.assertEqual(action[3].ports, [25])
80 self.assertEqual(action[3].name, 'smtp')
81 self.assertEqual(action[3].protocol, 'tcp')
8582
8683
8784 if __name__ == '__main__':
1212 import os
1313 sys.path.append(os.path.abspath(os.getcwd()))
1414 from plugins.repo.ping.plugin import CmdPingPlugin
15 from model.common import (
16 factory, ModelObjectVuln, ModelObjectCred,
17 ModelObjectVulnWeb, ModelObjectNote
18 )
19 from model.hosts import (
20 Host, Service, Interface
15 from model.common import factory
16 from persistence.server.models import (
17 Vuln,
18 Credential,
19 VulnWeb,
20 Note,
21 Host,
22 Service,
23 Interface
2124 )
2225 from plugins.modelactions import modelactions
2326
3134 factory.register(Host)
3235 factory.register(Interface)
3336 factory.register(Service)
34 factory.register(ModelObjectVuln)
35 factory.register(ModelObjectVulnWeb)
36 factory.register(ModelObjectNote)
37 factory.register(ModelObjectCred)
37 factory.register(Vuln)
38 factory.register(VulnWeb)
39 factory.register(Note)
40 factory.register(Credential)
3841
3942 def test_Plugin_Calls_createAndAddHost(self):
4043 self.plugin.parseOutputString(self.outputPingGoogle)
4144 action = self.plugin._pending_actions.get(block=True)
42 self.assertEqual(action[0], modelactions.CADDHOST)
43 self.assertEqual(action[1], "216.58.222.142")
45 self.assertEqual(action[0], modelactions.ADDHOST)
46 self.assertEqual(action[1].name, "216.58.222.142")
4447 action = self.plugin._pending_actions.get(block=True)
45 self.assertEqual(action[0], modelactions.CADDINTERFACE)
46 self.assertEqual(action[2], "216.58.222.142")
48 self.assertEqual(action[0], modelactions.ADDINTERFACE)
49 self.assertEqual(action[2].name, "216.58.222.142")
50
4751
4852 if __name__ == '__main__':
4953 unittest.main()
1212 import os
1313 sys.path.append(os.path.abspath(os.getcwd()))
1414 from plugins.repo.telnet.plugin import TelnetRouterPlugin
15 from model.common import (
16 factory, ModelObjectVuln, ModelObjectCred,
17 ModelObjectVulnWeb, ModelObjectNote
18 )
19 from model.hosts import (
20 Host, Service, Interface
15 from model.common import factory
16 from persistence.server.models import (
17 Vuln,
18 Credential,
19 VulnWeb,
20 Note,
21 Host,
22 Service,
23 Interface
2124 )
2225 from plugins.modelactions import modelactions
2326
3942 factory.register(Host)
4043 factory.register(Interface)
4144 factory.register(Service)
42 factory.register(ModelObjectVuln)
43 factory.register(ModelObjectVulnWeb)
44 factory.register(ModelObjectNote)
45 factory.register(ModelObjectCred)
45 factory.register(Vuln)
46 factory.register(VulnWeb)
47 factory.register(Note)
48 factory.register(Credential)
4649
4750 def test_Plugin_Calls_createAndAddHost(self):
4851 self.plugin.parseOutputString(self.outputTelnetLocalhost)
4952 action = self.plugin._pending_actions.get(block=True)
50 self.assertEqual(action[0], modelactions.CADDHOST)
51 self.assertEqual(action[1], "127.0.0.1")
53 self.assertEqual(action[0], modelactions.ADDHOST)
54 self.assertEqual(action[1].name, "127.0.0.1")
5255 action = self.plugin._pending_actions.get(block=True)
53 self.assertEqual(action[0], modelactions.CADDINTERFACE)
54 self.assertEqual(action[2], "127.0.0.1")
56 self.assertEqual(action[0], modelactions.ADDINTERFACE)
57 self.assertEqual(action[2].name, "127.0.0.1")
58
5559
5660 if __name__ == '__main__':
5761 unittest.main()
1212 import os
1313 sys.path.append(os.path.abspath(os.getcwd()))
1414 from plugins.repo.whois.plugin import CmdWhoisPlugin
15 from model.common import (
16 factory, ModelObjectVuln, ModelObjectCred,
17 ModelObjectVulnWeb, ModelObjectNote
18 )
19 from model.hosts import (
20 Host, Service, Interface
15 from model.common import factory
16 from persistence.server.models import (
17 Vuln,
18 Credential,
19 VulnWeb,
20 Note,
21 Host,
22 Service,
23 Interface
2124 )
2225 from plugins.modelactions import modelactions
2326
3235 factory.register(Host)
3336 factory.register(Interface)
3437 factory.register(Service)
35 factory.register(ModelObjectVuln)
36 factory.register(ModelObjectVulnWeb)
37 factory.register(ModelObjectNote)
38 factory.register(ModelObjectCred)
38 factory.register(Vuln)
39 factory.register(VulnWeb)
40 factory.register(Note)
41 factory.register(Credential)
3942
4043 def test_Plugin_Calls_createAndAddHost(self):
4144 self.plugin.parseOutputString(self.outputWhoisInfobyte)
4245 action = self.plugin._pending_actions.get(block=True)
43 self.assertEqual(action[0], modelactions.CADDHOST)
44 self.assertEqual(action[1], "205.251.196.172")
46 self.assertEqual(action[0], modelactions.ADDHOST)
47 self.assertEqual(action[1].name, "205.251.196.172")
4548 action = self.plugin._pending_actions.get(block=True)
46 self.assertEqual(action[0], modelactions.CADDINTERFACE)
47 self.assertEqual(action[2], "205.251.196.172")
49 self.assertEqual(action[0], modelactions.ADDINTERFACE)
50 self.assertEqual(action[2].name, "205.251.196.172")
51
4852
4953 if __name__ == '__main__':
5054 unittest.main()
0 import os
1 import sys
2 import unittest
3
04 import responses
15 import requests
2 import unittest
6 sys.path.append(os.path.abspath(os.getcwd()))
37 from persistence.server import server
48 from persistence.server import server_io_exceptions
59 from mock import MagicMock, patch
711 server.FARADAY_UP = False
812 server.SERVER_URL = "http://s:p"
913 example_url = "http://just_some_url"
14
15
1016 class ClientServerAPITests(unittest.TestCase):
1117
1218 def setUp(self):
99 "confidentiality": false,
1010 "integrity": false
1111 },
12 policyviolations = [],
1213 resolution = "",
1314 confirmed = false;
1415 if(doc.easeofresolution !== undefined) {
1617 }
1718 if(doc.impact !== undefined) {
1819 impact = doc.impact;
20 }
21 if(doc.policyviolations !== undefined) {
22 policyviolations = doc.policyviolations;
1923 }
2024 if(doc.resolution !== undefined) {
2125 resolution = doc.resolution;
2731 "_attachments": doc._attachments,
2832 "confirmed": doc.confirmed || confirmed,
2933 "data": doc.data,
30 "desc": doc.desc,
34 "desc": doc.desc,
3135 "easeofresolution": easeofresolution,
3236 "impact": impact,
3337 "metadata": doc.metadata,
34 "name": doc.name,
38 "name": doc.name,
3539 "obj_id": doc.obj_id,
3640 "owned": doc.owned,
3741 "owner": doc.owner,
38 "parent": doc.parent,
42 "parent": doc.parent,
43 "policyviolations": policyviolations,
3944 "refs": doc.refs,
4045 "resolution": resolution,
41 "severity": doc.severity,
42 "type": doc.type,
46 "severity": doc.severity,
47 "type": doc.type
4348 };
4449
4550 if(doc.type == "VulnerabilityWeb") {