Class: Arachni::Issue
- Defined in:
- lib/arachni/issue.rb,
lib/arachni/issue/severity.rb,
lib/arachni/issue/severity/base.rb
Overview
Represents a detected issue.
Defined Under Namespace
Modules: Severity
Constant Summary collapse
- VARIATION_ATTRIBUTES =
Attributes removed from a parent issue (i.e. an issues with variations) and solely populating variations.
Set.new([ :@page, :@referring_page, :@proof, :@signature, :@remarks, :@trusted ])
Instance Attribute Summary collapse
-
#check ⇒ Hash
Information about the check that logged the issue.
-
#cwe ⇒ String
The CWE ID number of the issue.
-
#description ⇒ String
Brief description.
-
#name ⇒ String
Name.
-
#page ⇒ Page
Page proving the issue.
-
#parent ⇒ Issue?
Parent of variation.
-
#platform_name ⇒ Symbol
Name of the vulnerable platform.
-
#platform_type ⇒ Symbol
Type of the vulnerable platform.
-
#proof ⇒ String
Data that was matched by the #signature.
-
#references ⇒ Hash
References related to the issue.
-
#referring_page ⇒ Page
Page containing the #vector and whose audit resulted in the discovery of the issue.
-
#remarks ⇒ Hash
Remarks about the issue.
-
#remedy_code ⇒ String
Code snippet demonstrating how to remedy the Issue.
-
#remedy_guidance ⇒ String
Brief text explaining how to remedy the issue.
-
#severity ⇒ String
Severity of the issue.
-
#signature ⇒ String
The signature/pattern that identified the issue.
-
#tags ⇒ Array<String>
Tags categorizing the issue.
-
#trusted ⇒ Bool
‘true` if the issue can be trusted (doesn’t require manual verification), ‘false` otherwise.
-
#variations ⇒ Array<Issue>
Variations of this issue.
-
#vector ⇒ Element::Base?
Instance of the relevant vector if available.
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#active? ⇒ Boolean
‘true` if the issue was discovered by manipulating an input, `false` otherwise.
-
#add_remark(author, string) ⇒ Object
Adds a remark as a heads-up to the end user.
-
#affected_input_name ⇒ String?
The name of the affected input, ‘nil` if the issue is #passive?.
- #as_variation ⇒ Issue
-
#cwe_url ⇒ String
CWE reference URL.
-
#digest ⇒ Integer
A hash uniquely identifying this issue.
- #eql?(other) ⇒ Boolean
- #hash ⇒ Object
-
#initialize(options = {}) ⇒ Issue
constructor
A new instance of Issue.
-
#passive? ⇒ Boolean
‘true` if the issue was discovered passively, `false` otherwise.
-
#recheck(framework = nil) ⇒ Issue?
Rechecks the existence of this issue.
- #request ⇒ HTTP::Request
- #response ⇒ HTTP::Response
-
#solo? ⇒ Bool
‘true` if the issue neither has nor is a variation, `false` otherwise.
- #to_h ⇒ Hash (also: #to_hash)
-
#to_rpc_data ⇒ Hash
Data representing this instance that are suitable the RPC transmission.
-
#to_solo(issue) ⇒ Issue
Copy of ‘self` as a solo issue.
-
#to_solo!(issue) ⇒ Issue
Converts ‘self` to a solo issue, in place.
-
#trusted? ⇒ Bool
‘true` if the issue can be trusted (doesn’t require manual verification), ‘false` otherwise.
-
#unique_id ⇒ String
A string uniquely identifying this issue.
- #untrusted? ⇒ Boolean
-
#variation? ⇒ Bool
‘true` if `self` is a variation.
-
#with_variations ⇒ Issue
A copy of ‘self` without specific details and an empty array of #variations to be populated.
Constructor Details
#initialize(options = {}) ⇒ Issue
Returns a new instance of Issue.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/arachni/issue.rb', line 121 def initialize( = {} ) # Make sure we're dealing with UTF-8 data. = .recode .each do |k, v| send( "#{k.to_s.downcase}=", v ) end fail ArgumentError, 'Missing :vector' if !@vector @remarks ||= {} @trusted = true if @trusted.nil? @references ||= {} @tags ||= [] @variations ||= [] @variation = nil @parent = nil end |
Instance Attribute Details
#check ⇒ Hash
Returns Information about the check that logged the issue.
91 92 93 |
# File 'lib/arachni/issue.rb', line 91 def check @check end |
#cwe ⇒ String
Returns The CWE ID number of the issue.
62 63 64 |
# File 'lib/arachni/issue.rb', line 62 def cwe @cwe end |
#description ⇒ String
Should be treated as Markdown.
Returns Brief description.
32 33 34 |
# File 'lib/arachni/issue.rb', line 32 def description @description end |
#page ⇒ Page
Returns Page proving the issue.
87 88 89 |
# File 'lib/arachni/issue.rb', line 87 def page @page end |
#parent ⇒ Issue?
Returns Parent of variation.
117 118 119 |
# File 'lib/arachni/issue.rb', line 117 def parent @parent end |
#platform_name ⇒ Symbol
Returns Name of the vulnerable platform.
68 69 70 |
# File 'lib/arachni/issue.rb', line 68 def platform_name @platform_name end |
#platform_type ⇒ Symbol
Returns Type of the vulnerable platform.
74 75 76 |
# File 'lib/arachni/issue.rb', line 74 def platform_type @platform_type end |
#proof ⇒ String
Returns Data that was matched by the #signature.
99 100 101 |
# File 'lib/arachni/issue.rb', line 99 def proof @proof end |
#references ⇒ Hash
Returns References related to the issue.
56 57 58 |
# File 'lib/arachni/issue.rb', line 56 def references @references end |
#referring_page ⇒ Page
Returns Page containing the #vector and whose audit resulted in the discovery of the issue.
83 84 85 |
# File 'lib/arachni/issue.rb', line 83 def referring_page @referring_page end |
#remarks ⇒ Hash
Returns Remarks about the issue. Key is the name of the entity which made the remark, value is an ‘Array` of remarks.
109 110 111 |
# File 'lib/arachni/issue.rb', line 109 def remarks @remarks end |
#remedy_code ⇒ String
Returns Code snippet demonstrating how to remedy the Issue.
42 43 44 |
# File 'lib/arachni/issue.rb', line 42 def remedy_code @remedy_code end |
#remedy_guidance ⇒ String
Should be treated as Markdown.
Returns Brief text explaining how to remedy the issue.
38 39 40 |
# File 'lib/arachni/issue.rb', line 38 def remedy_guidance @remedy_guidance end |
#severity ⇒ String
Returns Severity of the issue.
48 49 50 |
# File 'lib/arachni/issue.rb', line 48 def severity @severity end |
#signature ⇒ String
Returns The signature/pattern that identified the issue.
95 96 97 |
# File 'lib/arachni/issue.rb', line 95 def signature @signature end |
#tags ⇒ Array<String>
Returns Tags categorizing the issue.
52 53 54 |
# File 'lib/arachni/issue.rb', line 52 def @tags end |
#trusted ⇒ Bool
Returns ‘true` if the issue can be trusted (doesn’t require manual verification), ‘false` otherwise.
104 105 106 |
# File 'lib/arachni/issue.rb', line 104 def trusted @trusted end |
#variations ⇒ Array<Issue>
Returns Variations of this issue.
113 114 115 |
# File 'lib/arachni/issue.rb', line 113 def variations @variations end |
#vector ⇒ Element::Base?
Returns Instance of the relevant vector if available.
78 79 80 |
# File 'lib/arachni/issue.rb', line 78 def vector @vector end |
Class Method Details
.from_rpc_data(data) ⇒ Issue
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 |
# File 'lib/arachni/issue.rb', line 497 def self.from_rpc_data( data ) instance = allocate data.each do |name, value| value = case name when 'vector' element_string_to_class( value.delete('class') ).from_rpc_data( value ) when 'check' if value['elements'] value['elements'] = (value['elements'].map do |class_name| element_string_to_class( class_name ) end) end value.my_symbolize_keys(false) when 'variations' value.map { |i| from_rpc_data i } when 'remarks' value.my_symbolize_keys when 'platform_name', 'platform_type' next if !value value.to_sym when 'severity' next if value.to_s.empty? Severity.const_get( value.upcase.to_sym ) when 'page', 'referring_page' Arachni::Page.from_rpc_data( value ) else value end instance.instance_variable_set( "@#{name}", value ) end if instance.variations instance.variations.each do |v| v.parent = instance end end instance end |
Instance Method Details
#==(other) ⇒ Object
456 457 458 |
# File 'lib/arachni/issue.rb', line 456 def ==( other ) hash == other.hash end |
#active? ⇒ Boolean
Returns ‘true` if the issue was discovered by manipulating an input, `false` otherwise.
205 206 207 208 209 210 211 |
# File 'lib/arachni/issue.rb', line 205 def active? if variations && variations.any? return variations.first.active? end !!(vector.respond_to?( :affected_input_name ) && vector.affected_input_name) end |
#add_remark(author, string) ⇒ Object
Adds a remark as a heads-up to the end user.
193 194 195 196 197 198 |
# File 'lib/arachni/issue.rb', line 193 def add_remark( , string ) fail ArgumentError, 'Author cannot be blank.' if .to_s.empty? fail ArgumentError, 'String cannot be blank.' if string.to_s.empty? (@remarks[] ||= []) << string end |
#affected_input_name ⇒ String?
Returns The name of the affected input, ‘nil` if the issue is #passive?.
217 218 219 220 221 222 223 224 225 |
# File 'lib/arachni/issue.rb', line 217 def affected_input_name return if !active? if variations && variations.any? return variations.first.vector.affected_input_name end vector.affected_input_name end |
#as_variation ⇒ Issue
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
# File 'lib/arachni/issue.rb', line 410 def as_variation issue = self.deep_clone instance_variables.each do |k| next if k == :@vector || VARIATION_ATTRIBUTES.include?( k ) || !issue.instance_variable_defined?( k ) issue.remove_instance_variable k end issue.unique_id = unique_id issue.variation = true issue.parent = self issue end |
#cwe_url ⇒ String
Returns CWE reference URL.
257 258 259 260 |
# File 'lib/arachni/issue.rb', line 257 def cwe_url return if !cwe @cwe_url ||= "http://cwe.mitre.org/data/definitions/#{cwe}.html".freeze end |
#digest ⇒ Integer
Returns A hash uniquely identifying this issue.
368 369 370 |
# File 'lib/arachni/issue.rb', line 368 def digest unique_id.persistent_hash end |
#eql?(other) ⇒ Boolean
464 465 466 |
# File 'lib/arachni/issue.rb', line 464 def eql?( other ) hash == other.hash end |
#hash ⇒ Object
460 461 462 |
# File 'lib/arachni/issue.rb', line 460 def hash unique_id.hash end |
#passive? ⇒ Boolean
Returns ‘true` if the issue was discovered passively, `false` otherwise.
231 232 233 |
# File 'lib/arachni/issue.rb', line 231 def passive? !active? end |
#recheck(framework = nil) ⇒ Issue?
The whole environment needs to be fresh.
Rechecks the existence of this issue.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/arachni/issue.rb', line 150 def recheck( framework = nil ) new_issue = nil checker = proc do |f| referring_page.update_element_audit_whitelist vector f..url = referring_page.url f..audit.elements vector.class.type f.checks.load( parent ? parent.check[:shortname] : check[:shortname] ) f.push_to_page_queue referring_page f.run new_issue = Data.issues[digest] end if framework checker.call framework else Arachni::Framework.new( &checker ) end new_issue end |
#request ⇒ HTTP::Request
182 183 184 185 |
# File 'lib/arachni/issue.rb', line 182 def request return if !response response.request end |
#response ⇒ HTTP::Response
176 177 178 179 |
# File 'lib/arachni/issue.rb', line 176 def response return if !page page.response end |
#solo? ⇒ Bool
Returns ‘true` if the issue neither has nor is a variation, `false` otherwise.
374 375 376 |
# File 'lib/arachni/issue.rb', line 374 def solo? @variation.nil? end |
#to_h ⇒ Hash Also known as: to_hash
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
# File 'lib/arachni/issue.rb', line 286 def to_h h = {} self.instance_variables.each do |var| h[normalize_name( var )] = try_dup( instance_variable_get( var ) ) end h[:vector] = vector.to_h h.delete( :unique_id ) if solo? h.delete( :variation ) else if variation? h[:vector].delete :html h[:vector].delete :type h[:vector].delete :url h[:vector].delete :action h[:vector].delete :default_inputs h[:vector].delete :affected_input_name else h[:vector][:inputs] = h[:vector].delete( :default_inputs ) h[:vector][:affected_input_name] = affected_input_name end end if !variation? || solo? h[:digest] = digest h[:severity] = severity.to_sym h[:cwe_url] = cwe_url if cwe_url # Since we're doing the whole cross-platform hash thing better switch # the Element classes in the check's info data to symbols. h[:check][:elements] ||= [] h[:check][:elements] = h[:check][:elements].map(&:type) h[:variations] = @variations.map(&:to_h) end if variation? || solo? if page dom_h = page.dom.to_h dom_h.delete(:skip_states) h[:page] = { body: page.body, dom: dom_h } end if referring_page referring_page_dom_h = referring_page.dom.to_h referring_page_dom_h.delete(:skip_states) h[:referring_page] = { body: referring_page.body, dom: referring_page_dom_h } end h[:response] = response.to_h if response h[:request] = request.to_h if request end h.delete :parent h end |
#to_rpc_data ⇒ Hash
Returns Data representing this instance that are suitable the RPC transmission.
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 |
# File 'lib/arachni/issue.rb', line 470 def to_rpc_data data = {} instance_variables.each do |ivar| data[ivar.to_s.gsub('@','')] = instance_variable_get( ivar ).to_rpc_data_or_self end data.delete 'parent' if data['check'] && data['check'][:elements] data['check'] = data['check'].dup data['check'][:elements] = data['check'][:elements].map(&:to_s) end if data['variations'] data['variations'] = data['variations'].map(&:to_rpc_data) end data['digest'] = digest data['severity'] = data['severity'].to_s data end |
#to_solo(issue) ⇒ Issue
Copy of ‘self` as a solo issue.
452 453 454 |
# File 'lib/arachni/issue.rb', line 452 def to_solo( issue ) deep_clone.to_solo!( issue ) end |
#to_solo!(issue) ⇒ Issue
Converts ‘self` to a solo issue, in place.
432 433 434 435 436 437 438 439 440 441 442 443 444 |
# File 'lib/arachni/issue.rb', line 432 def to_solo!( issue ) issue.instance_variables.each do |k| next if k == :@variations || k == :@vector || k == :@trusted next if (val = issue.instance_variable_get(k)).nil? instance_variable_set( k, val ) end @variations = [] @variation = nil @parent = nil self end |
#trusted? ⇒ Bool
Returns ‘true` if the issue can be trusted (doesn’t require manual verification), ‘false` otherwise.
240 241 242 |
# File 'lib/arachni/issue.rb', line 240 def trusted? !!@trusted end |
#unique_id ⇒ String
Returns A string uniquely identifying this issue.
358 359 360 361 362 |
# File 'lib/arachni/issue.rb', line 358 def unique_id return @unique_id if @unique_id vector_info = active? ? "#{vector.method}:#{vector.affected_input_name}:" : nil "#{name}:#{vector_info}#{vector.action.split( '?' ).first}" end |
#untrusted? ⇒ Boolean
245 246 247 |
# File 'lib/arachni/issue.rb', line 245 def untrusted? !trusted? end |
#variation? ⇒ Bool
Returns ‘true` if `self` is a variation.
380 381 382 |
# File 'lib/arachni/issue.rb', line 380 def variation? !!@variation end |
#with_variations ⇒ Issue
Returns A copy of ‘self` without specific details and an empty array of #variations to be populated.
Also, the #vector attribute will hold the original, non-mutated vector.
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 |
# File 'lib/arachni/issue.rb', line 389 def with_variations issue = self.deep_clone instance_variables.each do |k| next if k == :@trusted || !VARIATION_ATTRIBUTES.include?( k ) || !issue.instance_variable_defined?( k ) issue.remove_instance_variable k end issue.vector.reset issue.unique_id = unique_id issue.variation = false issue.parent = nil issue end |