ronin-sql 0.1.1 → 0.2.0
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 +43 -0
- data/Manifest.txt +76 -23
- data/README.txt +31 -6
- data/Rakefile +2 -2
- data/lib/ronin/code/sql/{keyword.rb → add_column_clause.rb} +9 -13
- data/lib/ronin/code/sql/as.rb +47 -0
- data/lib/ronin/code/sql/asc.rb +38 -0
- data/lib/ronin/code/sql/between.rb +18 -12
- data/lib/ronin/code/sql/binary_expr.rb +12 -5
- data/lib/ronin/code/sql/clause.rb +37 -0
- data/lib/ronin/code/sql/code.rb +1 -1
- data/lib/ronin/code/sql/common_dialect.rb +16 -10
- data/lib/ronin/code/sql/create.rb +68 -0
- data/lib/ronin/code/sql/create_index.rb +9 -39
- data/lib/ronin/code/sql/create_table.rb +9 -56
- data/lib/ronin/code/sql/create_view.rb +7 -29
- data/lib/ronin/code/sql/default_values_clause.rb +38 -0
- data/lib/ronin/code/sql/delete.rb +10 -25
- data/lib/ronin/code/sql/desc.rb +38 -0
- data/lib/ronin/code/sql/dialect.rb +172 -52
- data/lib/ronin/code/sql/{builder.rb → drop.rb} +16 -20
- data/lib/ronin/code/sql/drop_index.rb +43 -0
- data/lib/ronin/code/sql/drop_table.rb +8 -16
- data/lib/ronin/code/sql/drop_view.rb +43 -0
- data/lib/ronin/code/sql/emittable.rb +102 -0
- data/lib/ronin/code/sql/exceptions/unknown_clause.rb +31 -0
- data/lib/ronin/code/sql/exceptions/unknown_dialect.rb +2 -2
- data/lib/ronin/code/sql/exceptions/unknown_statement.rb +31 -0
- data/lib/ronin/code/sql/exceptions.rb +3 -1
- data/lib/ronin/code/sql/expr.rb +7 -96
- data/lib/ronin/code/sql/field.rb +40 -23
- data/lib/ronin/code/sql/fields_clause.rb +48 -0
- data/lib/ronin/code/sql/from_clause.rb +44 -0
- data/lib/ronin/code/sql/function.rb +15 -12
- data/lib/ronin/code/sql/group_by_clause.rb +48 -0
- data/lib/ronin/code/sql/having_clause.rb +48 -0
- data/lib/ronin/code/sql/in.rb +9 -9
- data/lib/ronin/code/sql/injected_statement.rb +102 -0
- data/lib/ronin/code/sql/injection.rb +171 -5
- data/lib/ronin/code/sql/insert.rb +15 -45
- data/lib/ronin/code/sql/intersect_clause.rb +44 -0
- data/lib/ronin/code/sql/join_clause.rb +125 -0
- data/lib/ronin/code/sql/{like_expr.rb → like.rb} +19 -31
- data/lib/ronin/code/sql/limit_clause.rb +44 -0
- data/lib/ronin/code/sql/modifier.rb +50 -0
- data/lib/ronin/code/sql/offset_clause.rb +44 -0
- data/lib/ronin/code/sql/on_clause.rb +57 -0
- data/lib/ronin/code/sql/order_by_clause.rb +44 -0
- data/lib/ronin/code/sql/program.rb +170 -23
- data/lib/ronin/code/sql/rename_to_clause.rb +44 -0
- data/lib/ronin/code/sql/replace.rb +15 -17
- data/lib/ronin/code/sql/select.rb +46 -141
- data/lib/ronin/code/sql/set_clause.rb +44 -0
- data/lib/ronin/code/sql/statement.rb +117 -47
- data/lib/ronin/code/sql/token.rb +64 -0
- data/lib/ronin/code/sql/unary_expr.rb +9 -5
- data/lib/ronin/code/sql/union_all_clause.rb +44 -0
- data/lib/ronin/code/sql/union_clause.rb +44 -0
- data/lib/ronin/code/sql/update.rb +10 -31
- data/lib/ronin/code/sql/values_clause.rb +48 -0
- data/lib/ronin/code/sql/where_clause.rb +44 -0
- data/lib/ronin/code/sql.rb +1 -1
- data/lib/ronin/sql/error/error.rb +64 -0
- data/lib/ronin/sql/error/message.rb +64 -0
- data/lib/ronin/sql/error/pattern.rb +106 -0
- data/lib/ronin/sql/error/patterns.rb +100 -0
- data/lib/ronin/sql/error.rb +5 -30
- data/lib/ronin/sql/extensions/uri/http.rb +76 -21
- data/lib/ronin/sql/extensions/uri.rb +1 -1
- data/lib/ronin/sql/extensions.rb +2 -1
- data/lib/ronin/sql/injection.rb +213 -0
- data/lib/ronin/sql/version.rb +2 -2
- data/lib/ronin/sql.rb +7 -2
- data/spec/code/sql/create_examples.rb +19 -0
- data/spec/code/sql/create_index_spec.rb +25 -0
- data/spec/code/sql/create_table_spec.rb +27 -0
- data/spec/code/sql/create_view_spec.rb +16 -0
- data/spec/code/sql/delete_spec.rb +14 -0
- data/spec/code/sql/drop_examples.rb +10 -0
- data/spec/code/sql/drop_index_spec.rb +16 -0
- data/spec/code/sql/drop_table_spec.rb +16 -0
- data/spec/code/sql/drop_view_spec.rb +16 -0
- data/spec/code/sql/has_default_values_clause_examples.rb +10 -0
- data/spec/code/sql/has_fields_clause_examples.rb +15 -0
- data/spec/code/sql/has_from_clause_examples.rb +13 -0
- data/spec/code/sql/has_values_clause_examples.rb +15 -0
- data/spec/code/sql/has_where_clause_examples.rb +15 -0
- data/spec/code/sql/insert_spec.rb +21 -0
- data/spec/code/sql/replace_spec.rb +21 -0
- data/spec/code/sql/select_spec.rb +105 -0
- data/spec/code/sql/update_spec.rb +26 -0
- data/spec/helpers/code.rb +14 -0
- data/spec/sql/error_spec.rb +24 -0
- data/spec/sql/extensions/string_spec.rb +28 -0
- data/spec/sql_spec.rb +9 -0
- data/tasks/spec.rb +2 -0
- metadata +82 -29
- data/lib/ronin/code/sql/injection_builder.rb +0 -137
- data/lib/ronin/code/sql/injection_style.rb +0 -79
- data/lib/ronin/code/sql/style.rb +0 -170
- data/lib/ronin/sql/sql.rb +0 -83
@@ -0,0 +1,64 @@
|
|
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
|
+
module Ronin
|
25
|
+
module SQL
|
26
|
+
module Error
|
27
|
+
class Message
|
28
|
+
|
29
|
+
# The URL which is vulnerable
|
30
|
+
attr_reader :url
|
31
|
+
|
32
|
+
# The vulnerable query param
|
33
|
+
attr_accessor :param
|
34
|
+
|
35
|
+
# SQL error type
|
36
|
+
attr_reader :type
|
37
|
+
|
38
|
+
# SQL Dialect
|
39
|
+
attr_reader :dialect
|
40
|
+
|
41
|
+
# SQL error message
|
42
|
+
attr_reader :message
|
43
|
+
|
44
|
+
#
|
45
|
+
# Creates a new SQL Error object with the specified _type_,
|
46
|
+
# _dialect_ and _message_.
|
47
|
+
#
|
48
|
+
def initialize(type,dialect,message)
|
49
|
+
@type = type
|
50
|
+
@dialect = dialect
|
51
|
+
@message = message
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Returns the message in String form.
|
56
|
+
#
|
57
|
+
def to_s
|
58
|
+
@message.to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,106 @@
|
|
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/message'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module SQL
|
28
|
+
module Error
|
29
|
+
class Pattern
|
30
|
+
|
31
|
+
# Name of the pattern
|
32
|
+
attr_reader :name
|
33
|
+
|
34
|
+
# Name of the SQL dialect
|
35
|
+
attr_accessor :dialect
|
36
|
+
|
37
|
+
# Patterns to use for matching SQL errors
|
38
|
+
attr_reader :patterns
|
39
|
+
|
40
|
+
#
|
41
|
+
# Creates a new Pattern object with the specified _name_. If a
|
42
|
+
# _block_ is given, it will be passed the newly created Pattern
|
43
|
+
# object.
|
44
|
+
#
|
45
|
+
def initialize(name,&block)
|
46
|
+
@dialect = :common
|
47
|
+
@name = name.to_sym
|
48
|
+
@patterns = []
|
49
|
+
|
50
|
+
block.call(self) if block
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Add the specified _pattern_ to be used to recognize SQL error
|
55
|
+
# messages.
|
56
|
+
#
|
57
|
+
def recognize(pattern)
|
58
|
+
@patterns << pattern
|
59
|
+
return self
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Returns the first match between the error pattern and the
|
64
|
+
# specified _data_. If no matches were found +nil+ will be
|
65
|
+
# returned.
|
66
|
+
#
|
67
|
+
def match(data)
|
68
|
+
data = data.to_s
|
69
|
+
|
70
|
+
@patterns.each do |pattern|
|
71
|
+
match = data.match(pattern)
|
72
|
+
|
73
|
+
return Message.new(@name,@dialect,match[0]) if match
|
74
|
+
end
|
75
|
+
|
76
|
+
return nil
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# Returns the match index within the specified _data_ where a SQL
|
81
|
+
# error Pattern occurs. If no SQL error Pattern can be found within
|
82
|
+
# _data_, +nil+ will be returned.
|
83
|
+
#
|
84
|
+
def =~(data)
|
85
|
+
data = data.to_s
|
86
|
+
|
87
|
+
@patterns.each do |pattern|
|
88
|
+
if (index = (pattern =~ data))
|
89
|
+
return index
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
return nil
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Returns the name of the error pattern.
|
98
|
+
#
|
99
|
+
def to_s
|
100
|
+
@name.to_s
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,100 @@
|
|
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/pattern'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module SQL
|
28
|
+
module Error
|
29
|
+
Error.pattern :ms_sql do |p|
|
30
|
+
p.dialect = :ms
|
31
|
+
p.recognize /Microsoft OLE DB Provider for SQL Server/
|
32
|
+
p.recognize /Microsoft OLE DB Provider for ODBC Drivers.*\[Microsoft\]\[ODBC SQL Server Driver\]/
|
33
|
+
end
|
34
|
+
|
35
|
+
Error.pattern :ms_access do |p|
|
36
|
+
p.dialect = :ms
|
37
|
+
p.recognize /Microsoft OLE DB Provider for ODBC Drivers.*\[Microsoft\]\[ODBC Access Driver\]/
|
38
|
+
p.recognize /\[Microsoft\]\[ODBC Microsoft Access Driver\] Syntax error/
|
39
|
+
end
|
40
|
+
|
41
|
+
Error.pattern :ms_jetdb do |p|
|
42
|
+
p.dialect = :ms
|
43
|
+
p.recognize /Microsoft JET Database Engine/
|
44
|
+
end
|
45
|
+
|
46
|
+
Error.pattern :ms_adodb do |p|
|
47
|
+
p.dialect = :ms
|
48
|
+
p.recognize /ADODB.Command.*error/
|
49
|
+
end
|
50
|
+
|
51
|
+
Error.pattern :asp_net do |p|
|
52
|
+
p.dialect = :common
|
53
|
+
p.recognize /Server Error.*System\.Data\.OleDb\.OleDbException/
|
54
|
+
end
|
55
|
+
|
56
|
+
Error.pattern :mysql do |p|
|
57
|
+
p.dialect = :mysql
|
58
|
+
p.recognize /Warning.*supplied argument is not a valid MySQL result/
|
59
|
+
p.recognize /Warning.*mysql_.*\(\)/
|
60
|
+
p.recognize /You have an error in your SQL syntax.*(on|at) line/
|
61
|
+
end
|
62
|
+
|
63
|
+
Error.pattern :php do |p|
|
64
|
+
p.dialect = :common
|
65
|
+
p.recognize /Warning.*failed to open stream/
|
66
|
+
p.recognize /Fatal Error.*(on|at) line/
|
67
|
+
end
|
68
|
+
|
69
|
+
Error.pattern :oracle do |p|
|
70
|
+
p.dialect = :oracle
|
71
|
+
p.recognize /ORA-[0-9][0-9][0-9][0-9]/
|
72
|
+
end
|
73
|
+
|
74
|
+
Error.pattern :jdbc do |p|
|
75
|
+
p.dialect = :common
|
76
|
+
p.recognize /Invalid SQL statement or JDBC/
|
77
|
+
end
|
78
|
+
|
79
|
+
Error.pattern :java_servlet do |p|
|
80
|
+
p.dialect = :common
|
81
|
+
p.recognize /javax\.servlet\.ServletException/
|
82
|
+
end
|
83
|
+
|
84
|
+
Error.pattern :apache_tomcat do |p|
|
85
|
+
p.dialect = :common
|
86
|
+
p.recognize /org\.apache\.jasper\.JasperException/
|
87
|
+
end
|
88
|
+
|
89
|
+
Error.pattern :vb_runtime do |p|
|
90
|
+
p.dialect = :common
|
91
|
+
p.recognize /Microsoft VBScript runtime/
|
92
|
+
end
|
93
|
+
|
94
|
+
Error.pattern :vb_asp do |p|
|
95
|
+
p.dialect = :common
|
96
|
+
p.recognize /Type mismatch/
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/ronin/sql/error.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Ronin SQL - A Ronin library providing support for SQL related security
|
4
4
|
# tasks.
|
5
5
|
#
|
6
|
-
# Copyright (c) 2007-
|
6
|
+
# Copyright (c) 2007-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
7
|
#
|
8
8
|
# This program is free software; you can redistribute it and/or modify
|
9
9
|
# it under the terms of the GNU General Public License as published by
|
@@ -21,32 +21,7 @@
|
|
21
21
|
#++
|
22
22
|
#
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
# SQL error type
|
29
|
-
attr_reader :type
|
30
|
-
|
31
|
-
# SQL error message
|
32
|
-
attr_reader :message
|
33
|
-
|
34
|
-
#
|
35
|
-
# Creates a new SQL Error object with the specified _type_ and
|
36
|
-
# _message_.
|
37
|
-
#
|
38
|
-
def initialize(type,message)
|
39
|
-
@type = type
|
40
|
-
@message = message
|
41
|
-
end
|
42
|
-
|
43
|
-
#
|
44
|
-
# Returns the message in String form.
|
45
|
-
#
|
46
|
-
def to_s
|
47
|
-
@message.to_s
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
24
|
+
require 'ronin/sql/error/message'
|
25
|
+
require 'ronin/sql/error/pattern'
|
26
|
+
require 'ronin/sql/error/error'
|
27
|
+
require 'ronin/sql/error/patterns'
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Ronin SQL - A Ronin library providing support for SQL related security
|
4
4
|
# tasks.
|
5
5
|
#
|
6
|
-
# Copyright (c) 2007-
|
6
|
+
# Copyright (c) 2007-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
7
|
#
|
8
8
|
# This program is free software; you can redistribute it and/or modify
|
9
9
|
# it under the terms of the GNU General Public License as published by
|
@@ -21,10 +21,9 @@
|
|
21
21
|
#++
|
22
22
|
#
|
23
23
|
|
24
|
-
require 'ronin/sql/
|
25
|
-
require 'ronin/
|
26
|
-
|
27
|
-
require 'uri'
|
24
|
+
require 'ronin/sql/injection'
|
25
|
+
require 'ronin/extensions/uri/http'
|
26
|
+
require 'ronin/chars'
|
28
27
|
|
29
28
|
module URI
|
30
29
|
class HTTP < Generic
|
@@ -34,36 +33,92 @@ module URI
|
|
34
33
|
# SQL errors.
|
35
34
|
#
|
36
35
|
# _options_ may contain the following keys:
|
37
|
-
# <tt>:
|
38
|
-
# <tt>"'"</tt>.
|
39
|
-
# <tt>:types</tt>:: A list of error types to test for. If not specified
|
40
|
-
# all the error patterns in ERROR_PATTERNS will be
|
41
|
-
# tested.
|
36
|
+
# <tt>:sql</tt>:: The SQL injection to use. Defaults to <tt>"'"</tt>.
|
42
37
|
#
|
43
38
|
def sql_errors(options={})
|
44
|
-
|
39
|
+
errors = {}
|
45
40
|
|
46
|
-
return
|
47
|
-
|
41
|
+
return each_query_param do |param,value|
|
42
|
+
error = SQL::Injection.new(self,param).error(options)
|
48
43
|
|
49
|
-
|
44
|
+
errors[param] = error if error
|
50
45
|
end
|
46
|
+
|
47
|
+
return errors
|
48
|
+
end
|
49
|
+
|
50
|
+
def sql_error(options={})
|
51
|
+
sql_errors(options).values.first
|
51
52
|
end
|
52
53
|
|
53
54
|
#
|
54
|
-
#
|
55
|
-
# SQL errors.
|
55
|
+
# Returns +true+ if any of the +query_params+ of the HTTP URI return
|
56
|
+
# SQL errors using the given _options_, returns +false+ otherwise.
|
56
57
|
#
|
57
58
|
# _options_ may contain the following keys:
|
58
|
-
# <tt>:
|
59
|
-
# <tt>"'"</tt>.
|
60
|
-
# <tt>:types</tt>:: A list of error types to test for. If not specified
|
61
|
-
# all the error patterns in ERROR_PATTERNS will be
|
62
|
-
# tested.
|
59
|
+
# <tt>:sql</tt>:: The SQL injection to use. Defaults to <tt>"'"</tt>.
|
63
60
|
#
|
64
61
|
def has_sql_errors?(options={})
|
65
62
|
!(sql_errors(options).empty?)
|
66
63
|
end
|
67
64
|
|
65
|
+
#
|
66
|
+
# Tests the +query_params+ of the HTTP URL with the given _options_ for
|
67
|
+
# blind SQL injections.
|
68
|
+
#
|
69
|
+
def sql_injections(options={})
|
70
|
+
injectable = []
|
71
|
+
|
72
|
+
each_query_param do |param,value|
|
73
|
+
integer_tests = [
|
74
|
+
{:escape => value},
|
75
|
+
{:escape => value, :close_parenthesis => true}
|
76
|
+
]
|
77
|
+
|
78
|
+
string_tests = [
|
79
|
+
{:escape => value, :close_string => true},
|
80
|
+
{:escape => value, :close_string => true, :close_parenthesis => true}
|
81
|
+
]
|
82
|
+
|
83
|
+
if (value && Chars.numeric =~ value)
|
84
|
+
# if the param value is numeric, we should try escaping a
|
85
|
+
# numeric value first.
|
86
|
+
tests = integer_tests + string_tests
|
87
|
+
else
|
88
|
+
# if the param value is a string, we should try escaping a
|
89
|
+
# string value first.
|
90
|
+
tests = string_tests + integer_tests
|
91
|
+
end
|
92
|
+
|
93
|
+
tests.each do |test|
|
94
|
+
inj = Ronin::SQL::Injection.new(self,param,options.merge(test))
|
95
|
+
|
96
|
+
if inj.vulnerable?(options)
|
97
|
+
injectable << inj
|
98
|
+
break
|
99
|
+
end
|
100
|
+
end
|
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
|
+
end
|
113
|
+
|
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
|
122
|
+
|
68
123
|
end
|
69
124
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Ronin SQL - A Ronin library providing support for SQL related security
|
4
4
|
# tasks.
|
5
5
|
#
|
6
|
-
# Copyright (c) 2007-
|
6
|
+
# Copyright (c) 2007-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
7
|
#
|
8
8
|
# This program is free software; you can redistribute it and/or modify
|
9
9
|
# it under the terms of the GNU General Public License as published by
|
data/lib/ronin/sql/extensions.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Ronin SQL - A Ronin library providing support for SQL related security
|
4
4
|
# tasks.
|
5
5
|
#
|
6
|
-
# Copyright (c) 2007-
|
6
|
+
# Copyright (c) 2007-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
7
|
#
|
8
8
|
# This program is free software; you can redistribute it and/or modify
|
9
9
|
# it under the terms of the GNU General Public License as published by
|
@@ -21,4 +21,5 @@
|
|
21
21
|
#++
|
22
22
|
#
|
23
23
|
|
24
|
+
require 'ronin/sql/extensions/string'
|
24
25
|
require 'ronin/sql/extensions/uri'
|
@@ -0,0 +1,213 @@
|
|
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'
|
25
|
+
require 'ronin/code/sql/injection'
|
26
|
+
require 'ronin/sessions/http'
|
27
|
+
require 'ronin/extensions/uri'
|
28
|
+
require 'ronin/web/extensions/hpricot'
|
29
|
+
require 'ronin/web/web'
|
30
|
+
|
31
|
+
module Ronin
|
32
|
+
module SQL
|
33
|
+
class Injection
|
34
|
+
|
35
|
+
include Sessions::HTTP
|
36
|
+
|
37
|
+
# The URL to inject upon
|
38
|
+
attr_reader :url
|
39
|
+
|
40
|
+
# The URL query param to inject into
|
41
|
+
attr_reader :param
|
42
|
+
|
43
|
+
# Options for crafting SQL injections
|
44
|
+
attr_reader :sql_options
|
45
|
+
|
46
|
+
# HTTP request method (either :get or :post)
|
47
|
+
parameter :http_method,
|
48
|
+
:default => :get,
|
49
|
+
:description => 'HTTP request method to use'
|
50
|
+
|
51
|
+
#
|
52
|
+
# Creates a new Injection object with the specified _url_, _param_
|
53
|
+
# to inject upon and the given _options_ which will be used
|
54
|
+
# for crafting SQL injections.
|
55
|
+
#
|
56
|
+
def initialize(url,param,options={})
|
57
|
+
super()
|
58
|
+
|
59
|
+
@url = url
|
60
|
+
@param = param
|
61
|
+
@sql_options = options
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Spider a site starting at the specified _url_ using the given
|
66
|
+
# _options_ and return an Array of URLs which are vulnerable to SQL
|
67
|
+
# Injection. If a _block_ is given, it will be passed vulnerable SQL
|
68
|
+
# Injection objects as they are found.
|
69
|
+
#
|
70
|
+
# Injection.spider('http://www.target.com/contact/')
|
71
|
+
# # => [...]
|
72
|
+
#
|
73
|
+
# Injection.spider('http://www.target.com/') do |injection|
|
74
|
+
# ...
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
def Injection.spider(url,options={},&block)
|
78
|
+
injections = []
|
79
|
+
|
80
|
+
Web.spider_site(url,options) do |spider|
|
81
|
+
spider.every_url_like(/\?[a-zA-Z0-9_]/) do |vuln_url|
|
82
|
+
found = vuln_url.sql_injections
|
83
|
+
|
84
|
+
found.each(&block) if block
|
85
|
+
injections += found
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
return injections
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# Creates a new Code::SQL::Injection object using the given _options_
|
94
|
+
# and _block_. The given _options_ will be merged with the injections
|
95
|
+
# sql_options, to create a tailored Code::SQL::Injection object.
|
96
|
+
#
|
97
|
+
def sql(options={},&block)
|
98
|
+
Code::SQL::Injection.new(@sql_options.merge(options),&block)
|
99
|
+
end
|
100
|
+
|
101
|
+
def inject(options={},&block)
|
102
|
+
injection = (options[:sql] || sql(options,&block))
|
103
|
+
|
104
|
+
injection_url = URI(@url.to_s)
|
105
|
+
injection_url.query_params[@param.to_s] = injection
|
106
|
+
|
107
|
+
request_method = (options[:method] || @http_method)
|
108
|
+
options = options.merge(:url => injection_url)
|
109
|
+
|
110
|
+
if request_method == :post
|
111
|
+
return http_post_body(options)
|
112
|
+
else
|
113
|
+
return http_get_body(options)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def inject_error(options={})
|
118
|
+
inject({:sql => "'"}.merge(options))
|
119
|
+
end
|
120
|
+
|
121
|
+
def error(options={})
|
122
|
+
inject_error(options).sql_error
|
123
|
+
end
|
124
|
+
|
125
|
+
def has_error?(options={})
|
126
|
+
Error.has_message?(inject_error(options))
|
127
|
+
end
|
128
|
+
|
129
|
+
def vulnerable?(options={})
|
130
|
+
body1 = inject(options) { no_rows }
|
131
|
+
body2 = inject(options) { all_rows }
|
132
|
+
|
133
|
+
if (body1.sql_error? || body2.sql_error?)
|
134
|
+
return false
|
135
|
+
end
|
136
|
+
|
137
|
+
body1 = Hpricot(body1)
|
138
|
+
body2 = Hpricot(body2)
|
139
|
+
|
140
|
+
return body1 < body2
|
141
|
+
end
|
142
|
+
|
143
|
+
def has_column?(column,options={})
|
144
|
+
body1 = inject(options)
|
145
|
+
body2 = inject(options.merge(:symbols => {:column => column})) do
|
146
|
+
has_column?(column)
|
147
|
+
end
|
148
|
+
|
149
|
+
if (body1.sql_error? || body2.sql_error?)
|
150
|
+
return false
|
151
|
+
end
|
152
|
+
|
153
|
+
body1 = Hpricot(body1)
|
154
|
+
body2 = Hpricot(body2)
|
155
|
+
|
156
|
+
return body1 == body2
|
157
|
+
end
|
158
|
+
|
159
|
+
def has_table?(table,options={})
|
160
|
+
body1 = inject(options)
|
161
|
+
body2 = inject(options.merge(:symbols => {:table => table})) do
|
162
|
+
has_table?(table)
|
163
|
+
end
|
164
|
+
|
165
|
+
if (body1.sql_error? || body2.sql_error?)
|
166
|
+
return false
|
167
|
+
end
|
168
|
+
|
169
|
+
body1 = Hpricot(body1)
|
170
|
+
body2 = Hpricot(body2)
|
171
|
+
|
172
|
+
return body1 == body2
|
173
|
+
end
|
174
|
+
|
175
|
+
def uses_column?(column,options={})
|
176
|
+
body1 = inject(options)
|
177
|
+
body2 = inject(options.merge(:symbols => {:column => column})) do
|
178
|
+
uses_column?(table)
|
179
|
+
end
|
180
|
+
|
181
|
+
if (body1.sql_error? || body2.sql_error?)
|
182
|
+
return false
|
183
|
+
end
|
184
|
+
|
185
|
+
body1 = Hpricot(body1)
|
186
|
+
body2 = Hpricot(body2)
|
187
|
+
|
188
|
+
return body1 == body2
|
189
|
+
end
|
190
|
+
|
191
|
+
def uses_table?(table,options={})
|
192
|
+
body1 = inject(options)
|
193
|
+
body2 = inject(options.merge(:symbols => {:table => table})) do
|
194
|
+
uses_table?(table)
|
195
|
+
end
|
196
|
+
|
197
|
+
if (body1.sql_error? || body2.sql_error?)
|
198
|
+
return false
|
199
|
+
end
|
200
|
+
|
201
|
+
body1 = Hpricot(body1)
|
202
|
+
body2 = Hpricot(body2)
|
203
|
+
|
204
|
+
return body1 == body2
|
205
|
+
end
|
206
|
+
|
207
|
+
def to_s
|
208
|
+
@url.to_s
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
data/lib/ronin/sql/version.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Ronin SQL - A Ronin library providing support for SQL related security
|
4
4
|
# tasks.
|
5
5
|
#
|
6
|
-
# Copyright (c) 2007-
|
6
|
+
# Copyright (c) 2007-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
7
|
#
|
8
8
|
# This program is free software; you can redistribute it and/or modify
|
9
9
|
# it under the terms of the GNU General Public License as published by
|
@@ -24,6 +24,6 @@
|
|
24
24
|
module Ronin
|
25
25
|
module SQL
|
26
26
|
# Ronin SQL version
|
27
|
-
VERSION = '0.
|
27
|
+
VERSION = '0.2.0'
|
28
28
|
end
|
29
29
|
end
|