Skip to content
This repository has been archived by the owner on Dec 27, 2020. It is now read-only.

Prepared statements are expensive. #67

Open
lithdew opened this issue May 18, 2020 · 10 comments
Open

Prepared statements are expensive. #67

lithdew opened this issue May 18, 2020 · 10 comments

Comments

@lithdew
Copy link

lithdew commented May 18, 2020

statement, err := tx.Prepare(
fmt.Sprintf(`
INSERT INTO "%s" ("%s", "%s")
VALUES ($1, $2);

Prepared statements should only be prepared once during initialization as they are expensive to make. They should be cleaned up upon graceful shutdown of the application.

Also, for best practices, do not use fmt.Sprintf in any manner for formatting out SQL queries (there are many ways this may expose the ability for one to perform SQL injection). Provide table names and column names as typed parameters that are to be escaped by the query engine.

@magicoder10
Copy link
Member

@lithdew I thought parameterized queries are only vulnerable if the hacker can inject in the variables.

@magicoder10
Copy link
Member

@lithdew Will I be wasting resources if I never use the prepared the statement?

@magicoder10
Copy link
Member

@lithdew Thank you so much for the suggestions! I enjoyed those kinds of technical discussion.

@lithdew
Copy link
Author

lithdew commented May 18, 2020

@lithdew I thought parameterized queries are only vulnerable if the hacker can inject in the variables.

Misconfiguration can also lead to possible injection of variables.

@lithdew
Copy link
Author

lithdew commented May 18, 2020

@lithdew Will I be wasting resources if I never use the prepared the statement?

A minimal amount: it's better to only instantiate a prepared statement once throughout an application lifecycle.

@oatovar
Copy link

oatovar commented May 18, 2020

@lithdew I thought parameterized queries are only vulnerable if the hacker can inject in the variables.

Misconfiguration can also lead to possible injection of variables.

Can you elaborate more on a scenario where this could be introduced? At first glance the source of the input, would have to be updated and merged into the repo where code review should catch it.

@magicoder10
Copy link
Member

@lithdew I see. Are You trying to avoid people from accidentally passing params into fmt?

@magicoder10
Copy link
Member

magicoder10 commented May 18, 2020

@oatovar Can be problematic if the code reviewer is reviewing the code at 3 AM in the early morning.

@magicoder10
Copy link
Member

@lithdew From my research, prepare will send the query to the db ahead of time and stream the data later on to prevent SQL injection.

@lithdew
Copy link
Author

lithdew commented May 18, 2020

@lithdew From my research, prepare will send the query to the db ahead of time and stream the data later on to prevent SQL injection.

Right, this is why instantiating a prepared statement should ideally only be done once. Otherwise, there is no benefit to using prepared statements.

The issue of SQL injection is that should an attacker be able to pass in any parameters for either the table or table column names, they would be able to pass in arbitrary SQL queries.

Instantiating the prepared statement once on startup is a good countermeasure for this, since the prepared statement won't change during runtime. On top of that, it is just best practice to not use string formatting methods like fmt.Sprintf to lay out sensitive strings like SQL statements. You should take advantage of the underlying SQL engine's ability to 'escape' parameters provided to execute a SQL statement using named/anonymous parameters ('?', '$1').

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants