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.
- data/History.txt +9 -0
- data/Manifest.txt +7 -2
- data/README.txt +6 -3
- data/Rakefile +8 -8
- data/lib/ronin/code/sql/alter_table.rb +6 -6
- data/lib/ronin/code/sql/common_dialect.rb +1 -1
- data/lib/ronin/code/sql/create.rb +10 -2
- data/lib/ronin/code/sql/create_index.rb +3 -3
- data/lib/ronin/code/sql/create_table.rb +3 -3
- data/lib/ronin/code/sql/create_view.rb +3 -3
- data/lib/ronin/code/sql/delete.rb +7 -2
- data/lib/ronin/code/sql/dialect.rb +3 -1
- data/lib/ronin/code/sql/drop_index.rb +3 -3
- data/lib/ronin/code/sql/drop_table.rb +3 -3
- data/lib/ronin/code/sql/drop_view.rb +3 -3
- data/lib/ronin/code/sql/insert.rb +5 -5
- data/lib/ronin/code/sql/program.rb +2 -1
- data/lib/ronin/code/sql/select.rb +18 -5
- data/lib/ronin/code/sql/update.rb +3 -3
- data/lib/ronin/formatting/extensions/sql/string.rb +69 -0
- data/lib/ronin/formatting/extensions/sql.rb +24 -0
- data/lib/ronin/formatting/sql.rb +24 -0
- data/lib/ronin/sql/{extensions → error/extensions}/string.rb +3 -46
- data/lib/ronin/sql/error/extensions.rb +24 -0
- data/lib/ronin/sql/error/patterns.rb +1 -0
- data/lib/ronin/sql/error.rb +1 -0
- data/lib/ronin/sql/extensions/uri/http.rb +13 -28
- data/lib/ronin/sql/extensions.rb +0 -1
- data/lib/ronin/sql/injection.rb +2 -0
- data/lib/ronin/sql/version.rb +1 -1
- data/lib/ronin/sql.rb +0 -1
- data/spec/code/sql/common_dialect_spec.rb +205 -0
- data/spec/code/sql/create_examples.rb +4 -4
- data/spec/code/sql/select_spec.rb +4 -4
- data/spec/spec_helper.rb +3 -1
- data/spec/sql/extensions/uri/http_spec.rb +34 -0
- data.tar.gz.sig +1 -0
- metadata +45 -11
- metadata.gz.sig +4 -0
- 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/
|
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.
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
['ronin', '>=0.
|
14
|
-
['ronin-web', '>=0.1.
|
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 =
|
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
|
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 :
|
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
|
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
|
@@ -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 =
|
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 |
|
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
|
@@ -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 =
|
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
|
44
|
+
def table(name=nil)
|
45
|
+
@table = name if name
|
46
|
+
return @table
|
47
47
|
end
|
48
48
|
|
49
49
|
def emit
|
@@ -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
|
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
|
|
@@ -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
|
data/lib/ronin/sql/error.rb
CHANGED
@@ -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
|
-
|
44
|
+
mesg = Ronin::SQL::Injection.new(self,param).error(options)
|
43
45
|
|
44
|
-
errors[param] =
|
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
|
-
|
70
|
-
|
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 &&
|
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(
|
94
|
+
inj = Ronin::SQL::Injection.new(url,param,options.merge(test))
|
95
95
|
|
96
96
|
if inj.vulnerable?(options)
|
97
|
-
|
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
|
-
|
116
|
-
|
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
|
data/lib/ronin/sql/extensions.rb
CHANGED
data/lib/ronin/sql/injection.rb
CHANGED
@@ -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
|
data/lib/ronin/sql/version.rb
CHANGED
data/lib/ronin/sql.rb
CHANGED
@@ -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.
|
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.
|
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.
|
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.
|
102
|
+
@sql.distinct_rows!
|
103
|
+
@sql.should be_distinct_rows
|
104
104
|
end
|
105
105
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -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.
|
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-
|
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.
|
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.
|
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:
|
64
|
+
version: 2.3.2
|
44
65
|
version:
|
45
|
-
description:
|
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/
|
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.
|
215
|
+
rubygems_version: 1.3.4
|
182
216
|
signing_key:
|
183
|
-
specification_version:
|
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
@@ -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
|