33
44class SshResultTransformer
55 def initialize ( uuid_provider = SecureRandom )
6- @uuid_provider = uuid_provider ;
6+ @uuid_provider = uuid_provider
77 end
88
9-
109 def transform ( results , timed_out : false )
1110 findings = [ ]
11+
1212 results . each do |r |
13- findings << {
14- id : @uuid_provider . uuid ,
15- name : 'SSH Compliance' ,
16- description : 'SSH Compliance Information' ,
17- category : 'SSH Service' ,
18- osi_layer : 'NETWORK' ,
19- severity : 'INFORMATIONAL' ,
20- reference : { } ,
21- hint : '' ,
22- location : r . dig ( 'ip' ) ,
23- attributes : {
24- hostname : r . dig ( 'hostname' ) ,
25- server_banner : r . dig ( 'server_banner' ) ,
26- ssh_version : r . dig ( 'ssh_version' ) ,
27- os_cpe : r . dig ( 'os_cpe' ) ,
28- ssh_lib_cpe : r . dig ( 'ssh_lib_cpe' ) ,
29- compliance_policy : r . dig ( 'compliance' , 'policy' ) ,
30- compliant : r . dig ( 'compliance' , 'compliant' ) ,
31- grade : r . dig ( 'compliance' , 'grade' ) ,
32- start_time : r . dig ( 'start_time' ) ,
33- end_time : r . dig ( 'end_time' ) ,
34- scan_duration_seconds : r . dig ( 'scan_duration_seconds' ) ,
35- references : r . dig ( 'compliance' , 'references' )
36- }
37- }
13+ unless r . has_key? "error"
14+ location = ( r . dig ( 'hostname' ) . empty? ) ? r . dig ( 'ip' ) : r . dig ( 'hostname' )
15+ hostname = ( r . dig ( 'hostname' ) unless r . dig ( 'hostname' ) . empty? )
16+ findings <<
17+ {
18+ id : @uuid_provider . uuid ,
19+ name : 'SSH Service Information' ,
20+ description : '' ,
21+ category : 'SSH Service' ,
22+ osi_layer : 'NETWORK' ,
23+ severity : 'INFORMATIONAL' ,
24+ reference : { } ,
25+ hint : '' ,
26+ location : location ,
27+ attributes : {
28+ hostname : hostname ,
29+ ip_address : r . dig ( 'ip' ) ,
30+ server_banner :
31+ ( r . dig ( 'server_banner' ) unless r . dig ( 'server_banner' ) . empty? ) ,
32+ ssh_version : r . dig ( 'ssh_version' ) ,
33+ os_cpe : r . dig ( 'os_cpe' ) ,
34+ ssh_lib_cpe : r . dig ( 'ssh_lib_cpe' ) ,
35+ compliance_policy : r . dig ( 'compliance' , 'policy' ) ,
36+ compliant : r . dig ( 'compliance' , 'compliant' ) ,
37+ grade : r . dig ( 'compliance' , 'grade' ) ,
38+ start_time : r . dig ( 'start_time' ) ,
39+ end_time : r . dig ( 'end_time' ) ,
40+ scan_duration_seconds : r . dig ( 'scan_duration_seconds' ) ,
41+ references : r . dig ( 'compliance' , 'references' ) ,
42+ auth_methods : r . dig ( 'auth_methods' ) ,
43+ key_algorithms : r . dig ( 'key_algorithms' ) ,
44+ encryption_algorithms :
45+ r . dig ( 'encryption_algorithms_server_to_client' ) ,
46+ mac_algorithms : r . dig ( 'mac_algorithms_server_to_client' ) ,
47+ compression_algorithms :
48+ r . dig ( 'compression_algorithms_server_to_client' )
49+ }
50+ }
3851
39- unless r . dig ( 'compliance' , 'recommendations' ) . nil?
40- r . dig ( 'compliance' , 'recommendations' ) . each do |f |
41- findings << {
42- id : @uuid_provider . uuid ,
43- name : f . split ( ':' ) [ 0 ] ,
44- description : f . split ( ':' ) [ 1 ] ,
45- category : 'SSH Service' ,
46- osi_layer : 'NETWORK' ,
47- severity : decideSeverity ( r . dig ( 'compliance' , 'grade' ) ) ,
48- reference : { } ,
49- hint : '' ,
50- location : r . dig ( 'ip' ) ,
51- attributes : { }
52- }
52+ unless r . dig ( 'compliance' , 'recommendations' ) . nil?
53+ r . dig ( 'compliance' , 'recommendations' )
54+ . each do |policy_violation_message |
55+ findings <<
56+ create_policy_violation_finding (
57+ policy_violation_message ,
58+ location ,
59+ hostname ,
60+ r . dig ( 'ip' )
61+ )
62+ end
5363 end
5464 end
5565 end
5666
5767 findings
5868 end
5969
60- def decideSeverity ( grade )
61- case grade
62- when 'A' , 'B'
63- 'LOW'
64- when 'C' , 'D'
65- 'MEDIUM'
66- when 'E' , 'F'
67- 'HIGH'
70+ # rubocop:disable MethodComplexity
71+ def get_policy_violation_type ( message )
72+ type = message . split ( ': ' ) [ 0 ]
73+
74+ case type
75+ when /^Add these key exchange algorithms/
76+ {
77+ description : 'Good / encouraged SSH key algorithms are missing' ,
78+ name : 'Missing SSH Key Algorithms'
79+ }
80+ when /^Add these MAC algorithms/
81+ {
82+ description : 'Good / encouraged SSH MAC algorithms are missing' ,
83+ name : 'Missing SSH MAC Algorithms'
84+ }
85+ when /^Add these encryption ciphers/
86+ {
87+ description : 'Good / encouraged SSH encryption ciphers are missing' ,
88+ name : 'Missing SSH encryption Ciphers'
89+ }
90+ when /^Add these compression algorithms/
91+ {
92+ description : 'Good / encouraged SSH compression algorithms are missing' ,
93+ name : 'Missing SSH compression algorithms'
94+ }
95+ when /^Add these authentication methods/
96+ {
97+ description : 'Good / encouraged SSH authentication methods are missing' ,
98+ name : 'Missing SSH authentication methods'
99+ }
100+ when /^Remove these key exchange algorithms/
101+ {
102+ description : 'Deprecated / discouraged SSH key algorithms are used' ,
103+ name : 'Insecure SSH Key Algorithms'
104+ }
105+ when /^Remove these MAC algorithms/
106+ {
107+ description : 'Deprecated / discouraged SSH MAC algorithms are used' ,
108+ name : 'Insecure SSH MAC Algorithms'
109+ }
110+ when /^Remove these encryption ciphers/
111+ {
112+ description : 'Deprecated / discouraged SSH encryption ciphers are used' ,
113+ name : 'Insecure SSH encryption Ciphers'
114+ }
115+ when /^Remove these compression algorithms/
116+ {
117+ description :
118+ 'Deprecated / discouraged SSH compression algorithms are used' ,
119+ name : 'Insecure SSH compression algorithms'
120+ }
121+ when /^Remove these authentication methods/
122+ {
123+ description : 'Discouraged SSH authentication methods are used' ,
124+ name : 'Discouraged SSH authentication methods'
125+ }
126+ when /^Update your ssh version to/
127+ {
128+ description : 'Outdated SSH protocol version used' ,
129+ name : 'Outdated SSH Protocol Version'
130+ }
131+ else
132+ raise Exception . new "Unexpected Policy Violation Type: '#{ message } '"
68133 end
69134 end
70- end
135+ # rubocop:enable MethodComplexity
136+
137+ def create_policy_violation_finding (
138+ message , location , hostname , ip_address
139+ )
140+ policy_violation_type = get_policy_violation_type ( message )
141+
142+ payload = message . split ( ': ' ) [ 1 ] . split ( ', ' )
143+
144+ {
145+ id : @uuid_provider . uuid ,
146+ name : policy_violation_type [ :name ] ,
147+ description : policy_violation_type [ :description ] ,
148+ category : 'SSH Policy Violation' ,
149+ osi_layer : 'NETWORK' ,
150+ severity : 'MEDIUM' ,
151+ reference : { } ,
152+ hint : message ,
153+ location : location ,
154+ attributes : {
155+ hostname : hostname , ip_address : ip_address , payload : payload
156+ }
157+ }
158+ end
159+ end
0 commit comments