Skip to content

Commit 4258147

Browse files
committed
Swift: Test SQL injection via the SQLite.swift library.
1 parent 964c924 commit 4258147

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,79 @@
11

22
// --- stubs ---
33

4+
public protocol Binding {}
5+
6+
extension String: Binding {}
7+
8+
class Statement {
9+
init(_ connection: Connection, _ SQL: String) throws {}
10+
11+
public func bind(_ values: Binding?...) -> Statement { return Statement() }
12+
public func bind(_ values: [Binding?]) -> Statement { return Statement() }
13+
public func bind(_ values: [String: Binding?]) -> Statement { return Statement() }
14+
15+
@discardableResult public func run(_ bindings: Binding?...) throws -> Statement { return Statement() }
16+
@discardableResult public func run(_ bindings: [Binding?]) throws -> Statement { return Statement() }
17+
@discardableResult public func run(_ bindings: [String: Binding?]) throws -> Statement { return Statement() }
18+
19+
public func scalar(_ bindings: Binding?...) throws -> Binding? { return Binding() }
20+
public func scalar(_ bindings: [Binding?]) throws -> Binding? { return Binding() }
21+
public func scalar(_ bindings: [String: Binding?]) throws -> Binding? { return Binding() }
22+
}
23+
24+
class Connection {
25+
public func execute(_ SQL: String) throws { }
26+
27+
public func prepare(_ statement: String, _ bindings: Binding?...) throws -> Statement { return Statement() }
28+
public func prepare(_ statement: String, _ bindings: [Binding?]) throws -> Statement { return Statement() }
29+
public func prepare(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement { return Statement() }
30+
31+
@discardableResult public func run(_ statement: String, _ bindings: Binding?...) throws -> Statement { return Statement() }
32+
@discardableResult public func run(_ statement: String, _ bindings: [Binding?]) throws -> Statement { return Statement() }
33+
@discardableResult public func run(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement { return Statement() }
34+
35+
public func scalar(_ statement: String, _ bindings: Binding?...) throws -> Binding? { return Binding() }
36+
public func scalar(_ statement: String, _ bindings: [Binding?]) throws -> Binding? { return Binding() }
37+
public func scalar(_ statement: String, _ bindings: [String: Binding?]) throws -> Binding? { return Binding() }
38+
}
39+
40+
func sanitize(_ string: String) -> String { return string }
41+
442
// --- tests ---
43+
44+
func test_sqlite_swift_api(db: Connection) {
45+
let localString = "user"
46+
let remoteString = try! String(contentsOf: URL(string: "http://example.com/")!)
47+
let sanitizedString = sanitize(remoteString)
48+
49+
let unsafeQuery1 = remoteString
50+
let unsafeQuery2 = "SELECT * FROM users WHERE username='" + remoteString + "'"
51+
let unsafeQuery3 = "SELECT * FROM users WHERE username='\(remoteString)'"
52+
let safeQuery1 = "SELECT * FROM users WHERE username='\(localString)'"
53+
let safeQuery2 = "SELECT * FROM users WHERE username='\(sanitizedString)'"
54+
let varQuery = "SELECT * FROM users WHERE username=?"
55+
56+
// --- execute ---
57+
58+
try db.execute(unsafeQuery1) // BAD
59+
try db.execute(unsafeQuery2) // BAD
60+
try db.execute(unsafeQuery3) // BAD
61+
try db.execute(safeQuery1) // GOOD
62+
try db.execute(safeQuery2) // GOOD (sanitized)
63+
64+
// --- prepared statements ---
65+
66+
let stmt1 = try db.prepare(unsafeQuery3) // BAD
67+
try stmt1.run()
68+
69+
let stmt2 = try db.prepare(varQuery, localString) // GOOD
70+
try stmt2.run()
71+
72+
let stmt3 = try db.prepare(varQuery, sanitizedString) // GOOD
73+
try stmt3.run()
74+
75+
let stmt4 = try db.prepare(varQuery, remoteString) // GOOD???
76+
try stmt4.run()
77+
78+
// TODO: test all versions of prepare, run, scalar on Connection and Statement
79+
}

0 commit comments

Comments
 (0)