Does Knex.js prevent sql injection? - mysql

I'm using a MySql database and was trying to find a MySQL alternative to tedious.js (a SQL server parameterised query builder).I'm using Node.js for my backend.
I read that the .raw() command from knex.js is susceptible to sql injection, if not used with bindings.
But are the other commands and knex.js as a whole safe to use to prevent sql injection? Or am I barking up the wrong tree?

Read carefully from knex documentation how to pass values to knex raw (http://knexjs.org/#Raw).
If you are passing values as parameter binding to raw like:
knex.raw('select * from foo where id = ?', [1])
In that case parameters and query string are passed separately to database driver protecting query from SQL injection.
Other query builder methods always uses binding format internally so they are safe too.
To see how certain query is passed to database driver one can do:
knex('foo').where('id', 1).toSQL().toNative()
Which will output SQL string and bindings that are given to driver for running the query (https://runkit.com/embed/2yhqebv6pte6).
Biggest mistake that one can do with knex raw queries is to use javascript template string and interpolate variables directly to SQL string format like:
knex.raw(`select * from foo where id = ${id}`) // NEVER DO THIS
One thing to note is that knex table/identifier names cannot be passed as bindings to driver, so with those one should be extra careful to not read table / column names from user and use them without properly validating them first.
Edit:
By saying that identifier names cannot be passed as bindings I mean that when one is using ?? knex -binding for identifier name, that will be rendered as part of SQL string when passed to the database driver.

Related

Is it possible to use JOOQ to form a simple string query without creating factory using connection as compile time check is not required?

Is it possible to use JOOQ to form a simple string query without creating factory using connection as compile time check is not required?
I dont want to establish the connection first and generate the classes
Yes you can execute SQL as strings. But you will loose all benefits from code completion will writing queries and the type safety and this is the many advantage of jOOQ over using plain JDBC.
// Create a Query object and execute it:
Query query = create.query("DELETE FROM BOOK");
query.execute();
// Create a ResultQuery object and execute it, fetching results:
ResultQuery<Record> resultQuery = create.resultQuery("SELECT * FROM BOOK");
Result<Record> result = resultQuery.fetch();
Please also checkout the documentation. https://www.jooq.org/doc/3.13/manual-single-page/#sql-execution

"Must declare the scalar variable #Idx" when using a Dapper query on SQL server via OleDb

This code works when the connection is made to an accdb database:
Dim customer = connection.Query(Of Klantgegevens)("Select Actief,Onderhoudscontract From Klantgegevens Where Klantnummer=#Idx", New With {.Idx = customerId}).SingleOrDefault
But the code below gives the error about the Idx parameter when the connection is made to a SQL server database that has a table with the same structure:
Dim customer = connection.Query(Of Klantgegevens)("Select Actief,Onderhoudscontract From [dbo.Klantgegevens] Where Klantnummer=#Idx", New With {.Idx = customerId}).SingleOrDefault
What is going wrong here? I had hoped that by using Dapper I would be able to write database agnostic code. But it seems that is not the case!
If you are using an ODBC/OLEDB connection, then my first suggestion would be: move to SqlClient (SqlConnection). Everything should work fine with SqlConnection.
If you can't do that for some reason - i.e. you're stuck with a provider that doesn't have good support for named parameters - then you might need to tell dapper to use pseudo-positional parameters. Instead of #Idx, use ?Idx?. Dapper interprets this as an instruction to replace ?Idx? with the positional placeholder (simply: ?), using the value from the member Idx.
This is also a good fix for talking to accdb, which has very atypical parameter usage for an ADO.NET provider: it allows named parameter tokens, but all the tokens all replaced with ?, and given values from the positions of the added parameters (not via their names).

Getting the raw SQL query string from the ORM

How do I get the raw SQL string sent to the server from the ORM? How do I intercept it in order to do custom work?
I want to forward the query to a custom driver. My target is MS SQL Server via NodeJS - from a Linux environment.
But I don't want to reinvent the wheel. I want to reuse the existing SqlServer query builder.
As long as your query is not executed by toArray() or something similar, you can use $q->sql() to retrieve the raw sql query that cakePHP will execute:
$q = $this->Model->find('all');
$this->log($q->sql()); // log raw sql query
$query = $this->find();
debug($query);
$query is a query object from where you can get the raw SQL expression.

Insert the input body in a database with the SQL component from Camel

I want to parse the content of xml files and create queries to insert/update some of the xml content in a database.
So far I am able to generate the SQL queries in a processor, populate the body with them, then I would like to run them with the SQL component.
First please let me know if this is not the recommended way to do.
(for instance I feel like the SQL component is meant to run only 1 query).
...
.process(new XmlToSqlProcessor())
.to("sql:${in.body}?dataSource=dataSource")
Doesn't work, ${in.body} is not replaced by its content (meaning the set of queries generated in the processor):
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '${in.body}' at line 1
Should I do all the work in the processor (I wanted to avoid all the database boilerplate though), or maybe use the JDBC component?
If yes can you confirm that the SQL component can only run 1 query and can not parse Simple Expression Language? (I also tried :#${body} that I saw there https://issues.apache.org/jira/browse/CAMEL-7455 but as expected it's considered as a param, not a whole query)
Thanks!
EDIT: after more reading it seems like the SQL component and the JDBC component as well can execute only 1 query. So, having my own processor is apparently the only choice... let me know if I am wrong ;-)
You are right, sql component will execute only 1 query and will not evaluate ${in.body}. You miss two concepts in your route:
Splitter (http://camel.apache.org/splitter.html)
RecipientList
(http://camel.apache.org/recipient-list.html)
Try something like:
...
.process(new XmlToSqlProcessor())
.split().body()
.recipientList(simple("sql:${in.body}?dataSource=dataSource"))

Drupal : How can I know if the db is mysql or postgres

I have a complicated query and since I need that my module work on both mysql and postgres, I need to write two version of it.
Unfortunately, I don't know how I can check if the db I use is mysql or postgres, to know which query use. Do you know if a function can return this value?
As #kordirko says, one option is to query the server version: SELECT version(); will work on both MySQL and PostgreSQL, though not most other database engines.
Parsing version strings is always a bit fragile though, and MySQL returns just a version number like 5.5.32 wheras PostgreSQL returns something like PostgreSQL 9.4devel on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8), 64-bit. What do you do if you're connecting to a PostgreSQL-compatible database like EnterpriseDB Postgres Plus, or a MySQL-compatible database?
It's much safer to use the Drupal function for the purpose, DatabaseConnection::databaseType. This avoids a query round-trip to the DB, will work on databases that won't understand/accept SELECT version(), and will avoid the need to parse version strings.
You'll find this bug report useful; it suggests that the correct usage is Database::getConnection()->databaseType().
(I've never even used Drupal, I just searched for this).
As long as the abstract DatabaseConnection class extends PDO class, you can invoking pdo methods in order to know the current database driver.
For instance:
$conn = Database::getConnection();
print $conn->getAttribute($conn::ATTR_DRIVER_NAME); #returns mysql, pgsql...
There is a second way to do it using DatabaseConnection::driver():
print $conn->driver();
or DatabaseConnection::databaseType();
print $conn->databaseType();
Note that DatabaseConnection::driver() and DatabaseConnection::databaseType() are similar functions but not equals!
The return value from DatabaseConnection::driver() method depends on the implementation and other factors.
in the Drupal Database API page:
database.inc abstract public DatabaseConnection::driver()
This is not necessarily the same as the type of the database itself. For instance, there could be two MySQL drivers, mysql and mysql_mock. This function would return different values for each, but both would return "mysql" for databaseType().
In the most cases you just gonna want to use only
$conn->getAttribute($conn::ATTR_DRIVER_NAME)
or $conn->databaseType()
If you want get more specific properties, you should take advantage the PHP ReflectionClass features:
$conn = Database::getConnection();
$ref = new ReflectionClass($conn);
#ref->getProperties, ref->getConstants $ref->isAbstract...
Reference:
PDO::getAttribute
PDO::ATTR_DRIVER_NAME
Drupal Database API
Drupal Base Database API class