1
2
3 __docformat__ = 'restructuredtext'
4 __version__ = '$Id$'
5
6 import __builtin__
7 from routerdefense.common import *
8
9 from xml import *
10
12 """BGP configuration assessment."""
13
14 if search_string(lines, 'router bgp') is None:
15 return
16
17 remoteAsCount = 0
18 ttl_securityCount = 0
19 session_passwordCount = 0
20 max_prefixesCount = 0
21 prefix_listInCount = 0
22 prefix_listOutCount = 0
23 aspath_listInCount = 0
24 aspath_listOutCount = 0
25 maxaspathLimit = 0
26
27 remoteAsCount = search_re_string_count(lines, 'neighbor .* remote-as .*')
28 ttl_securityCount = search_re_string_count(lines, 'neighbor .* ttl-security hops .*')
29 session_passwordCount = search_re_string_count(lines, 'neighbor .* password .*')
30 max_prefixesCount = search_re_string_count(lines, 'neighbor .* maximum-prefix .*')
31 prefix_listInCount = search_re_string_count(lines, 'neighbor .* prefix-list .* in')
32 prefix_listOutCount = search_re_string_count(lines, 'neighbor .* prefix-list .* out')
33 aspath_listInCount = search_re_string_count(lines, 'neighbor .* filter-list .* in')
34 aspath_listOutCount = search_re_string_count(lines, 'neighbor .* filter-list .* out')
35 maxaspathLimit = search_re_string_count(lines, '^bgp maxas-limit .*$')
36
37 if ttl_securityCount < remoteAsCount:
38 bgp.ttl_security['must_report'] = True
39
40 if session_passwordCount < remoteAsCount:
41 bgp.session_password['must_report'] = True
42
43 if max_prefixesCount < remoteAsCount:
44 bgp.max_prefixes['must_report'] = True
45
46 if prefix_listInCount < remoteAsCount:
47 bgp.prefix_list['must_report'] = True
48
49 if prefix_listOutCount < remoteAsCount:
50 bgp.prefix_list['must_report'] = True
51
52 if aspath_listInCount < remoteAsCount:
53 bgp.aspath_list['must_report'] = True
54
55 if aspath_listOutCount < remoteAsCount:
56 bgp.aspath_list['must_report'] = True
57
58 if maxaspathLimit <= 0:
59 bgp.maxpath_limit['must_report'] = True
60
61 if bgp.ttl_security['must_report'] == True:
62 items = search_xml('bgpTTLsecurity')
63 cvssMetrics = str(cvss_score(items[5]))
64 bgp.ttl_security = {
65 "must_report": True,
66 "fixImpact": (items[0]),
67 "definition": (items[1]),
68 "threatInfo": (items[2]),
69 "howtofix": (items[3]),
70 "cvss": (cvssMetrics)}
71
72 if bgp.session_password['must_report'] == True:
73 items = search_xml('bgpSessionPassword')
74 cvssMetrics = str(cvss_score(items[5]))
75 bgp.session_password = {
76 "must_report": True,
77 "fixImpact": (items[0]),
78 "definition": (items[1]),
79 "threatInfo": (items[2]),
80 "howtofix": (items[3]),
81 "cvss": (cvssMetrics)}
82
83 if bgp.max_prefixes['must_report'] == True:
84 items = search_xml('bgpMaxPrefixes')
85 cvssMetrics = str(cvss_score(items[5]))
86 bgp.max_prefixes = {
87 "must_report": True,
88 "fixImpact": (items[0]),
89 "definition": (items[1]),
90 "threatInfo": (items[2]),
91 "howtofix": (items[3]),
92 "cvss": (cvssMetrics)}
93
94 if bgp.prefix_list['must_report'] == True:
95 items = search_xml('bgpPrefixList')
96 cvssMetrics = str(cvss_score(items[5]))
97 bgp.prefix_list = {
98 "must_report": True,
99 "fixImpact": (items[0]),
100 "definition": (items[1]),
101 "threatInfo": (items[2]),
102 "howtofix": (items[3]),
103 "cvss": (cvssMetrics)}
104
105 if bgp.aspath_list['must_report'] == True:
106 items = search_xml('bgpaspathList')
107 cvssMetrics = str(cvss_score(items[5]))
108 bgp.aspath_list = {
109 "must_report": True,
110 "fixImpact": (items[0]),
111 "definition": (items[1]),
112 "threatInfo": (items[2]),
113 "howtofix": (items[3]),
114 "cvss": (cvssMetrics)}
115
116 if bgp.maxpath_limit['must_report'] == True:
117 items = search_xml('bgpMaxASlimit')
118 cvssMetrics = str(cvss_score(items[5]))
119 bgp.maxpath_limit = {
120 "must_report": True,
121 "fixImpact": (items[0]),
122 "definition": (items[1]),
123 "threatInfo": (items[2]),
124 "howtofix": (items[3]),
125 "cvss": (cvssMetrics)}
126
127 toBeReturned = ''
128 if bgp.ttl_security['must_report'] == True:
129 toBeReturned = bgp.ttl_security['definition'] + '\n'+ bgp.ttl_security['threatInfo'] + '\n\n' + bgp.ttl_security['howtofix'] + '\n'
130 if bgp.session_password['must_report'] == True:
131 toBeReturned = toBeReturned + bgp.session_password['definition'] + '\n' + bgp.session_password['threatInfo'] + '\n\n' + bgp.session_password['howtofix'] + '\n'
132 if bgp.max_prefixes['must_report'] == True:
133 toBeReturned = toBeReturned + bgp.max_prefixes['definition'] + '\n' + bgp.max_prefixes['threatInfo'] + '\n\n' + bgp.max_prefixes['howtofix'] + '\n'
134 if bgp.prefix_list['must_report'] == True:
135 toBeReturned = toBeReturned + bgp.prefix_list['definition'] + '\n' + bgp.prefix_list['threatInfo'] + '\n\n' + bgp.prefix_list['howtofix'] + '\n'
136 if bgp.aspath_list['must_report'] == True:
137 toBeReturned = toBeReturned + bgp.aspath_list['definition'] + '\n' + bgp.aspath_list['threatInfo'] + '\n\n' + bgp.aspath_list['howtofix'] + '\n'
138 if bgp.maxpath_limit['must_report'] == True:
139 toBeReturned = toBeReturned + bgp.maxpath_limit['definition'] + '\n' + bgp.maxpath_limit['threatInfo'] + '\n\n' + bgp.maxpath_limit['howtofix'] + '\n'
140
141 return toBeReturned
142
144 """EIGRP configuration assessment."""
145
146 if search_string(lines, 'router eigrp') is None:
147 return
148 auth_md5 = None
149 eigrpInstances = 0
150 eigrpInstances = search_string_count(lines, 'router eigrp')
151 if eigrpInstances != 0:
152 for i,v in enumerate(lines):
153 if v.rfind('router eigrp') != -1:
154 eigrp.asNumber.append(v.split(' ')[2])
155 eigrpLines= []
156 lineEigrpLocation = i
157 eigrpLines.append(stripping(lines[i]))
158 for j in range(lineEigrpLocation + 1, len(lines)):
159 if lines[j].startswith(" ") or not lines[j].startswith("!"):
160 eigrpLines.append(stripping(lines[j]))
161 else:
162 break
163 try:
164 eigrp.passive['cmdInCfg'] = search_string(eigrpLines, 'passive-interface default')
165 except AttributeError:
166 pass
167 try:
168 eigrp.rfilter_in['cmdInCfg'] = search_re_string(eigrpLines, 'distribute-list prefix .* in .*')
169 except AttributeError:
170 pass
171 try:
172 eigrp.rfilter_out['cmdInCfg'] = search_re_string(eigrpLines, 'distribute-list prefix .* out .*')
173 except AttributeError:
174 pass
175
176 for line in eigrpLines:
177 if line.find('no passive-interface') != -1:
178 eigrp.activeIfaces.append(line.split(' ')[2])
179
180 if ( (eigrp.passive['cmdInCfg'] is None) ):
181 eigrp.passive['asn'].append(v.split(' ')[2].strip())
182 eigrp.passive['must_report'] = True
183
184 if ( (eigrp.rfilter_in['cmdInCfg'] is None) ):
185 eigrp.rfilter_in['asn'].append(v.split(' ')[2].strip())
186 eigrp.rfilter_in['must_report'] = True
187
188 if ( (eigrp.rfilter_out['cmdInCfg'] is None) ):
189 eigrp.rfilter_out['asn'].append(v.split(' ')[2].strip())
190 eigrp.rfilter_out['must_report'] = True
191
192 for ifaceName in eigrp.activeIfaces:
193 for index in range(0, len(ifaceCfg)):
194 if ifaceCfg[index].name.strip() == ifaceName.strip():
195 auth_md5 = search_re_string(ifaceCfg[index].configuration, 'ip authentication mode eigrp .* md5')
196 if auth_md5 is None:
197 eigrp.auth_md5['interfaces'].append(ifaceName.strip())
198 eigrp.auth_md5['asn'].append(v.split(' ')[2].strip())
199 eigrp.auth_md5['must_report'] = True
200
201 if eigrp.passive['must_report'] == True:
202 items = search_xml('eigrpPassiveDefault')
203 cvssMetrics = str(cvss_score(items[5]))
204 eigrp.passive = {
205 "must_report": True,
206 "asn": eigrp.passive['asn'],
207 "fixImpact": (items[0]),
208 "definition": (items[1]),
209 "threatInfo": (items[2]),
210 "howtofix": (items[3]),
211 "cvss": (cvssMetrics)}
212
213 if eigrp.auth_md5['must_report'] == True:
214 items = search_xml('eigrpAuthModeMD5')
215 cvssMetrics = str(cvss_score(items[5]))
216 eigrp.auth_md5 = {
217 "must_report": True,
218 "interfaces": eigrp.auth_md5['interfaces'],
219 "asn": eigrp.auth_md5['asn'],
220 "fixImpact": (items[0]),
221 "definition": (items[1]),
222 "threatInfo": (items[2]),
223 "howtofix": (items[3]),
224 "cvss": (cvssMetrics)}
225
226 if eigrp.rfilter_in['must_report'] == True:
227 items = search_xml('eigrpRouteFilteringIn')
228 cvssMetrics = str(cvss_score(items[5]))
229 eigrp.rfilter_in = {
230 "must_report": True,
231 "asn": eigrp.rfilter_in['asn'],
232 "fixImpact": (items[0]),
233 "definition": (items[1]),
234 "threatInfo": (items[2]),
235 "howtofix": (items[3]),
236 "cvss": (cvssMetrics)}
237
238 if eigrp.rfilter_out['must_report'] == True:
239 items = search_xml('eigrpRouteFilteringOut')
240 cvssMetrics = str(cvss_score(items[5]))
241 eigrp.rfilter_out = {
242 "must_report": True,
243 "asn": eigrp.rfilter_out['asn'],
244 "fixImpact": (items[0]),
245 "definition": (items[1]),
246 "threatInfo": (items[2]),
247 "howtofix": (items[3]),
248 "cvss": (cvssMetrics)}
249
250 toBeReturned = ''
251 if eigrp.passive['must_report'] == True:
252 toBeReturned = eigrp.passive['definition'] + '\n' + eigrp.passive['threatInfo'] + '\n\n' + eigrp.passive['howtofix'] + '\n'
253 if eigrp.auth_md5['must_report'] == True:
254 toBeReturned = toBeReturned + eigrp.auth_md5['definition'] + '\n' + eigrp.auth_md5['threatInfo'] + '\n\n' + eigrp.auth_md5['howtofix'] + '\n'
255 if eigrp.rfilter_in['must_report'] == True:
256 toBeReturned = toBeReturned + eigrp.rfilter_in['definition'] + '\n' + eigrp.rfilter_in['threatInfo'] + '\n\n' + eigrp.rfilter_in['howtofix'] + '\n'
257 if eigrp.rfilter_out['must_report'] == True:
258 toBeReturned = toBeReturned + eigrp.rfilter_out['definition'] + '\n' + eigrp.rfilter_out['threatInfo'] + '\n\n' + eigrp.rfilter_out['howtofix'] + '\n'
259
260 return toBeReturned
261
263 """RIP configuration assessment."""
264
265 if search_string(lines, 'router rip') is None:
266 return
267 rip.version = 1
268 for i,v in enumerate(lines):
269 if v.rfind('router rip') != -1:
270 ripLines= []
271 lineRipLocation = i
272 ripLines.append(stripping(lines[i]))
273 for j in range(lineRipLocation + 1, len(lines)):
274 if lines[j].startswith(" ") or not lines[j].startswith("!"):
275 ripLines.append(stripping(lines[j]))
276 else:
277 break
278
279 for line in ripLines:
280 if line.find('version 2') != -1:
281 rip.version = 2
282
283 ripMask = None
284 ripMask = search_re_string(ripLines, 'network .* .*')
285 if ripMask is not None:
286 rip.version = 2
287
288 if rip.version == 1:
289 return
290 elif rip.version == 2:
291 ripMD5 = None
292 MD5notFound = False
293 for line in ripLines:
294 if MD5notFound == False:
295 if line.find('network',0, 8) != -1:
296 ripNet =line.split(' ')[1]
297 ifIPmask = None
298 for index in range(0, len(ifaceCfg)):
299 ifIPmask = search_re_string(ifaceCfg[index].configuration, 'ip address .* .*')
300 if ifIPmask is not None:
301 ipTuple = ifIPmask.split(' ')
302 ipAddress = ipTuple[2]
303 Mask = ipTuple[3]
304 if ripNet == network_address(ipAddress, Mask):
305 ripMD5 = search_string(ifaceCfg[index].configuration, 'ip rip authentication mode md5')
306 if ripMD5 is None:
307 MD5notFound = True
308 rip.auth_md5['interfaces'].append(ifaceCfg[index].name.strip())
309 rip.auth_md5['must_report'] = True
310
311 if rip.auth_md5['must_report'] == True:
312 items = search_xml('ripAuthModeMD5')
313 cvssMetrics = str(cvss_score(items[5]))
314 rip.auth_md5 = {
315 "must_report": True,
316 "interfaces": rip.auth_md5['interfaces'],
317 "fixImpact": (items[0]),
318 "definition": (items[1]),
319 "threatInfo": (items[2]),
320 "howtofix": (items[3]),
321 "cvss": (cvssMetrics)}
322
323 toBeReturned = ''
324 if rip.auth_md5['must_report'] == True:
325 toBeReturned = rip.auth_md5['definition'] + '\n' + rip.auth_md5['threatInfo'] + '\n\n' + rip.auth_md5['howtofix'] + '\n'
326
327 return toBeReturned
328
329
331 """"OSPF configuration assessment."""
332
333 if search_string(lines, 'router ospf') is None:
334 return
335 auth_md5 = None
336 ospfInstances = 0
337 ospfInstances = search_string_count(lines, 'router ospf')
338 if ospfInstances != 0:
339 for i,v in enumerate(lines):
340 if v.find('router ospf',0,12) != -1:
341 ospfLines= []
342 lineOspfLocation = i
343 ospfLines.append(stripping(lines[i]))
344 currentPid = ospfLines[0].split(' ')[2]
345 for j in range(lineOspfLocation + 1, len(lines)):
346 if lines[j].startswith(" ") or not lines[j].startswith("!"):
347 ospfLines.append(stripping(lines[j]))
348 else:
349 break
350 try:
351 ospf.passive['cmdInCfg'] = search_string(ospfLines, 'passive-interface default')
352 except AttributeError:
353 pass
354 try:
355 ospf.maxLSA['cmdInCfg'] = search_re_string(ospfLines, 'max-lsa .*')
356 except AttributeError:
357 pass
358
359 if ( (ospf.passive['cmdInCfg'] is None) ):
360 ospf.passive['pid'].append(currentPid)
361 ospf.passive['must_report'] = True
362
363 if ( (ospf.rfilter_in['cmdInCfg'] is None) ):
364 ospf.rfilter_in['pid'].append(currentPid)
365 ospf.rfilter_in['must_report'] = True
366
367 if ( (ospf.rfilter_out['cmdInCfg'] is None) ):
368 ospf.rfilter_out['pid'].append(currentPid)
369 ospf.rfilter_out['must_report'] = True
370
371 if ( (ospf.maxLSA['cmdInCfg'] is None) ):
372 ospf.maxLSA['pid'].append(currentPid)
373 ospf.maxLSA['must_report'] = True
374
375 ospf.area = []
376 for line in ospfLines:
377 if line.find('network',0,8) != -1:
378 if not line.split(' ')[4] in ospf.area:
379 ospf.area.append(line.split(' ')[4])
380
381 for areaNumber in ospf.area:
382 areaDigest = False
383 searchArea = None
384 searchArea = search_re_string(ospfLines,'area .* authentication message-digest')
385 if searchArea is not None:
386 matchArea = searchArea.split(' ')[1]
387 if matchArea == areaNumber:
388 areaDigest = True
389
390 if areaDigest == False:
391 if not areaNumber in ospf.auth_md5['area']:
392 ospf.auth_md5['area'].append(areaNumber)
393 if not currentPid in ospf.auth_md5['pid']:
394 ospf.auth_md5['pid'].append(currentPid)
395 ospf.auth_md5['must_report'] = True
396
397 if ospf.auth_md5['must_report'] == True:
398 for line in ospfLines:
399 if line.find('network',0, 8) != -1:
400 ospfNet =line.split(' ')[1]
401 ifIPmask = None
402 for index in range(0, len(ifaceCfg)):
403 ifIPmask = search_re_string(ifaceCfg[index].configuration, 'ip address .* .*')
404 if ifIPmask is not None:
405 ipTuple = ifIPmask.split(' ')
406 ipAddress = ipTuple[2]
407 Mask = ipTuple[3]
408 if ospfNet == network_address(ipAddress, Mask):
409 ospfMD5 = search_re_string(ifaceCfg[index].configuration, 'ip ospf message-digest-key .* md5 .*')
410 if ospfMD5 is None:
411 ospf.auth_md5['interfaces'].append(ifaceCfg[index].name.strip())
412
413 searchFilterAreaIn = 'area ' + str(areaNumber) + ' filter-list prefix .* in'
414 if search_re_string(ospfLines, searchFilterAreaIn) is None:
415 if not areaNumber in ospf.rfilter_in['area']:
416 ospf.rfilter_in['area'].append(areaNumber)
417
418 searchFilterAreaOut = 'area ' + str(areaNumber) + ' filter-list prefix .* out'
419 if search_re_string(ospfLines, searchFilterAreaOut) is None:
420 if not areaNumber in ospf.rfilter_out['area']:
421 ospf.rfilter_out['area'].append(areaNumber)
422
423
424 if ospf.passive['must_report'] == True:
425 items = search_xml('ospfPassiveDefault')
426 cvssMetrics = str(cvss_score(items[5]))
427 ospf.passive = {
428 "pid": ospf.passive['pid'],
429 "must_report": True,
430 "fixImpact": (items[0]),
431 "definition": (items[1]),
432 "threatInfo": (items[2]),
433 "howtofix": (items[3]),
434 "cvss": (cvssMetrics)}
435
436 if ospf.auth_md5['must_report'] == True:
437 items = search_xml('ospfAuthModeMD5')
438 cvssMetrics = str(cvss_score(items[5]))
439 ospf.auth_md5 = {
440 "must_report": True,
441 "pid": ospf.auth_md5['pid'],
442 "area": ospf.auth_md5['area'],
443 "interfaces": ospf.auth_md5['interfaces'],
444 "fixImpact": (items[0]),
445 "definition": (items[1]),
446 "threatInfo": (items[2]),
447 "howtofix": (items[3].strip() \
448 .replace('[%ospfPID]', "".join(ospf.auth_md5['pid']), 1) \
449 .replace('[%ospfArea]', "".join(ospf.auth_md5['area']), 1) \
450 .replace('[%ospfinterface]', ", ".join(ospf.auth_md5['interfaces']), 1)),
451 "cvss": (cvssMetrics)}
452
453 if ospf.rfilter_in['must_report'] == True:
454 items = search_xml('ospfRouteFilteringIn')
455 cvssMetrics = str(cvss_score(items[5]))
456 ospf.rfilter_in = {
457 "area": ospf.rfilter_in['area'],
458 "pid": ospf.rfilter_in['pid'],
459 "must_report": True,
460 "fixImpact": (items[0]),
461 "definition": (items[1]),
462 "threatInfo": (items[2]),
463 "howtofix": (items[3].strip() \
464 .replace('[%ospfPID]', "".join(ospf.rfilter_in['pid']), 1) \
465 .replace('[%ospfArea]', "".join(ospf.rfilter_in['area']), 1)),
466 "cvss": (cvssMetrics)}
467
468 if ospf.rfilter_out['must_report'] == True:
469 items = search_xml('ospfRouteFilteringOut')
470 cvssMetrics = str(cvss_score(items[5]))
471 ospf.rfilter_out = {
472 "area": ospf.rfilter_out['area'],
473 "pid": ospf.rfilter_out['pid'],
474 "must_report": True,
475 "fixImpact": (items[0]),
476 "definition": (items[1]),
477 "threatInfo": (items[2]),
478 "howtofix": (items[3].strip() \
479 .replace('[%ospfPID]', "".join(ospf.rfilter_out['pid']), 1) \
480 .replace('[%ospfArea]', "".join(ospf.rfilter_out['area']), 1)),
481 "cvss": (cvssMetrics)}
482
483 if ospf.maxLSA['must_report'] == True:
484 items = search_xml('ospfMaxLSA')
485 cvssMetrics = str(cvss_score(items[5]))
486 ospf.maxLSA = {
487 "pid": ospf.maxLSA['pid'],
488 "must_report": True,
489 "fixImpact": (items[0]),
490 "definition": (items[1]),
491 "threatInfo": (items[2]),
492 "howtofix": (items[3].strip() \
493 .replace('[%ospfInstance]', "".join(ospf.maxLSA['pid']), 1)),
494 "cvss": (cvssMetrics)}
495
496 toBeReturned = ''
497 if ospf.passive['must_report'] == True:
498 toBeReturned = ospf.passive['definition'] + '\n' + ospf.passive['threatInfo'] + '\n\n' + ospf.passive['howtofix'] + '\n'
499 if ospf.auth_md5['must_report'] == True:
500 toBeReturned = toBeReturned + ospf.auth_md5['definition'] + '\n' + ospf.auth_md5['threatInfo'] + '\n\n' + ospf.auth_md5['howtofix'] + '\n'
501 if ospf.rfilter_in['must_report'] == True:
502 toBeReturned = toBeReturned + ospf.rfilter_in['definition'] + '\n' + ospf.rfilter_in['threatInfo'] + '\n\n' + ospf.rfilter_in['howtofix'] + '\n'
503 if ospf.rfilter_out['must_report'] == True:
504 toBeReturned = toBeReturned + ospf.rfilter_out['definition'] + '\n' + ospf.rfilter_out['threatInfo'] + '\n\n' + ospf.rfilter_out['howtofix'] + '\n'
505 if ospf.maxLSA['must_report'] == True:
506 toBeReturned = toBeReturned + ospf.maxLSA['definition'] + '\n' + ospf.maxLSA['threatInfo'] + '\n\n' + ospf.maxLSA['howtofix'] + '\n'
507
508 return toBeReturned
509