Class: Watobo::Modules::Active::Xss::Xss_rated

Inherits:
ActiveCheck show all
Defined in:
modules/active/xss/xss_rated.rb

Constant Summary

Constants included from Constants

Constants::AC_GROUP_APACHE, Constants::AC_GROUP_DOMINO, Constants::AC_GROUP_ENUMERATION, Constants::AC_GROUP_FILE_INCLUSION, Constants::AC_GROUP_FLASH, Constants::AC_GROUP_GENERIC, Constants::AC_GROUP_JBOSS, Constants::AC_GROUP_JOOMLA, Constants::AC_GROUP_SAP, Constants::AC_GROUP_SQL, Constants::AC_GROUP_TYPO3, Constants::AC_GROUP_XSS, Constants::AUTH_TYPE_BASIC, Constants::AUTH_TYPE_DIGEST, Constants::AUTH_TYPE_NONE, Constants::AUTH_TYPE_NTLM, Constants::CHAT_SOURCE_AUTO_SCAN, Constants::CHAT_SOURCE_FUZZER, Constants::CHAT_SOURCE_INTERCEPT, Constants::CHAT_SOURCE_MANUAL, Constants::CHAT_SOURCE_MANUAL_SCAN, Constants::CHAT_SOURCE_PROXY, Constants::CHAT_SOURCE_UNDEF, Constants::DEFAULT_PORT_HTTP, Constants::DEFAULT_PORT_HTTPS, Constants::FINDING_TYPE_HINT, Constants::FINDING_TYPE_INFO, Constants::FINDING_TYPE_UNDEFINED, Constants::FINDING_TYPE_VULN, Constants::FIRST_TIME_FILE, Constants::GUI_REGULAR_FONT_SIZE, Constants::GUI_SMALL_FONT_SIZE, Constants::ICON_PATH, Constants::LOG_DEBUG, Constants::LOG_INFO, Constants::SCAN_CANCELED, Constants::SCAN_FINISHED, Constants::SCAN_PAUSED, Constants::SCAN_STARTED, Constants::TE_CHUNKED, Constants::TE_COMPRESS, Constants::TE_DEFLATE, Constants::TE_GZIP, Constants::TE_IDENTITY, Constants::TE_NONE, Constants::VULN_RATING_CRITICAL, Constants::VULN_RATING_HIGH, Constants::VULN_RATING_INFO, Constants::VULN_RATING_LOW, Constants::VULN_RATING_MEDIUM, Constants::VULN_RATING_UNDEFINED

Instance Attribute Summary

Attributes inherited from ActiveCheck

#info, #numChecks

Instance Method Summary collapse

Methods inherited from ActiveCheck

#addFinding, #cancel, #checksRunning?, #continue, #disable, #do_test, #enable, #enabled=, #enabled?, #fileExists?, #getCheckCount, #log_console, #maxChecks, #maxChecks=, #postParmNames, #reset, #resetCounters, #run_checks, #stop, #updateCounters, #urlParmNames, #waitLogin

Methods inherited from Session

#addProxy, #clearEvents, #doRequest, #getProxy, #get_settings, #notify, #readHTTPBody, #runLogin, #sendHTTPRequest, #sessionSettings, #setSIDCache, #sidCache, #subscribe

Constructor Details

#initialize(project, prefs = {}) ⇒ Xss_rated

Returns a new instance of Xss_rated.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'modules/active/xss/xss_rated.rb', line 30

def initialize(project, prefs={})
  super(project, prefs)
  
  threat =<<'EOF'
Cross-site Scripting (XSS) is an attack technique that involves echoing attacker-supplied code into a user's browser instance. 
A browser instance can be a standard web browser client, or a browser object embedded in a software product such as the browser 
within WinAmp, an RSS reader, or an email client. The code itself is usually written in HTML/JavaScript, but may also extend to 
VBScript, ActiveX, Java, Flash, or any other browser-supported technology.

When an attacker gets a user's browser to execute his/her code, the code will run within the security context (or zone) of the 
hosting web site. With this level of privilege, the code has the ability to read, modify and transmit any sensitive data accessible 
by the browser. A Cross-site Scripted user could have his/her account hijacked (cookie theft), their browser redirected to another 
location, or possibly shown fraudulent content delivered by the web site they are visiting. Cross-site Scripting attacks essentially 
compromise the trust relationship between a user and the web site. Applications utilizing browser object instances which load content 
from the file system may execute code under the local machine zone allowing for system compromise.

Source: http://projects.webappsec.org/Cross-Site+Scripting
EOF
  
  measure = "All user input should be filtered and/or escaped using a method appropriate for the output context"
  
  @info.update(
               :check_name => 'Rated Cross Site Scripting Checks',    # name of check which briefly describes functionality, will be used for tree and progress views
  :check_group => AC_GROUP_XSS,
  :description => "Checking every URL parameter for missing output sanitisation. The results have a rated exploitability.",   # description of checkfunction
  :author => "Andreas Schmidt", # author of check
  :version => "1.0"   # check version
  )
  
  @finding.update(
                  :threat => threat,        # thread of vulnerability, e.g. loss of information
                  :class => "Reflected XSS [RATED]",    # vulnerability class, e.g. Stored XSS, SQL-Injection, ...
  :type => FINDING_TYPE_VULN,         # FINDING_TYPE_HINT, FINDING_TYPE_INFO, FINDING_TYPE_VULN
  :rating => VULN_RATING_HIGH,
  :measure => measure
  )
  
  @envelop = [ "watobo", "watobo".reverse]
  @evasions = [ "%0a", "%00"]
  @xss_chars= %w( < > ' " ) 
  @escape_chars = ['\\']       
  
end

Instance Method Details

#generateChecks(chat) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'modules/active/xss/xss_rated.rb', line 75

def generateChecks(chat)    
  #
  #  Check GET-Parameters
  #
  begin
    
    log_console("generating checks ...")
    urlParmNames(chat).each do |parm|
      log_console( parm )
      # puts "#{Module.nesting[0].name}: run check on chat-id (#{chat.id}) with parm (#{parm})"
      pval = chat.request.get_parm_value(parm)
      checks = []
      @xss_chars.each do |xss|
         tp = "#{@envelop[0]}"
         tp << CGI.escape(xss)
         tp << "#{@envelop[1]}"
         pattern = "#{@envelop[0]}([^#{@envelop[0]}]*#{xss})#{@envelop[1]}"   
         checks << [ xss.dup, "#{tp}" , pattern ]
         checks << [xss.dup, "#{pval}#{tp}", pattern ]
         checks << [xss.dup, "#{tp}#{pval}", pattern ]
            
        end
        checker = proc {
          results = {}
          rating = 0
             test_request = nil
            test_response = nil
     
          
          checks.each do |xss, check, proof|
            next if results.has_key? xss
            test = chat.copyRequest
            test.replace_get_parm(parm, check)
              
            test_request,test_response = doRequest(test)
                             
            if not test_response then
              if $DEBUG
              puts "[#{Module.nesting[0].name}] got no response :("
              puts test
              end
            elsif test_response.join =~ /#{proof}/i
              match = $1
            #  puts "MATCH: #{match}/#{xss}"
              if match == xss
              results[xss] = { :match => :full, :check => check, :proof => proof }
              end
              
              unless results.has_key? xss
                @escape_chars.each do |ec|
                  ep = Regexp.quote("#{ec}#{xss}")
                #  puts "Escaped: #{match} / #{ep}"
                  results[xss] = { :match => :escaped, :check => check, :proof => proof} if match =~ /#{ep}/
                end
              end
              
              results[xss] = { :match => :modified, :check => check, :proof => proof } unless results.has_key? xss
              
            end
            puts results.to_yaml if $DEBUG
          end
          
         
          xss_combo = ""
         results.each do |k,v|
           mp = CGI.escape(k)
           rp = CGI.escape(@xss_chars.join)
           case v[:match]
           when :full
               rating += 100/@xss_chars.length
               xss_combo = v[:check].gsub(/#{mp}/, rp)
             when :escaped
                rating += 100/(@xss_chars.length*4)
                xss_combo = v[:check].gsub(/#{mp}/, rp) if xss_combo.empty?
             when :modified
               rating += 100/(@xss_chars.length*4)
               xss_combo = v[:check].gsub(/#{mp}/, rp) if xss_combo.empty?
             end
         end                   
          
          if rating > 0
            test = chat.copyRequest
            puts "COMBO-REQUEST: #{xss_combo}"
            test.replace_get_parm(parm, xss_combo)
              
          #  puts "Reflected XSS: #{ts}"
         #     pattern = "#{@envelop[0]}[^#{@envelop[0]}]*(\\\\)?#{@xss_chars.join('(\\\\)?')}#{@envelop[1]}"
            match = ""
            pattern = "#{@envelop[0]}([^#{@envelop[0]}]*(#{@xss_chars.join("|")})+[^#{@envelop[0]}]*)#{@envelop[1]}"
            test_request,test_response = doRequest(test)
            if not test_response then
              puts "got no response :("
            elsif test_response.join =~ /#{pattern}/i
              match = $1
              puts "MATCH: #{match}"
            end
           
            addFinding( test_request, test_response,
                       :check_pattern => xss_combo, 
            :proof_pattern => "#{match}", 
            :test_item => parm,
            :class => "Reflected XSS", 
            :chat => chat,
            :title => "[#{parm} - #{rating}%] - #{test_request.path}"
            )
          end
          #@project.new_finding(:short_name=>"#{parm}", :check=>"#{check}", :proof=>"#{pattern}", :kategory=>"XSS-Post", :type=>"Vuln", :chat=>test_chat, :rating=>"High")
          [ test_request, test_response ]
        }
        yield checker
     
    end
   
    
  rescue => bang
    puts bang
    puts bang.backtrace if $DEBUG
    puts "ERROR!! #{Module.nesting[0].name}"
    raise
    
    
  end
end