ronin-sql 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|