Class: Watobo::Modules::Active::Sqlinjection::Sqli_timing

Inherits:
ActiveCheck
  • Object
show all
Defined in:
modules/active/sqlinjection/sqli_timing.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 Method Summary collapse

Methods included from CheckInfoMixin::InfoMethods

#check_group, #check_name

Constructor Details

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

Returns a new instance of Sqli_timing.


66
67
68
69
# File 'modules/active/sqlinjection/sqli_timing.rb', line 66

def initialize(project, prefs={})
  super(project, prefs)
  
end

Instance Method Details

#generateChecks(chat) {|checker| ... } ⇒ Object

Yields:

  • (checker)

71
72
73
74
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'modules/active/sqlinjection/sqli_timing.rb', line 71

def generateChecks(chat)
            sql_timing_commands = [
 'and sleep(SLEEP_TIME)',
 'and 1 in (select BENCHMARK(20000000,MD5(CHAR(97))))',
 'and waitfor delay \'0:0:SLEEP_TIME\''
            ]
            
            sqli_vectors = [ 
 '', 
 '\'', 
 '\'))', 
 '\')))', 
 ')', 
 '))', 
 ')))'
 ]
 
 sql_terminators = [
   '', '--', ';--'
 ]
 
 sqli_patterns = []
 sqli_vectors.each do |v|
    sql_timing_commands.each do |stc|
      sql_terminators.each do |sts|
        sqli_patterns << "#{v} #{stc}#{sts}"
      end
    end  
 end
 
 check_parms = []
 
 urlParmNames(chat).each do |parm|
   pval = chat.request.get_parm_value(parm)
   check_parms << { :name => parm, :value => pval, :type => :url }
 end
 
 postParmNames(chat).each do |parm|
   pval = chat.request.post_parm_value(parm)
   check_parms << { :name => parm, :value => pval, :type => :form }
 end
 

   checker = proc {
      test_request = nil
      test_response = nil
      output = ""
      
      check_parms.each do |parm|
    # first get multiple response times
         rtimes = []
        
         timing_response = nil
         
         vulnerable = false
         
         4.times do
           test = chat.copyRequest
            start = Time.now().to_i
            timing_request, timing_response = doRequest(test,:default => true)
            stop = Time.now().to_i
            rtimes << ( stop - start )
         
         end
         # now calculate the average time
         average_t = rtimes.inject(:+) / rtimes.length
         max_t = rtimes.max > 5 ? rtimes.max : 5
        # puts "Analyzing timing behaviour ..."
        # rtimes.each do |t|
        #   puts t.to_s
        # end
        # puts "Average Response Time: #{average_t}s (max #{max_t}s)"                     
         
    #     time_to_sleep = 4 * max_t
         time_to_sleep = max_t
         #timeout_t = time_to_sleep + average_t
         timeout_t = 2 * time_to_sleep
          
         test_value = ""
         test = nil
         log_request = nil
         max_timeouts = 2
         timeout_counter = 0
         sqli_start = sqli_stop = 0
         
         sqli_patterns.each do |sql|
           timeout_counter = 0
           output = ""
           break if vulnerable
           begin
              sqli_start = Time.now().to_i
              timeout(timeout_t) do
                test = chat.copyRequest
                # also need to check if altered parm will change response
                test_value = CGI.escape("#{parm[:value]}#{sql.gsub(/SLEEP_TIME/, time_to_sleep.to_s)}")
                case parm[:type]
                  when :url     
                    test.replace_get_parm(parm[:name], test_value)
                  when :form
                    test.replace_post_parm(parm[:name], test_value)
                end
                
                test_request, test_response = doRequest(test,:default => true)
                sqli_stop = Time.now().to_i
              end
            rescue Timeout::Error
              timeout_counter += 1
         #     puts "[#{self}] Hit Timeout after #{timeout_t} seconds (#{timeout_counter})."
         #     puts test
         #     puts 
         #     puts "... retry after #{max_t} seconds ..."
              sleep max_t
              retry unless timeout_counter > 2
              sqli_stop = Time.now().to_i
              output << "Hit Timeout after #{sqli_start - sqli_stop} seconds\n"
         #     puts "* redo request with sleep_time=0 to get an apropriate server response ..."
              test = chat.copyRequest
              test_value = CGI.escape("#{parm[:value]}#{sql.gsub(/SLEEP_TIME/, "0")}")     
                case parm[:type]
                  when :url     
                test.replace_get_parm(parm[:name], test_value)
                when :form
                  test.replace_post_parm(parm[:name], test_value)
                end
                
                dummy_request, test_response = doRequest(test, :default => true)
               
            rescue => bang
              puts bang
              puts bang.backtrace
            end    
            
            
            duration = sqli_stop - sqli_start
          #  puts duration
            if ( duration >= time_to_sleep )
              puts "Found time-based SQLi in parameter #{parm} !!!"
              puts "after #{duration}s / time-to-sleep #{time_to_sleep}s)"
              test_request.extend Watobo::Mixin::Parser::Url unless test_request.respond_to? :path
              path = "/" + test_request.path
              
              vulnerable = true
              output << "SleepTime: #{time_to_sleep}\nQuery Duration: #{duration}s" 
                                      
              addFinding( test_request, test_response,
                        :check_pattern => "#{test_value}",
                        :chat => chat,
                        :title => "[#{parm[:name]}] - #{path}",
                        :proof_pattern => "",
                        :test_item => parm[:name],
                        :class => "SQL-Injection (Time-based)",
                        :output => output               
                        )
               #readlines
             break 
            end
         end
           
           end
    
       [ test_request, test_response ]
     }
     yield checker
     
   
end