ronin-code-sql 2.0.0.beta1
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.
- checksums.yaml +7 -0
- data/.document +4 -0
- data/.editorconfig +11 -0
- data/.github/workflows/ruby.yml +27 -0
- data/.gitignore +11 -0
- data/.mailmap +1 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +104 -0
- data/Gemfile +28 -0
- data/README.md +212 -0
- data/Rakefile +30 -0
- data/gemspec.yml +25 -0
- data/lib/ronin/code/sql/binary_expr.rb +53 -0
- data/lib/ronin/code/sql/clause.rb +74 -0
- data/lib/ronin/code/sql/clauses.rb +310 -0
- data/lib/ronin/code/sql/emittable.rb +88 -0
- data/lib/ronin/code/sql/emitter.rb +406 -0
- data/lib/ronin/code/sql/field.rb +110 -0
- data/lib/ronin/code/sql/fields.rb +82 -0
- data/lib/ronin/code/sql/function.rb +53 -0
- data/lib/ronin/code/sql/functions.rb +1265 -0
- data/lib/ronin/code/sql/injection.rb +168 -0
- data/lib/ronin/code/sql/injection_expr.rb +113 -0
- data/lib/ronin/code/sql/literal.rb +40 -0
- data/lib/ronin/code/sql/literals.rb +83 -0
- data/lib/ronin/code/sql/operators.rb +384 -0
- data/lib/ronin/code/sql/statement.rb +72 -0
- data/lib/ronin/code/sql/statement_list.rb +112 -0
- data/lib/ronin/code/sql/statements.rb +117 -0
- data/lib/ronin/code/sql/unary_expr.rb +38 -0
- data/lib/ronin/code/sql/version.rb +28 -0
- data/lib/ronin/code/sql.rb +96 -0
- data/ronin-code-sql.gemspec +62 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/sql/binary_expr_examples.rb +25 -0
- data/spec/sql/binary_expr_spec.rb +5 -0
- data/spec/sql/clause_examples.rb +43 -0
- data/spec/sql/clause_spec.rb +31 -0
- data/spec/sql/clauses_spec.rb +47 -0
- data/spec/sql/emittable_spec.rb +41 -0
- data/spec/sql/emitter_spec.rb +533 -0
- data/spec/sql/field_spec.rb +103 -0
- data/spec/sql/fields_spec.rb +40 -0
- data/spec/sql/function_examples.rb +30 -0
- data/spec/sql/function_spec.rb +25 -0
- data/spec/sql/functions_spec.rb +113 -0
- data/spec/sql/injection_expr_spec.rb +98 -0
- data/spec/sql/injection_spec.rb +172 -0
- data/spec/sql/literal_spec.rb +5 -0
- data/spec/sql/literals_spec.rb +46 -0
- data/spec/sql/operators_spec.rb +44 -0
- data/spec/sql/statement_examples.rb +39 -0
- data/spec/sql/statement_list_spec.rb +48 -0
- data/spec/sql/statement_spec.rb +38 -0
- data/spec/sql/statements_spec.rb +22 -0
- data/spec/sql/unary_expr_examples.rb +20 -0
- data/spec/sql/unary_expr_spec.rb +5 -0
- data/spec/sql_spec.rb +18 -0
- metadata +157 -0
@@ -0,0 +1,168 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-code-sql - A Ruby DSL for crafting SQL Injections.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-code-sql is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-code-sql is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-code-sql. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/code/sql/literals'
|
22
|
+
require 'ronin/code/sql/clauses'
|
23
|
+
require 'ronin/code/sql/injection_expr'
|
24
|
+
require 'ronin/code/sql/statement_list'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module Code
|
28
|
+
module SQL
|
29
|
+
#
|
30
|
+
# Represents a SQL injection (SQLi).
|
31
|
+
#
|
32
|
+
# @api public
|
33
|
+
#
|
34
|
+
# @see http://en.wikipedia.org/wiki/SQL_injection
|
35
|
+
#
|
36
|
+
class Injection < StatementList
|
37
|
+
|
38
|
+
include Literals
|
39
|
+
include Clauses
|
40
|
+
|
41
|
+
# Default place holder values.
|
42
|
+
PLACE_HOLDERS = {
|
43
|
+
integer: 1,
|
44
|
+
decimal: 1.0,
|
45
|
+
string: '1',
|
46
|
+
list: [nil],
|
47
|
+
column: :id
|
48
|
+
}
|
49
|
+
|
50
|
+
# The type of element to escape out of
|
51
|
+
#
|
52
|
+
# @return [:integer, :decimal, :string, :column]
|
53
|
+
attr_reader :escape
|
54
|
+
|
55
|
+
# The expression that will be injected
|
56
|
+
#
|
57
|
+
# @return [InjectionExpr]
|
58
|
+
attr_reader :expression
|
59
|
+
|
60
|
+
#
|
61
|
+
# Initializes a new SQL injection.
|
62
|
+
#
|
63
|
+
# @param [:integer, :decimal, :string, :column] escape
|
64
|
+
# The type of element to escape out of.
|
65
|
+
#
|
66
|
+
# @param [String, Symbol, Integer] place_holder
|
67
|
+
# Place-holder data.
|
68
|
+
#
|
69
|
+
# @yield [(injection)]
|
70
|
+
# If a block is given, it will be evaluated within the injection.
|
71
|
+
# If the block accepts an argument, the block will be called with the
|
72
|
+
# new injection.
|
73
|
+
#
|
74
|
+
# @yieldparam [Injection] injection
|
75
|
+
# The new injection.
|
76
|
+
#
|
77
|
+
def initialize(escape: :integer,
|
78
|
+
place_holder: PLACE_HOLDERS.fetch(escape),
|
79
|
+
&block)
|
80
|
+
@escape = escape
|
81
|
+
@expression = InjectionExpr.new(place_holder)
|
82
|
+
|
83
|
+
super(&block)
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Appends an `AND` expression to the injection.
|
88
|
+
#
|
89
|
+
# @yield [(expr)]
|
90
|
+
# The return value of the block will be used as the right-hand side
|
91
|
+
# operand. If the block accepts an argument, it will be called with
|
92
|
+
# the injection.
|
93
|
+
#
|
94
|
+
# @yieldparam [InjectionExpr] expr
|
95
|
+
#
|
96
|
+
# @return [self]
|
97
|
+
#
|
98
|
+
def and(&block)
|
99
|
+
@expression.and(&block)
|
100
|
+
return self
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Appends an `OR` expression to the injection.
|
105
|
+
#
|
106
|
+
# @yield [(expr)]
|
107
|
+
# The return value of the block will be used as the right-hand side
|
108
|
+
# operand. If the block accepts an argument, it will be called with
|
109
|
+
# the injection expression.
|
110
|
+
#
|
111
|
+
# @yieldparam [InjectionExpr] expr
|
112
|
+
#
|
113
|
+
# @return [self]
|
114
|
+
#
|
115
|
+
def or(&block)
|
116
|
+
@expression.or(&block)
|
117
|
+
return self
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
# Converts the SQL injection to SQL.
|
122
|
+
#
|
123
|
+
# @param [Boolean] terminate
|
124
|
+
# Specifies whether to terminate the injection with `;--`.
|
125
|
+
#
|
126
|
+
# @param [Hash{Symbol => Object}] kwargs
|
127
|
+
# Additional keyword arguments for {Emitter#initialize}.
|
128
|
+
#
|
129
|
+
# @return [String]
|
130
|
+
# The raw SQL.
|
131
|
+
#
|
132
|
+
def to_sql(terminate: false, **kwargs)
|
133
|
+
emitter = emitter(**kwargs)
|
134
|
+
sql = @expression.to_sql(**kwargs)
|
135
|
+
|
136
|
+
unless clauses.empty?
|
137
|
+
sql << emitter.space << emitter.emit_clauses(clauses)
|
138
|
+
end
|
139
|
+
|
140
|
+
unless statements.empty?
|
141
|
+
sql << ';' << emitter.space << emitter.emit_statement_list(self)
|
142
|
+
end
|
143
|
+
|
144
|
+
case @escape
|
145
|
+
when :string, :list
|
146
|
+
if (terminate || (sql[0,1] != sql[-1,1]))
|
147
|
+
# terminate the expression
|
148
|
+
sql << ';--'
|
149
|
+
else
|
150
|
+
sql = sql[0..-2]
|
151
|
+
end
|
152
|
+
|
153
|
+
# balance the quotes
|
154
|
+
sql = sql[1..-1]
|
155
|
+
else
|
156
|
+
if terminate
|
157
|
+
# terminate the expression
|
158
|
+
sql << ';--'
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
return sql
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-code-sql - A Ruby DSL for crafting SQL Injections.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-code-sql is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-code-sql is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-code-sql. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/code/sql/binary_expr'
|
22
|
+
require 'ronin/code/sql/literals'
|
23
|
+
require 'ronin/code/sql/fields'
|
24
|
+
require 'ronin/code/sql/functions'
|
25
|
+
require 'ronin/code/sql/statements'
|
26
|
+
require 'ronin/code/sql/emittable'
|
27
|
+
|
28
|
+
module Ronin
|
29
|
+
module Code
|
30
|
+
module SQL
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
#
|
34
|
+
# @since 1.1.0
|
35
|
+
#
|
36
|
+
class InjectionExpr
|
37
|
+
|
38
|
+
include Literals
|
39
|
+
include Fields
|
40
|
+
include Functions
|
41
|
+
include Statements
|
42
|
+
include Emittable
|
43
|
+
|
44
|
+
# The expression that will be injected
|
45
|
+
attr_reader :expression
|
46
|
+
|
47
|
+
#
|
48
|
+
# Initializes the new expression to inject.
|
49
|
+
#
|
50
|
+
# @param [String, Integer, Float, Array, Symbol] initial_value
|
51
|
+
# The initial value for the expression.
|
52
|
+
#
|
53
|
+
def initialize(initial_value)
|
54
|
+
@expression = initial_value
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Appends an `AND` expression to the injection.
|
59
|
+
#
|
60
|
+
# @yield [(self)]
|
61
|
+
# The return value of the block will be used as the right-hand side
|
62
|
+
# operand. If the block accepts an argument, it will be called with
|
63
|
+
# the injection expression.
|
64
|
+
#
|
65
|
+
# @return [self]
|
66
|
+
#
|
67
|
+
def and(&block)
|
68
|
+
value = case block.arity
|
69
|
+
when 0 then instance_eval(&block)
|
70
|
+
else block.call(self)
|
71
|
+
end
|
72
|
+
|
73
|
+
@expression = BinaryExpr.new(@expression,:AND,value)
|
74
|
+
return self
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Appends an `OR` expression to the injection.
|
79
|
+
#
|
80
|
+
# @yield [(self)]
|
81
|
+
# The return value of the block will be used as the right-hand side
|
82
|
+
# operand. If the block accepts an argument, it will be called with
|
83
|
+
# the injection expression.
|
84
|
+
#
|
85
|
+
# @return [self]
|
86
|
+
#
|
87
|
+
def or(&block)
|
88
|
+
value = case block.arity
|
89
|
+
when 0 then instance_eval(&block)
|
90
|
+
else block.call(self)
|
91
|
+
end
|
92
|
+
|
93
|
+
@expression = BinaryExpr.new(@expression,:OR,value)
|
94
|
+
return self
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Emits the injection expression.
|
99
|
+
#
|
100
|
+
# @param [Hash{Symbol => Object}] kwargs
|
101
|
+
# Additional keyword arguments for {Emitter#initialize}.
|
102
|
+
#
|
103
|
+
# @return [String]
|
104
|
+
# The raw SQL.
|
105
|
+
#
|
106
|
+
def to_sql(**kwargs)
|
107
|
+
emitter(**kwargs).emit(@expression)
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-code-sql - A Ruby DSL for crafting SQL Injections.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-code-sql is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-code-sql is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-code-sql. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/code/sql/emittable'
|
22
|
+
require 'ronin/code/sql/operators'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module Code
|
26
|
+
module SQL
|
27
|
+
#
|
28
|
+
# Represents SQL literals.
|
29
|
+
#
|
30
|
+
# @api semipublic
|
31
|
+
#
|
32
|
+
class Literal < Struct.new(:value)
|
33
|
+
|
34
|
+
include Operators
|
35
|
+
include Emittable
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-code-sql - A Ruby DSL for crafting SQL Injections.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-code-sql is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-code-sql is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-code-sql. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/code/sql/literal'
|
22
|
+
|
23
|
+
module Ronin
|
24
|
+
module Code
|
25
|
+
module SQL
|
26
|
+
#
|
27
|
+
# Methods for creating SQL {Literals Literal}.
|
28
|
+
#
|
29
|
+
# @api public
|
30
|
+
#
|
31
|
+
module Literals
|
32
|
+
#
|
33
|
+
# Creates a `NULL` literal.
|
34
|
+
#
|
35
|
+
# @return [Literal]
|
36
|
+
# The `NULL` literal.
|
37
|
+
#
|
38
|
+
def null
|
39
|
+
Literal.new(:NULL)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Creates an Integer literal.
|
44
|
+
#
|
45
|
+
# @param [String, Numeric] value
|
46
|
+
# The value to convert to an Integer.
|
47
|
+
#
|
48
|
+
# @return [Literal<Integer>]
|
49
|
+
# The Integer literal.
|
50
|
+
#
|
51
|
+
def int(value)
|
52
|
+
Literal.new(value.to_i)
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Creates an Float literal.
|
57
|
+
#
|
58
|
+
# @param [String, Numeric] value
|
59
|
+
# The value to convert to a Float.
|
60
|
+
#
|
61
|
+
# @return [Literal<Float>]
|
62
|
+
# The Float literal.
|
63
|
+
#
|
64
|
+
def float(value)
|
65
|
+
Literal.new(value.to_f)
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Creates an String literal.
|
70
|
+
#
|
71
|
+
# @param [String, Numeric] value
|
72
|
+
# The value to convert to a String.
|
73
|
+
#
|
74
|
+
# @return [Literal<String>]
|
75
|
+
# The String literal.
|
76
|
+
#
|
77
|
+
def string(value)
|
78
|
+
Literal.new(value.to_s)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|