ronin-sql 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/History.txt +9 -0
  2. data/Manifest.txt +7 -2
  3. data/README.txt +6 -3
  4. data/Rakefile +8 -8
  5. data/lib/ronin/code/sql/alter_table.rb +6 -6
  6. data/lib/ronin/code/sql/common_dialect.rb +1 -1
  7. data/lib/ronin/code/sql/create.rb +10 -2
  8. data/lib/ronin/code/sql/create_index.rb +3 -3
  9. data/lib/ronin/code/sql/create_table.rb +3 -3
  10. data/lib/ronin/code/sql/create_view.rb +3 -3
  11. data/lib/ronin/code/sql/delete.rb +7 -2
  12. data/lib/ronin/code/sql/dialect.rb +3 -1
  13. data/lib/ronin/code/sql/drop_index.rb +3 -3
  14. data/lib/ronin/code/sql/drop_table.rb +3 -3
  15. data/lib/ronin/code/sql/drop_view.rb +3 -3
  16. data/lib/ronin/code/sql/insert.rb +5 -5
  17. data/lib/ronin/code/sql/program.rb +2 -1
  18. data/lib/ronin/code/sql/select.rb +18 -5
  19. data/lib/ronin/code/sql/update.rb +3 -3
  20. data/lib/ronin/formatting/extensions/sql/string.rb +69 -0
  21. data/lib/ronin/formatting/extensions/sql.rb +24 -0
  22. data/lib/ronin/formatting/sql.rb +24 -0
  23. data/lib/ronin/sql/{extensions → error/extensions}/string.rb +3 -46
  24. data/lib/ronin/sql/error/extensions.rb +24 -0
  25. data/lib/ronin/sql/error/patterns.rb +1 -0
  26. data/lib/ronin/sql/error.rb +1 -0
  27. data/lib/ronin/sql/extensions/uri/http.rb +13 -28
  28. data/lib/ronin/sql/extensions.rb +0 -1
  29. data/lib/ronin/sql/injection.rb +2 -0
  30. data/lib/ronin/sql/version.rb +1 -1
  31. data/lib/ronin/sql.rb +0 -1
  32. data/spec/code/sql/common_dialect_spec.rb +205 -0
  33. data/spec/code/sql/create_examples.rb +4 -4
  34. data/spec/code/sql/select_spec.rb +4 -4
  35. data/spec/spec_helper.rb +3 -1
  36. data/spec/sql/extensions/uri/http_spec.rb +34 -0
  37. data.tar.gz.sig +1 -0
  38. metadata +45 -11
  39. metadata.gz.sig +4 -0
  40. data/spec/sql/extensions/string_spec.rb +0 -28
data/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ === 0.2.3 / 2009-07-02
2
+
3
+ * Use Hoe >= 2.0.0.
4
+ * Require ronin >= 0.2.4.
5
+ * Require ronin-web >= 0.1.3.
6
+ * Use Ronin::Scanners::Scanner to define the scanner for finding
7
+ Ronin::SQL::Injection objects for URI::HTTP urls.
8
+ * Added more specs.
9
+
1
10
  === 0.2.2 / 2009-01-22
2
11
 
3
12
  * Depend on the new ronin-web library.
data/Manifest.txt CHANGED
@@ -63,11 +63,15 @@ lib/ronin/code/sql/union_clause.rb
63
63
  lib/ronin/code/sql/update.rb
64
64
  lib/ronin/code/sql/values_clause.rb
65
65
  lib/ronin/code/sql/where_clause.rb
66
+ lib/ronin/formatting/sql.rb
67
+ lib/ronin/formatting/extensions/sql.rb
68
+ lib/ronin/formatting/extensions/sql/string.rb
66
69
  lib/ronin/sql/extensions.rb
67
- lib/ronin/sql/extensions/string.rb
68
70
  lib/ronin/sql/extensions/uri.rb
69
71
  lib/ronin/sql/extensions/uri/http.rb
70
72
  lib/ronin/sql/error.rb
73
+ lib/ronin/sql/error/extensions.rb
74
+ lib/ronin/sql/error/extensions/string.rb
71
75
  lib/ronin/sql/error/message.rb
72
76
  lib/ronin/sql/error/pattern.rb
73
77
  lib/ronin/sql/error/error.rb
@@ -97,5 +101,6 @@ spec/code/sql/select_spec.rb
97
101
  spec/code/sql/update_spec.rb
98
102
  spec/code/sql/replace_spec.rb
99
103
  spec/code/sql/delete_spec.rb
104
+ spec/code/sql/common_dialect_spec.rb
100
105
  spec/sql/error_spec.rb
101
- spec/sql/extensions/string_spec.rb
106
+ spec/sql/extensions/uri/http_spec.rb
data/README.txt CHANGED
@@ -45,12 +45,15 @@ of Ronin.
45
45
 
46
46
  == REQUIREMENTS:
47
47
 
48
- * ronin >= 0.1.2
49
- * ronin-web >= 0.1.0
48
+ * {ronin}[http://ronin.rubyforge.org/] >= 0.1.2
49
+ * {ronin-web}[http://ronin.rubyforge.org/web/] >= 0.1.0
50
50
 
51
51
  == INSTALL:
52
52
 
53
- $ sudo gem install ronin-sql
53
+ $ sudo gem install --no-rdoc ronin-sql
54
+
55
+ * Due to a bug in RDoc ronin-sql must be installed with RDoc documentation
56
+ disabled.
54
57
 
55
58
  == EXAMPLES:
56
59
 
data/Rakefile CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'hoe'
5
+ require 'hoe/signing'
5
6
  require './tasks/spec.rb'
6
- require './lib/ronin/sql/version.rb'
7
7
 
8
- Hoe.new('ronin-sql', Ronin::SQL::VERSION) do |p|
9
- p.rubyforge_name = 'ronin'
10
- p.developer('Postmodern','postmodern.mod3@gmail.com')
11
- p.remote_rdoc_dir = 'docs/ronin-sql'
12
- p.extra_deps = [
13
- ['ronin', '>=0.1.4'],
14
- ['ronin-web', '>=0.1.0']
8
+ Hoe.spec('ronin-sql') do
9
+ self.rubyforge_name = 'ronin'
10
+ self.developer('Postmodern','postmodern.mod3@gmail.com')
11
+ self.remote_rdoc_dir = 'docs/ronin-sql'
12
+ self.extra_deps = [
13
+ ['ronin', '>=0.2.4'],
14
+ ['ronin-web', '>=0.1.3']
15
15
  ]
16
16
  end
17
17
 
@@ -33,15 +33,15 @@ module Ronin
33
33
  clause :rename_to, RenameToClause
34
34
  clause :add_column, AddColumnClause
35
35
 
36
- def initialize(options={},&block)
37
- @table = options[:table]
36
+ def initialize(dialect,table=nil,options={},&block)
37
+ @table = table
38
38
 
39
- super(options,&block)
39
+ super(dialect,options,&block)
40
40
  end
41
41
 
42
- def table(name)
43
- @table = name
44
- return self
42
+ def table(name=nil)
43
+ @table = name if name
44
+ return @table
45
45
  end
46
46
 
47
47
  def emit
@@ -50,7 +50,7 @@ module Ronin
50
50
 
51
51
  aggregators :avg, :count, :group_concat, :min, :max, :sum, :total
52
52
 
53
- statement :create_type, CreateTable
53
+ statement :create_table, CreateTable
54
54
  statement :create_index, CreateIndex
55
55
  statement :create_view, CreateView
56
56
  statement :alter_table, AlterTable
@@ -40,16 +40,24 @@ module Ronin
40
40
  super(dialect,options,&block)
41
41
  end
42
42
 
43
- def temp
43
+ def temp!
44
44
  @temp = true
45
45
  return self
46
46
  end
47
47
 
48
- def if_not_exists
48
+ def temp?
49
+ @temp == true
50
+ end
51
+
52
+ def if_not_exists!
49
53
  @if_not_exists = true
50
54
  return self
51
55
  end
52
56
 
57
+ def if_not_exists?
58
+ @if_not_exists == true
59
+ end
60
+
53
61
  def emit
54
62
  tokens = emit_token('CREATE')
55
63
  tokens += emit_token('TEMP') if @temp
@@ -35,9 +35,9 @@ module Ronin
35
35
  super(dialect,'INDEX',index,options,&block)
36
36
  end
37
37
 
38
- def index(name)
39
- @name = name
40
- return self
38
+ def index(name=nil)
39
+ @name = name if name
40
+ return @name
41
41
  end
42
42
 
43
43
  end
@@ -35,9 +35,9 @@ module Ronin
35
35
  super(dialect,'TABLE',table,options,&block)
36
36
  end
37
37
 
38
- def table(name)
39
- @name = name
40
- return self
38
+ def table(name=nil)
39
+ @name = name if name
40
+ return @name
41
41
  end
42
42
 
43
43
  end
@@ -32,9 +32,9 @@ module Ronin
32
32
  super(dialect,'VIEW',view,options,&block)
33
33
  end
34
34
 
35
- def view(name)
36
- @name = name
37
- return self
35
+ def view(name=nil)
36
+ @name = name if name
37
+ return @name
38
38
  end
39
39
 
40
40
  end
@@ -33,12 +33,17 @@ module Ronin
33
33
  clause :from, FromClause
34
34
  clause :where, WhereClause
35
35
 
36
- def initialize(dialect,options={},&block)
37
- @table = options[:table]
36
+ def initialize(dialect,table=nil,options={},&block)
37
+ @table = table
38
38
 
39
39
  super(dialect,options,&block)
40
40
  end
41
41
 
42
+ def table(name=nil)
43
+ @table = name if name
44
+ return @table
45
+ end
46
+
42
47
  def emit
43
48
  emit_token('DELETE FROM') + emit_value(@table)
44
49
  end
@@ -212,7 +212,9 @@ module Ronin
212
212
  type_name = name.upcase
213
213
  supports_length = options[:length]
214
214
 
215
- class_def(name) do |length|
215
+ class_def(name) do |*arguments|
216
+ length = arguments.first
217
+
216
218
  if (supports_length && length)
217
219
  Token.new("#{type_name}(#{length})")
218
220
  else
@@ -32,9 +32,9 @@ module Ronin
32
32
  super(dialect,'INDEX',index,options,&block)
33
33
  end
34
34
 
35
- def index(name)
36
- @name = name
37
- return self
35
+ def index(name=nil)
36
+ @name = name if name
37
+ return @name
38
38
  end
39
39
 
40
40
  end
@@ -32,9 +32,9 @@ module Ronin
32
32
  super(dialect,'TABLE',table,options,&block)
33
33
  end
34
34
 
35
- def table(name)
36
- @name = name
37
- return self
35
+ def table(name=nil)
36
+ @name = name if name
37
+ return @name
38
38
  end
39
39
 
40
40
  end
@@ -32,9 +32,9 @@ module Ronin
32
32
  super(dialect,'VIEW',view,options,&block)
33
33
  end
34
34
 
35
- def view(name)
36
- @name = name
37
- return self
35
+ def view(name=nil)
36
+ @name = name if name
37
+ return @name
38
38
  end
39
39
 
40
40
  end
@@ -35,15 +35,15 @@ module Ronin
35
35
  clause :default_values, DefaultValuesClause
36
36
  clause :values, ValuesClause
37
37
 
38
- def initialize(dialect,options={},&block)
39
- @table = options[:table]
38
+ def initialize(dialect,table=nil,options={},&block)
39
+ @table = table
40
40
 
41
41
  super(dialect,options,&block)
42
42
  end
43
43
 
44
- def table(name)
45
- @table = name
46
- return value
44
+ def table(name=nil)
45
+ @table = name if name
46
+ return @table
47
47
  end
48
48
 
49
49
  def emit
@@ -23,7 +23,8 @@
23
23
 
24
24
  require 'ronin/code/sql/dialect'
25
25
  require 'ronin/code/sql/common_dialect'
26
- require 'ronin/chars/char_set'
26
+
27
+ require 'chars/char_set'
27
28
 
28
29
  module Ronin
29
30
  module Code
@@ -52,11 +52,16 @@ module Ronin
52
52
  clause :union_all, UnionAllClause
53
53
 
54
54
  def initialize(dialect,options={},&block)
55
- @distinct_rows = options[:distinct_rows]
56
- @all_rows = options[:all_rows]
57
-
58
55
  super(dialect,options)
59
56
 
57
+ if options[:distinct_rows]
58
+ self.distinct_rows!
59
+ end
60
+
61
+ if options[:all_rows]
62
+ self.all_rows!
63
+ end
64
+
60
65
  unless options[:fields]
61
66
  fields(all)
62
67
  end
@@ -64,16 +69,24 @@ module Ronin
64
69
  instance_eval(&block) if block
65
70
  end
66
71
 
67
- def all_rows
72
+ def all_rows!
68
73
  @all_rows = true
69
74
  return self
70
75
  end
71
76
 
72
- def distinct_rows
77
+ def all_rows?
78
+ @all_rows == true
79
+ end
80
+
81
+ def distinct_rows!
73
82
  @distinct_rows = true
74
83
  return self
75
84
  end
76
85
 
86
+ def distinct_rows?
87
+ @distinct_rows == true
88
+ end
89
+
77
90
  def emit
78
91
  tokens = emit_token('SELECT')
79
92
 
@@ -39,9 +39,9 @@ module Ronin
39
39
  super(dialect,options,&block)
40
40
  end
41
41
 
42
- def table(value)
43
- @table = value
44
- return self
42
+ def table(name=nil)
43
+ @table = name if name
44
+ return @table
45
45
  end
46
46
 
47
47
  def emit
@@ -0,0 +1,69 @@
1
+ #
2
+ #--
3
+ # Ronin SQL - A Ronin library providing support for SQL related security
4
+ # tasks.
5
+ #
6
+ # Copyright (c) 2007-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #++
22
+ #
23
+
24
+ class String
25
+
26
+ #
27
+ # Returns the SQL hex-string encoded form of the String.
28
+ #
29
+ # "/etc/passwd".sql_encode
30
+ # # => "0x2f6574632f706173737764"
31
+ #
32
+ def sql_encode
33
+ return '' if empty?
34
+
35
+ hex_string = '0x'
36
+
37
+ each_byte do |b|
38
+ hex_string << ('%.2x' % b)
39
+ end
40
+
41
+ return hex_string
42
+ end
43
+
44
+ #
45
+ # Returns the SQL decoded form of the String.
46
+ #
47
+ # "'Conan O''Brian'".sql_decode
48
+ # # => "Conan O'Brian"
49
+ #
50
+ # "0x2f6574632f706173737764".sql_decode
51
+ # # => "/etc/passwd"
52
+ #
53
+ def sql_decode
54
+ if ((self[0...2] == '0x') && (length % 2 == 0))
55
+ raw = ''
56
+
57
+ self[2..-1].scan(/[0-9a-fA-F]{2}/).each do |hex_char|
58
+ raw << hex_char.hex.chr
59
+ end
60
+
61
+ return raw
62
+ elsif (self[0..0] == "'" && self[-1..-1] == "'")
63
+ self[1..-2].gsub(/\\'/,"'").gsub(/''/,"'")
64
+ else
65
+ return self
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,24 @@
1
+ #
2
+ #--
3
+ # Ronin SQL - A Ronin library providing support for SQL related security
4
+ # tasks.
5
+ #
6
+ # Copyright (c) 2007-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #++
22
+ #
23
+
24
+ require 'ronin/formatting/extensions/sql/string'
@@ -0,0 +1,24 @@
1
+ #
2
+ #--
3
+ # Ronin SQL - A Ronin library providing support for SQL related security
4
+ # tasks.
5
+ #
6
+ # Copyright (c) 2007-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #++
22
+ #
23
+
24
+ require 'ronin/formatting/extensions/sql'
@@ -62,11 +62,11 @@ class String
62
62
  #
63
63
  def sql_error?(options={})
64
64
  if options[:dialect]
65
- patterns = Error.patterns_for_dialect(options[:dialect])
65
+ patterns = Ronin::SQL::Error.patterns_for_dialect(options[:dialect])
66
66
  elsif options[:types]
67
- patterns = Error.patterns_for(*options[:types])
67
+ patterns = Ronin::SQL::Error.patterns_for(*options[:types])
68
68
  else
69
- patterns = Error.patterns.values
69
+ patterns = Ronin::SQL::Error.patterns.values
70
70
  end
71
71
 
72
72
  patterns.each do |pattern|
@@ -76,47 +76,4 @@ class String
76
76
  return false
77
77
  end
78
78
 
79
- #
80
- # Returns the SQL hex-string encoded form of the String.
81
- #
82
- # "/etc/passwd".sql_encode
83
- # # => "0x2f6574632f706173737764"
84
- #
85
- def sql_encode
86
- return '' if empty?
87
-
88
- hex_string = '0x'
89
-
90
- each_byte do |b|
91
- hex_string << ('%.2x' % b)
92
- end
93
-
94
- return hex_string
95
- end
96
-
97
- #
98
- # Returns the SQL decoded form of the String.
99
- #
100
- # "'Conan O''Brian'".sql_decode
101
- # # => "Conan O'Brian"
102
- #
103
- # "0x2f6574632f706173737764".sql_decode
104
- # # => "/etc/passwd"
105
- #
106
- def sql_decode
107
- if ((self[0...2] == '0x') && (length % 2 == 0))
108
- raw = ''
109
-
110
- self[2..-1].scan(/[0-9a-fA-F]{2}/).each do |hex_char|
111
- raw << hex_char.hex.chr
112
- end
113
-
114
- return raw
115
- elsif (self[0..0] == "'" && self[-1..-1] == "'")
116
- self[1..-2].gsub(/\\'/,"'").gsub(/''/,"'")
117
- else
118
- return self
119
- end
120
- end
121
-
122
79
  end
@@ -0,0 +1,24 @@
1
+ #
2
+ #--
3
+ # Ronin SQL - A Ronin library providing support for SQL related security
4
+ # tasks.
5
+ #
6
+ # Copyright (c) 2007-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #++
22
+ #
23
+
24
+ require 'ronin/sql/error/extensions/string'
@@ -28,6 +28,7 @@ module Ronin
28
28
  module Error
29
29
  Error.pattern :ms_sql do |p|
30
30
  p.dialect = :ms
31
+ p.recognize /Microsoft SQL Native Client/
31
32
  p.recognize /Microsoft OLE DB Provider for SQL Server/
32
33
  p.recognize /Microsoft OLE DB Provider for ODBC Drivers.*\[Microsoft\]\[ODBC SQL Server Driver\]/
33
34
  end
@@ -25,3 +25,4 @@ require 'ronin/sql/error/message'
25
25
  require 'ronin/sql/error/pattern'
26
26
  require 'ronin/sql/error/error'
27
27
  require 'ronin/sql/error/patterns'
28
+ require 'ronin/sql/error/extensions'
@@ -22,12 +22,14 @@
22
22
  #
23
23
 
24
24
  require 'ronin/sql/injection'
25
+ require 'ronin/scanners/scanner'
25
26
  require 'ronin/extensions/uri/http'
26
- require 'ronin/chars'
27
27
 
28
28
  module URI
29
29
  class HTTP < Generic
30
30
 
31
+ include Ronin::Scanners::Scanner
32
+
31
33
  #
32
34
  # Tests the +query_params+ of the HTTP URL with the given _options_ for
33
35
  # SQL errors.
@@ -39,9 +41,9 @@ module URI
39
41
  errors = {}
40
42
 
41
43
  return each_query_param do |param,value|
42
- error = SQL::Injection.new(self,param).error(options)
44
+ mesg = Ronin::SQL::Injection.new(self,param).error(options)
43
45
 
44
- errors[param] = error if error
46
+ errors[param] = mesg if mesg
45
47
  end
46
48
 
47
49
  return errors
@@ -66,10 +68,8 @@ module URI
66
68
  # Tests the +query_params+ of the HTTP URL with the given _options_ for
67
69
  # blind SQL injections.
68
70
  #
69
- def sql_injections(options={})
70
- injectable = []
71
-
72
- each_query_param do |param,value|
71
+ scanner(:sqli) do |url,results,options|
72
+ url.each_query_param do |param,value|
73
73
  integer_tests = [
74
74
  {:escape => value},
75
75
  {:escape => value, :close_parenthesis => true}
@@ -80,7 +80,7 @@ module URI
80
80
  {:escape => value, :close_string => true, :close_parenthesis => true}
81
81
  ]
82
82
 
83
- if (value && Chars.numeric =~ value)
83
+ if (value && value =~ /^[0-9]+$/)
84
84
  # if the param value is numeric, we should try escaping a
85
85
  # numeric value first.
86
86
  tests = integer_tests + string_tests
@@ -91,34 +91,19 @@ module URI
91
91
  end
92
92
 
93
93
  tests.each do |test|
94
- inj = Ronin::SQL::Injection.new(self,param,options.merge(test))
94
+ inj = Ronin::SQL::Injection.new(url,param,options.merge(test))
95
95
 
96
96
  if inj.vulnerable?(options)
97
- injectable << inj
97
+ results.call(inj)
98
98
  break
99
99
  end
100
100
  end
101
101
  end
102
-
103
- return injectable
104
- end
105
-
106
- #
107
- # Returns the first vulnerable SQL injection object found in the
108
- # HTTP URL.
109
- #
110
- def sql_injection(options={})
111
- sql_injections(options).first
112
102
  end
113
103
 
114
- #
115
- # Returns +true+ if any of the +query_params+ of the HTTP URL are
116
- # vulnerable to blind SQL injection using the given _options_, returns
117
- # +false+ otherwise.
118
- #
119
- def has_sql_injections?(options={})
120
- !(sql_injections(options).empty?)
121
- end
104
+ alias sql_injections sqli_scan
105
+ alias sql_injection first_sqli
106
+ alias has_sql_injections? has_sqli?
122
107
 
123
108
  end
124
109
  end
@@ -21,5 +21,4 @@
21
21
  #++
22
22
  #
23
23
 
24
- require 'ronin/sql/extensions/string'
25
24
  require 'ronin/sql/extensions/uri'
@@ -28,12 +28,14 @@ require 'ronin/extensions/uri'
28
28
  require 'ronin/web/extensions/nokogiri'
29
29
  require 'ronin/web/spider'
30
30
 
31
+ require 'parameters'
31
32
  require 'nokogiri'
32
33
 
33
34
  module Ronin
34
35
  module SQL
35
36
  class Injection
36
37
 
38
+ include Parameters
37
39
  include Sessions::HTTP
38
40
 
39
41
  # The URL to inject upon
@@ -24,6 +24,6 @@
24
24
  module Ronin
25
25
  module SQL
26
26
  # Ronin SQL version
27
- VERSION = '0.2.2'
27
+ VERSION = '0.2.3'
28
28
  end
29
29
  end
data/lib/ronin/sql.rb CHANGED
@@ -21,7 +21,6 @@
21
21
  #++
22
22
  #
23
23
 
24
- require 'ronin/code/sql'
25
24
  require 'ronin/sql/extensions'
26
25
  require 'ronin/sql/error'
27
26
  require 'ronin/sql/injection'
@@ -0,0 +1,205 @@
1
+ require 'ronin/code/sql/common_dialect'
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Code::SQL::CommonDialect do
6
+ before(:all) do
7
+ @dialect = Code::SQL::CommonDialect.new
8
+ end
9
+
10
+ it "should provide the 'yes' primitive" do
11
+ token = @dialect.yes
12
+
13
+ token.class.should == Code::SQL::Token
14
+ token.to_s.should == 'yes'
15
+ end
16
+
17
+ it "should provide the 'no' primitive" do
18
+ token = @dialect.no
19
+
20
+ token.class.should == Code::SQL::Token
21
+ token.to_s.should == 'no'
22
+ end
23
+
24
+ it "should provide the 'on' primitive" do
25
+ token = @dialect.on
26
+
27
+ token.class.should == Code::SQL::Token
28
+ token.to_s.should == 'on'
29
+ end
30
+
31
+ it "should provide the 'off' primitive" do
32
+ token = @dialect.off
33
+
34
+ token.class.should == Code::SQL::Token
35
+ token.to_s.should == 'off'
36
+ end
37
+
38
+ it "should provide the 'null' primitive" do
39
+ token = @dialect.null
40
+
41
+ token.class.should == Code::SQL::Token
42
+ token.to_s.should == 'null'
43
+ end
44
+
45
+ it "should provide the 'int' data-type" do
46
+ token = @dialect.int
47
+
48
+ token.class.should == Code::SQL::Token
49
+ token.to_s.should == 'INT'
50
+ end
51
+
52
+ it "should provide the 'varchar' data-type" do
53
+ token = @dialect.varchar
54
+
55
+ token.class.should == Code::SQL::Token
56
+ token.to_s.should == 'VARCHAR'
57
+ end
58
+
59
+ it "should provide the 'varchar' data-type with specific length" do
60
+ token = @dialect.varchar(15)
61
+
62
+ token.class.should == Code::SQL::Token
63
+ token.to_s.should == 'VARCHAR(15)'
64
+ end
65
+
66
+ it "should provide the 'text' data-type" do
67
+ token = @dialect.text
68
+
69
+ token.class.should == Code::SQL::Token
70
+ token.to_s.should == 'TEXT'
71
+ end
72
+
73
+ it "should provide the 'record' data-type" do
74
+ token = @dialect.record
75
+
76
+ token.class.should == Code::SQL::Token
77
+ token.to_s.should == 'RECORD'
78
+ end
79
+
80
+ it "should provide the 'avg' function" do
81
+ func = @dialect.avg(:salary)
82
+
83
+ func.name.should == :avg
84
+ func.fields.should == [:salary]
85
+ end
86
+
87
+ it "should provide the 'count' function" do
88
+ func = @dialect.count(:id)
89
+
90
+ func.name.should == :count
91
+ func.fields.should == [:id]
92
+ end
93
+
94
+ it "should provide the 'group_concat' function" do
95
+ func = @dialect.group_concat(:id)
96
+
97
+ func.name.should == :group_concat
98
+ func.fields.should == [:id]
99
+ end
100
+
101
+ it "should provide the 'min' function" do
102
+ func = @dialect.min(:salary)
103
+
104
+ func.name.should == :min
105
+ func.fields.should == [:salary]
106
+ end
107
+
108
+ it "should provide the 'max' function" do
109
+ func = @dialect.max(:salary)
110
+
111
+ func.name.should == :max
112
+ func.fields.should == [:salary]
113
+ end
114
+
115
+ it "should provide the 'sum' function" do
116
+ func = @dialect.sum(:salary)
117
+
118
+ func.name.should == :sum
119
+ func.fields.should == [:salary]
120
+ end
121
+
122
+ it "should provide the 'total' function" do
123
+ func = @dialect.total(:salary)
124
+
125
+ func.name.should == :total
126
+ func.fields.should == [:salary]
127
+ end
128
+
129
+ it "should provide the 'create table' statement" do
130
+ stmt = @dialect.create_table(:users)
131
+
132
+ stmt.class.should == Code::SQL::CreateTable
133
+ stmt.table.should == :users
134
+ end
135
+
136
+ it "should provide the 'create index' statement" do
137
+ stmt = @dialect.create_index(:users_index)
138
+
139
+ stmt.class.should == Code::SQL::CreateIndex
140
+ stmt.index.should == :users_index
141
+ end
142
+
143
+ it "should provide the 'create view' statement" do
144
+ stmt = @dialect.create_view(:users_view)
145
+
146
+ stmt.class.should == Code::SQL::CreateView
147
+ stmt.view.should == :users_view
148
+ end
149
+
150
+ it "should provide the 'alter table' statement" do
151
+ stmt = @dialect.alter_table(:users)
152
+
153
+ stmt.class.should == Code::SQL::AlterTable
154
+ stmt.table.should == :users
155
+ end
156
+
157
+ it "should provide the 'insert' statement" do
158
+ stmt = @dialect.insert(:users)
159
+
160
+ stmt.class.should == Code::SQL::Insert
161
+ stmt.table.should == :users
162
+ end
163
+
164
+ it "should provide the 'select' statement" do
165
+ stmt = @dialect.select(:from => :users)
166
+
167
+ stmt.class.should == Code::SQL::Select
168
+ stmt.from.table.should == :users
169
+ end
170
+
171
+ it "should provide the 'update' statement" do
172
+ stmt = @dialect.update(:users)
173
+
174
+ stmt.class.should == Code::SQL::Update
175
+ stmt.table.should == :users
176
+ end
177
+
178
+ it "should provide the 'delete' statement" do
179
+ stmt = @dialect.delete(:users)
180
+
181
+ stmt.class.should == Code::SQL::Delete
182
+ stmt.table.should == :users
183
+ end
184
+
185
+ it "should provide the 'drop table' statement" do
186
+ stmt = @dialect.drop_table(:users)
187
+
188
+ stmt.class.should == Code::SQL::DropTable
189
+ stmt.table.should == :users
190
+ end
191
+
192
+ it "should provide the 'drop index' statement" do
193
+ stmt = @dialect.drop_index(:users_index)
194
+
195
+ stmt.class.should == Code::SQL::DropIndex
196
+ stmt.index.should == :users_index
197
+ end
198
+
199
+ it "should provide the 'drop view' statement" do
200
+ stmt = @dialect.drop_view(:users_view)
201
+
202
+ stmt.class.should == Code::SQL::DropView
203
+ stmt.view.should == :users_view
204
+ end
205
+ end
@@ -8,12 +8,12 @@ shared_examples_for "Create" do
8
8
  it_should_behave_like "has a fields clause"
9
9
 
10
10
  it "should have a temp option" do
11
- @sql.temp
12
- @sql.instance_variable_get('@temp').should == true
11
+ @sql.temp!
12
+ @sql.should be_temp
13
13
  end
14
14
 
15
15
  it "should have a if_not_exists option" do
16
- @sql.if_not_exists
17
- @sql.instance_variable_get('@if_not_exists').should == true
16
+ @sql.if_not_exists!
17
+ @sql.should be_if_not_exists
18
18
  end
19
19
  end
@@ -94,12 +94,12 @@ describe Select do
94
94
  end
95
95
 
96
96
  it "should have an all rows option" do
97
- @sql.all_rows
98
- @sql.instance_variable_get('@all_rows').should == true
97
+ @sql.all_rows!
98
+ @sql.should be_all_rows
99
99
  end
100
100
 
101
101
  it "should have an distinct rows option" do
102
- @sql.distinct_rows
103
- @sql.instance_variable_get('@distinct_rows').should == true
102
+ @sql.distinct_rows!
103
+ @sql.should be_distinct_rows
104
104
  end
105
105
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'rubygems'
2
- gem 'rspec', '>=1.1.3'
2
+ gem 'rspec', '>=1.1.12'
3
3
  require 'spec'
4
4
 
5
+ require 'ronin/sql/version'
6
+
5
7
  include Ronin
@@ -0,0 +1,34 @@
1
+ require 'ronin/sql/extensions/uri/http'
2
+
3
+ require 'spec_helper'
4
+
5
+ describe URI::HTTP do
6
+ before(:all) do
7
+ @url = URI('http://testasp.acunetix.com/showthread.asp?id=2')
8
+ end
9
+
10
+ it "should determine which query params have SQL errors" do
11
+ @url.sql_errors.should == {'id' => '2'}
12
+ end
13
+
14
+ it "should find all SQL injections" do
15
+ injections = @url.sql_injections
16
+ injection = injections.first
17
+
18
+ injections.length.should == 1
19
+
20
+ injection.param.should == 'id'
21
+ injection.sql_options[:escape].should == '2'
22
+ end
23
+
24
+ it "should find the first working SQL injection" do
25
+ injection = @url.sql_injection
26
+
27
+ injection.param.should == 'id'
28
+ injection.sql_options[:escape].should == '2'
29
+ end
30
+
31
+ it "should determine if a URL is vulnerable to SQL injection" do
32
+ @url.has_sql_injections?.should == true
33
+ end
34
+ end
data.tar.gz.sig ADDED
@@ -0,0 +1 @@
1
+ Ȩ�f�^U��78�pF��Xg��lȘ&��"�[���"�����h���t�5oa~@x���Q�F�l�x��&� ͻó*��5>�Y�_:䭕����p��o�0xe4�U����(�d��T����4й��� �a�ɱ��Kd�1�D�k\0�^��c� �W�"��:`��^e�,�ی���c[�����*W)��8l|���J��E-,�Kt�n__W5��c���s�����u@ �M)���1c�#6��`��
metadata CHANGED
@@ -1,15 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ronin-sql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain: []
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDQDCCAiigAwIBAgIBADANBgkqhkiG9w0BAQUFADBGMRgwFgYDVQQDDA9wb3N0
14
+ bW9kZXJuLm1vZDMxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixk
15
+ ARkWA2NvbTAeFw0wOTA2MDMwNDU5MDNaFw0xMDA2MDMwNDU5MDNaMEYxGDAWBgNV
16
+ BAMMD3Bvc3Rtb2Rlcm4ubW9kMzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYK
17
+ CZImiZPyLGQBGRYDY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
18
+ 1wvANkTDHFgVih5XLjuTwTZjgBq1lBGybXJiH6Id1lY2JOMqM5FB1DDHVvvij94i
19
+ mJabN0zkzu6VKWC70y0IwOxY7CPokr0eFdK/D0y7mCq1P8QITv76i2YqAl0eYqIt
20
+ W+IhIkANQ7E6uMZIZcdnfadC6lPAtlKkqtd9crvRbFgr6e3kyflmohbRnTEJHoRd
21
+ 7SHHsybE6DSn7oTDs6XBTNrNIn5VfZA0z01eeos/+zBm1zKJOK2+/7xtLLDuDU9G
22
+ +Rd+ltUBbvxUrMNZmDG29pnmN2xTRH+Q8HxD2AxlvM5SRpK6OeZaHV7PaCCAVZ4L
23
+ T9BFl1sfMvRlABeGEkSyuQIDAQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE
24
+ sDAdBgNVHQ4EFgQUKwsd+PqEYmBvyaTyoL+uRuk+PhEwDQYJKoZIhvcNAQEFBQAD
25
+ ggEBAB4TvHsrlbcXcKg6gX5BIb9tI+zGkpzo0Z7jnxMEcNO7NGGwmzafDBI/xZYv
26
+ xkRH3/HXbGGYDOi6Q6gWt5GujSx0bOImDtYTJTH8jnzN92HzEK5WdScm1QpZKF1e
27
+ cezArMbxbSPaosxTCtG6LQTkE28lFQsmFZ5xzouugS4h5+LVJiVMmiP+l3EfkjFa
28
+ GOURU+rNEMPWo8MCWivGW7jes6BMzWHcW7DQ0scNVmIcCIgdyMmpscuAEOSeghy9
29
+ /fFs57Ey2OXBL55nDOyvN/ZQ2Vab05UH4t+GCxjAPeirzL/29FBtePT6VD44c38j
30
+ pDj+ws7QjtH/Qcrr1l9jfN0ehDs=
31
+ -----END CERTIFICATE-----
11
32
 
12
- date: 2009-01-22 00:00:00 -08:00
33
+ date: 2009-07-08 00:00:00 -07:00
13
34
  default_executable:
14
35
  dependencies:
15
36
  - !ruby/object:Gem::Dependency
@@ -20,7 +41,7 @@ dependencies:
20
41
  requirements:
21
42
  - - ">="
22
43
  - !ruby/object:Gem::Version
23
- version: 0.1.4
44
+ version: 0.2.4
24
45
  version:
25
46
  - !ruby/object:Gem::Dependency
26
47
  name: ronin-web
@@ -30,7 +51,7 @@ dependencies:
30
51
  requirements:
31
52
  - - ">="
32
53
  - !ruby/object:Gem::Version
33
- version: 0.1.0
54
+ version: 0.1.3
34
55
  version:
35
56
  - !ruby/object:Gem::Dependency
36
57
  name: hoe
@@ -40,9 +61,15 @@ dependencies:
40
61
  requirements:
41
62
  - - ">="
42
63
  - !ruby/object:Gem::Version
43
- version: 1.8.3
64
+ version: 2.3.2
44
65
  version:
45
- description: Ronin SQL is a Ruby library for Ronin that provids support for SQL related security tasks. Ronin is a Ruby platform designed for information security and data exploration tasks. Ronin allows for the rapid development and distribution of code over many of the common Source-Code-Management (SCM) systems.
66
+ description: |-
67
+ Ronin SQL is a Ruby library for Ronin that provids support for SQL related
68
+ security tasks.
69
+
70
+ Ronin is a Ruby platform designed for information security and data
71
+ exploration tasks. Ronin allows for the rapid development and distribution
72
+ of code over many of the common Source-Code-Management (SCM) systems.
46
73
  email:
47
74
  - postmodern.mod3@gmail.com
48
75
  executables: []
@@ -119,11 +146,15 @@ files:
119
146
  - lib/ronin/code/sql/update.rb
120
147
  - lib/ronin/code/sql/values_clause.rb
121
148
  - lib/ronin/code/sql/where_clause.rb
149
+ - lib/ronin/formatting/sql.rb
150
+ - lib/ronin/formatting/extensions/sql.rb
151
+ - lib/ronin/formatting/extensions/sql/string.rb
122
152
  - lib/ronin/sql/extensions.rb
123
- - lib/ronin/sql/extensions/string.rb
124
153
  - lib/ronin/sql/extensions/uri.rb
125
154
  - lib/ronin/sql/extensions/uri/http.rb
126
155
  - lib/ronin/sql/error.rb
156
+ - lib/ronin/sql/error/extensions.rb
157
+ - lib/ronin/sql/error/extensions/string.rb
127
158
  - lib/ronin/sql/error/message.rb
128
159
  - lib/ronin/sql/error/pattern.rb
129
160
  - lib/ronin/sql/error/error.rb
@@ -153,10 +184,13 @@ files:
153
184
  - spec/code/sql/update_spec.rb
154
185
  - spec/code/sql/replace_spec.rb
155
186
  - spec/code/sql/delete_spec.rb
187
+ - spec/code/sql/common_dialect_spec.rb
156
188
  - spec/sql/error_spec.rb
157
- - spec/sql/extensions/string_spec.rb
189
+ - spec/sql/extensions/uri/http_spec.rb
158
190
  has_rdoc: true
159
191
  homepage: http://ronin.rubyforge.org/sql/
192
+ licenses: []
193
+
160
194
  post_install_message:
161
195
  rdoc_options:
162
196
  - --main
@@ -178,9 +212,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
212
  requirements: []
179
213
 
180
214
  rubyforge_project: ronin
181
- rubygems_version: 1.3.1
215
+ rubygems_version: 1.3.4
182
216
  signing_key:
183
- specification_version: 2
217
+ specification_version: 3
184
218
  summary: Ronin SQL is a Ruby library for Ronin that provids support for SQL related security tasks
185
219
  test_files: []
186
220
 
metadata.gz.sig ADDED
@@ -0,0 +1,4 @@
1
+ �Z� ��d�L�u�dT�H�1�QP�A��U���]��E�w߸K��&a�t����AL��@�{�`����v�~�”Y{` ���$9i��\$�C�S�'������O�/�۔ka�e�\U3��&O�E��p�X���L�a_ �����Q��>�l*=����������E����c��`�T/$���1�:
2
+ OB&��S*���_T>�.�
3
+ �&���eX����v�k����2KC�6'_��e�
4
+ ��
@@ -1,28 +0,0 @@
1
- require 'ronin/sql/extensions/string'
2
-
3
- require 'spec_helper'
4
-
5
- describe String do
6
- describe "SQL-hex encoding" do
7
- it "should be able to be SQL-hex encoded" do
8
- '/etc/passwd'.sql_encode.should == '0x2f6574632f706173737764'
9
- end
10
-
11
- it "should return an empty String if empty" do
12
- ''.sql_encode.should == ''
13
- end
14
- end
15
-
16
- describe "SQL-hex decoding" do
17
- it "should be able to be SQL-hex decoded" do
18
- encoded = '/etc/passwd'.sql_encode
19
-
20
- encoded.should == '0x2f6574632f706173737764'
21
- encoded.sql_decode.should == '/etc/passwd'
22
- end
23
-
24
- it "should be able to decode SQL comma-escaping" do
25
- "'Conan O''Brian'".sql_decode.should == "Conan O'Brian"
26
- end
27
- end
28
- end