I have an insert query that I want to execute using the JavaScript V3 AWS client, against an AWS Aurora MySQL Serverless database. I am using the Data API of the database. I got the #aws-sdk/client-rds-data set up in my code and I can connect and execute arbitrary SQL queries using the ExecuteStatementCommand.
What I would like to know is that how I make SQL prepared statements and execute them. I have an INSERT query whose values are user provided. I cannot just concatenate those values into the SQL query as it would create an SQL injection vulnerability.
Unfortunatelly, I couldn't find how to make prepared statements and execute them in the #aws-sdk/client-rds-data package's documentation.
If somebody knows how to do it, could that someone please explain. Big thanks in advance!
I'm not a user of the AWS SDK for client-rds-data, but I'm inferring the following from the documentation, and my own knowledge of MySQL.
I see that interface ExecuteSqlCommandInput has a property sqlStatements, which allows multiple SQL statements separated by semicolons. This precludes the use of query parameters, because in MySQL you can't use prepare() on a string that includes multiple SQL statements.
Whereas ExecuteStatementCommandInput has a property sql (a single statement) and a property parameters which is an array of scalar parameters (i.e. each scalar corresponds to one parameter placeholder in the sql string). This should allow you to run a parameterized SQL query.
Re your comment: When you said you wanted to use prepared statements to avoid SQL injection vulnerabilities, I assumed you understood how prepared statements protect against those vulnerabilities.
In fact, using prepared statements alone is not a defense. You have to separate dynamic inputs from your SQL query by using query parameters. It just happens that using query parameters requires using prepared statements, so people say "use prepared statements" to defend against SQL injection, when they should say "use query parameters, which implies you must use prepared statements."
Tutorials about using SQL with query parameters are abundant. Here's one for Node.js: https://www.veracode.com/blog/secure-development/how-prevent-sql-injection-nodejs
The calling convention for the AWS SDK is different, but the concept is the same. I have only found reference documentation for AWS SDK, no code examples or task-oriented documentation. This is disappointing but unfortunately typical for AWS.
Related
According to Node.js' mysql package documentation:
In order to avoid SQL Injection attacks, you should always escape any user provided data before using it inside a SQL query. You can do so using the mysql.escape(), connection.escape() or pool.escape() methods.
I cannot find any documentation / reference to using prepared statements with mysql, except for in a reference to using '?' characters. It states the following:
Alternatively, you can use ? characters as placeholders for values you would like to have escaped...
This looks similar to prepared statements in MySQL, however it really
just uses the same connection.escape() method internally.
From my experience with talking to other developers, the general consensus in the developer community is that prepared statements are the ONLY safe way to perform mysql queries from Node.js however, as you can see with the mysql package, there is no obvious support for prepared statements. However, it is indicated that their method for avoiding SQL injection is via the usage of the escape functions.
My Question:
Are the escape functions in the mysql package sufficient enough to securely query a mysql database (without the use of prepared statements)?
Escaping is actually just as safe as using parameterized queries, if you do it consistently.
But it's recommended to use parameters because it makes your code simpler. Therefore developers are probably more likely to do it.
If the Node.js library makes it just as convenient as parameters, but implements it internally by modifying query strings, replacing the ? marks with the parameter values, then you're good.
For what it's worth, Python's MySQL driver does this too, and also PHP's PDO extension when the "emulate prepares" option is in effect. As long as those libraries are well-tested, it should be safe.
FWIW, both escaping and parameters is limited in SQL injection prevention, because in both cases, you can only protect values that you would combine with your SQL query. You cannot protect identifiers (like table names, or column names), or SQL keywords, or expressions, etc. In these cases, just be careful that you have vetted any dynamic content before combining it with your SQL query.
See also:
Preventing SQL injection in Node.js
Difference between real_escape_string and prepare()?
As this document says prepared statements are server side statements like functions or procedures (correct me if I'm wrong).
But I have some trouble finding defined prepared statement on my database. I'm currently working with MySQL Workbench and in the left side pane I can see all my procedures and functions and I can't see any of defined prepared statements here.
So is there any query which I can use to get their names?
The doc says
A prepared statement is specific to the session in which it was created. If you terminate a session without deallocating a previously prepared statement, the server deallocates it automatically.
So Prepared Statements get deleted automtically after the session ends. Besides, a Prepared Statement does not have a name It is just a query string.
I mean for security. Does converting to/from JSON objects help any with MySQLi?
My intention is to use MySQLi statements and send/receive everything as JSON objects (in order to in the future allow Android to use the same calls and queries.)
My only focus on this question is the security side of it. Do I need prepared statements if I'm converting everything to and from JSON objects for a MySQL database.
It doesn't matter what kind of data you are storing in the database. To prevent against SQL injection you need to parameterize all variable input in your SQL. It makes no difference where this data comes from. It doesn't matter what it is.
There is no reason not to use prepared statements. Seriously, not a single reason why you should not use prepared statements 100% of the time, even for constant queries.
Remember though, that prepared statements do not protect against SQL injection. Only the parameters help. Use placeholders in your SQL and bind the data separately. Do this always.
I'm coming from an Oracle world where I can use DBMS_SQL for dynamic SQL with an unknown number of bind variables. Apparently this is not possible in MySQL. So my question is how do you protect against SQL Injection in MySQL? I thought this would be easy to lookup but every example I find is with PHP & MySQL. I'm only dealing with MySQL stored procedures, no PHP. Here is a snippet:
set #sql_string=concat(#sql_string,'col1=''',someRandomText,''' where col2=''',moreRandomText,''';');
Is there a protection function that could be applied to someRandomText to prevent SQL Injection (http://bobby-tables.com/)?
Thanks!
All of the examples I've found show how to use query by sql statement, as: 'connection.query("select * from my_table",...)', but I want to do it without sql statement, but with store procedure.
I found something about 'db-mysql' that supplies this option but I didn't success installing it.
I don't want to use sql statement in my code.
I want to select, update etc. by stored procedures in my mysqldatabase (like C#).
How can I do it?
Checkout http://sequelizejs.com/ it is a node compatible orm which allows you to easily interface with sql without needing to use sql statements.