Skip to content

Commit 9ae9209

Browse files
authored
Fix possible SQL injection issue (#18)
* Add a validation test case for the SQL injection Signed-off-by: Mark Oude Veldhuis <mark.oudeveldhuis@nedap.com> * Raise exception on invalid UUIDs Signed-off-by: Mark Oude Veldhuis <mark.oudeveldhuis@nedap.com> * Stay within 80 chars, add some comments.
1 parent 687a6c1 commit 9ae9209

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

lib/mysql-binuuid/type.rb

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module MySQLBinUUID
2-
class Type < ActiveModel::Type::Binary
2+
class InvalidUUID < StandardError; end
33

4+
class Type < ActiveModel::Type::Binary
45
def type
56
:uuid
67
end
@@ -27,7 +28,16 @@ def cast(value)
2728
# it to the database.
2829
def serialize(value)
2930
return if value.nil?
30-
Data.new(strip_dashes(value))
31+
undashed_uuid = strip_dashes(value)
32+
33+
# To avoid SQL injection, verify that it looks like a UUID. ActiveRecord
34+
# does not explicity escape the Binary data type. escaping is implicit as
35+
# the Binary data type always converts its value to a hex string.
36+
unless valid_undashed_uuid?(undashed_uuid)
37+
raise MySQLBinUUID::InvalidUUID, "#{value} is not a valid UUID"
38+
end
39+
40+
Data.new(undashed_uuid)
3141
end
3242

3343
# We're inheriting from the Binary type since ActiveRecord in that case
@@ -73,5 +83,10 @@ def strip_dashes(uuid)
7383
uuid.delete("-")
7484
end
7585

86+
# Verify that the undashed version of a UUID only contains characters that
87+
# represent a hexadecimal value.
88+
def valid_undashed_uuid?(value)
89+
value =~ /\A[[:xdigit:]]{32}\z/
90+
end
7691
end
7792
end

test/integration/mysql_integration_test.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,24 @@ class MyUuidModelWithValidations < MyUuidModel
112112
assert_equal results.first, @my_model
113113
assert_equal results.first.the_uuid, sample_uuid
114114
end
115+
116+
it "can't be used to inject SQL using .where" do
117+
assert_raises MySQLBinUUID::InvalidUUID do
118+
MyUuidModel.where(the_uuid: "' OR ''='").first
119+
end
120+
end
121+
122+
it "can't be used to inject SQL using .find_by" do
123+
assert_raises MySQLBinUUID::InvalidUUID do
124+
MyUuidModel.find_by(the_uuid: "' OR ''='")
125+
end
126+
end
127+
128+
it "can't be used to inject SQL while creating" do
129+
assert_raises MySQLBinUUID::InvalidUUID do
130+
MyUuidModel.create!(the_uuid: "40' + x'40")
131+
end
132+
end
115133
end
116134

117135
end

0 commit comments

Comments
 (0)