Class: Msf::Exploit::Remote::HTTP::Kubernetes::AuthParser
- Inherits:
-
Object
- Object
- Msf::Exploit::Remote::HTTP::Kubernetes::AuthParser
- Defined in:
- lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb
Overview
Parses the succinct Kubernetes authentication API response and converts it into a more consumable format
Instance Attribute Summary collapse
-
#auth_response ⇒ Object
readonly
protected
Returns the value of attribute auth_response.
Instance Method Summary collapse
-
#as_simple_rule(policy_rule) ⇒ Object
protected
returns nil if it’s not possible to simplify this rule.
-
#as_table ⇒ Object
Converts the kubernetes auth response into an array of human readable table.
-
#breakdown_policy_rule(policy_rule) ⇒ Object
protected
Converts the original policy rule into its smaller policy rules, where there is at most one verb for each rule.
- #combine_resource_groups(resources, groups) ⇒ Object protected
-
#compact_policy_rules(policy_rules) ⇒ Object
protected
Merge policy rules together, by joining rules that are associated with the same resource, but different verbs.
-
#find_policy(existing_simple_rules, simple_rule) ⇒ Object
protected
Finds the original policy rule associated with a simplified rule.
- #human_readable_policy_rule(rule) ⇒ Object protected
-
#initialize(auth_response) ⇒ AuthParser
constructor
A new instance of AuthParser.
- #policy_rule_for(apiGroups: [], resources: [], verbs: [], resourceNames: [], nonResourceURLs: []) ⇒ Object protected
-
#rules ⇒ Object
Extracts the list of rules associated with a kubernetes auth response.
Constructor Details
#initialize(auth_response) ⇒ AuthParser
Returns a new instance of AuthParser.
6 7 8 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 6 def initialize(auth_response) @auth_response = auth_response end |
Instance Attribute Details
#auth_response ⇒ Object (readonly, protected)
Returns the value of attribute auth_response.
42 43 44 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 42 def auth_response @auth_response end |
Instance Method Details
#as_simple_rule(policy_rule) ⇒ Object (protected)
returns nil if it’s not possible to simplify this rule
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 138 def as_simple_rule(policy_rule) return nil if policy_rule[:resourceNames].count > 1 || policy_rule[:nonResourceURLs].count > 0 return nil if policy_rule[:apiGroups].count != 1 || policy_rule[:resources].count != 1 allowed_keys = %i[apiGroups resources verbs resourceNames nonResourceURLs] unsupported_keys = policy_rule.keys - allowed_keys return nil if unsupported_keys.any? simple_rule = { group: policy_rule[:apiGroups][0], resource: policy_rule[:resources][0] } if policy_rule[:resourceNames].any? simple_rule.merge( { resourceName: policy_rule[:resourceNames][0] } ) end simple_rule end |
#as_table ⇒ Object
Converts the kubernetes auth response into an array of human readable table
26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 26 def as_table columns = ['Resources', 'Non-Resource URLs', 'Resource Names', 'Verbs'] rows = rules.map do |rule| [ combine_resource_groups(rule[:resources], rule[:apiGroups]), "[#{rule[:nonResourceURLs].join(' ')}]", "[#{rule[:resourceNames].join(' ')}]", "[#{rule[:verbs].join(' ')}]" ] end { columns: columns, rows: rows } end |
#breakdown_policy_rule(policy_rule) ⇒ Object (protected)
Converts the original policy rule into its smaller policy rules, where there is at most one verb for each rule
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 56 def breakdown_policy_rule(policy_rule) sub_rules = [] policy_rule.fetch(:apiGroups, []).each do |group| policy_rule.fetch(:resources, []).each do |resource| policy_rule.fetch(:verbs, []).each do |verb| if policy_rule.fetch(:resourceNames, []).any? sub_rules += policy_rule[:resourceNames].map do |resource_name| policy_rule_for( apiGroups: [group], resources: [resource], verbs: [verb], resourceNames: [resource_name] ) end else sub_rules << policy_rule_for( apiGroups: [group], resources: [resource], verbs: [verb] ) end end end end sub_rules += policy_rule.fetch(:nonResourceURLs, []).flat_map do |non_resource_url| policy_rule[:verbs].map do |verb| policy_rule_for( nonResourceURLs: [non_resource_url], verbs: [verb] ) end end sub_rules end |
#combine_resource_groups(resources, groups) ⇒ Object (protected)
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 174 def combine_resource_groups(resources, groups) return '' if resources.empty? parts = resources[0].split('/', 2) result = parts[0] if groups.count > 0 && groups[0] != '' result = result + '.' + groups[0] end if parts.count == 2 result = result + '/' + parts[1] end result end |
#compact_policy_rules(policy_rules) ⇒ Object (protected)
Merge policy rules together, by joining rules that are associated with the same resource, but different verbs
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 114 def compact_policy_rules(policy_rules) compact_rules = [] simple_rules = {} policy_rules.each do |policy_rule| simple_rule = as_simple_rule(policy_rule) if simple_rule existing_rule = find_policy(simple_rules, simple_rule) if existing_rule existing_rule[:verbs] ||= [] existing_rule[:verbs] = (existing_rule[:verbs] + policy_rule[:verbs]).uniq else simple_rules[simple_rule] = policy_rule.clone end else compact_rules << policy_rule end end compact_rules += simple_rules.values compact_rules end |
#find_policy(existing_simple_rules, simple_rule) ⇒ Object (protected)
Finds the original policy rule associated with a simplified rule
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 94 def find_policy(existing_simple_rules, simple_rule) return nil if simple_rule.nil? existing_simple_rules.each do |existing_simple_rule, policy| is_match = ( existing_simple_rule[:group] == simple_rule[:group] && existing_simple_rule[:resource] == simple_rule[:resource] && existing_simple_rule[:resourceName] == simple_rule[:resourceName] ) if is_match return policy end end nil end |
#human_readable_policy_rule(rule) ⇒ Object (protected)
162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 162 def human_readable_policy_rule(rule) parts = [] parts << "APIGroups:[#{rule[:apiGroups].join(' ')}]" if rule[:apiGroups].any? parts << "Resources:[#{rule[:resources].join(' ')}]" if rule[:resources].any? parts << "NonResourceURLs:[#{rule[:nonResourceURLs].join(' ')}]" if rule[:nonResourceURLs].any? parts << "ResourceNames:[#{rule[:resourceNames].join(' ')}]" if rule[:resourceNames].any? parts << "Verbs:[#{rule[:verbs].join(' ')}]" if rule[:verbs].any? parts.join(', ') end |
#policy_rule_for(apiGroups: [], resources: [], verbs: [], resourceNames: [], nonResourceURLs: []) ⇒ Object (protected)
44 45 46 47 48 49 50 51 52 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 44 def policy_rule_for(apiGroups: [], resources: [], verbs: [], resourceNames: [], nonResourceURLs: []) { apiGroups: apiGroups, resources: resources, verbs: verbs, resourceNames: resourceNames, nonResourceURLs: nonResourceURLs } end |
#rules ⇒ Object
Extracts the list of rules associated with a kubernetes auth response
11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/msf/core/exploit/remote/http/kubernetes/auth_parser.rb', line 11 def rules resource_rules = auth_response.dig(:status, :resourceRules) || [] non_resource_rules = auth_response.dig(:status, :nonResourceRules) || [] policy_rules = resource_rules + non_resource_rules broke_down_policy_rules = policy_rules.flat_map do |policy_rule| breakdown_policy_rule(policy_rule) end compacted_rules = compact_policy_rules(broke_down_policy_rules) sorted_rules = compacted_rules.sort_by { |rule| human_readable_policy_rule(rule) } sorted_rules end |