SQL FullText Indexes and SQL Injection - mysql

Is there any known danger with exposing the use of a FullText index to internal and possibly public users?
Assuming the queries are properly parameterized, is there any way that a user could abuse the inputs to trigger a SQL injection or denial of service attack?
// SQL Server
select * from content_table WHERE CONTAINS((Title, Subtitle, Body), #fullTextSearch);
// MySQL
select * from content_table WHERE MATCH(Title, Subtitle, Body) AGAINST (#fullTextSearch);
// Oracle
select * from content_table WHERE CONTAINS(Body, #fullTextSearch);
The trigger for this question is the large variety of inputs a user could specify and the fact that the different SQL servers have different query syntax and at least some (MySQL) will return a syntax error if an invalid query is specified.
'FORMSOF(INFLECTIONAL, model NEAR airplane)'
'NEAR((term1, term2),5) AND term3'
'NEAR((term1, term2),5) OR NEAR((term3, term4),2, TRUE)'
'+join +(>left <right)'
'electric INPATH (/purchaseOrder/items/item/comment)'

When talking about SQL injection the risk is that someone can introduce SQL keywords into the query itself by adding SQL to a data parameter.
This is why separation of data and query is absolutely critical. This normally plays out by using placeholder values, as in:
SELECT * FROM content_table WHERE MATCH(Title, Subtitle, Body) AGAINST (?);
In the case of search there's often two levels you need to be aware of:
The SQL layer where you're using raw SQL keywords to express the query conditions, such as WHERE x=? AND y=?
The search layer where you're expressing conditions within a string, like WHERE CONTAINS(?) which has a bound data parameter '"computer software" NEAR hardware)'
Note that the second form has a syntax within a string, so if you're exposing that you're not at risk of SQL injection per-se, but you may end up receiving a lot of syntax errors caused by bad user input that you need to handle.
In the first case if you need to compose the query conditions you need to follow the usual rules:
Do not permit:
Inclusion of unknown fields into the query.
Inclusion of unknown operators into the query.
Maintain as strict a separation between query and data as is practical.
You may need to parse the request's data into components that can be recomposed into a SQL query. This can get messy, especially if you're allowing a lot of latitude in how things can be searched, so try and keep it as simple and testable as possible.
If you have unit tests, include one that's deliberately hostile and tries to introduce invalid or injection-type data into the query. Ensure the data is properly contained.
Note: If you're calling a stored procedure using placeholder values, but the stored procedure composes SQL statements using concatenation you're still at risk, so you need to be absolutely certain you're keeping the data separated from the query. If you have a query with zero user data introduced in it there is no risk of SQL injection.

Related

Can mojolicious output the prepared sql query?

Perl Mojolicious use query with placeholder to prevent SQL injection. But the problem is, sometimes I want to see what's the query look like.
Is there a way to print the query with all placeholders replaced with the real values?
I know I can do a replace by myself. But I have to do it every time I want to debug the SQL. It's so cumbersome. If mojolicious has a way like $c->mysql->output_last_sql(), it'll be amazing.
my $sql=q|
SELECT
count(*) cnt
FROM
my_table
WHERE
id= ?
|;
# I know I can do below by myself
print q1|
SELECT
count(*) cnt
FROM
my_table
WHERE
id= $c->param('id')
|;
my $query=$c->mysql->db->query($sql, $c->param('id'));
# how can I print the real SQL with all placeholders replaced?
print $query->hash()->{cnt};
I checked the document of Mojolicious but didn't find anything useful.
https://docs.mojolicious.org/Mojo/Pg/Database
The advantage of query parameters is that they are not simply string-replacements into the SQL query. If they were, they would still cause a risk of SQL injection. The way parameters work is that they are never replaced in your query until after the query is prepared. Parsing occurs during the prepare step, so if parameter values are not combined with the query until after parsing, then there's no way for the values to cause mischief with the SQL syntax.
That means you can't get the SQL combined with its parameters in the client.
The only workaround is to use the query log on the MySQL Server. I give an example here: Getting raw SQL query string from PDO prepared statements. That's about PHP, not Perl, but it works the same regardless of which language you use.
(With exceptions only for client connectors that create fake prepared statements, and actually do interpolate parameters into the SQL string, then send it to the MySQL Server. For example, Python's connector does this by default, for example, but you can optionally make even Python use true prepared statements.)

Can I parameterize a create statement in Go?

Using the Go SQL library we can create SELECT, INSERT, UPDATE and DELETE statements with parameters like this:
db.Query("SELECT * FROM database.table WHERE param = ?", param_value)
I want to create tables from user provided input that describes the table structure, users will be asked for the name of the table and the name and type of each column they want to create. However, building a CREATE statement in the query interface Creating a CREATE statement by concatenating strings together works, but that's a SQL injection attack waiting to happen.
Is there a way to parameterize CREATE statements using the Go SQL library?
SQL query parameters take the place of a scalar value only.
That is, you can use a parameter to substitute only where you would otherwise use a constant quoted string, constant quoted date/time, or constant numeric.
SQL query parameters can't be used for:
Table names, column names, or other identifiers
SQL expressions
Lists of scalar values (like in an IN(...) predicate)
SQL keywords
The proper way to write your app that takes user input which describes table structure is to interpret the user input as a guide, not as literal SQL syntax. Avoid passing user input (or any unsafe content) through to be executed as part of any SQL statement.

SQL injection on autoincrement

I have been looking up SQL injection lately and what they are, what they do and how to stop them. Most place talk about username stored by users in select stamens causing problems such as 'OR 1 but if I was to only use a auto incremented id to select information from a database and not a user input value would this also prevent sql injections?
SQL Injection applies specifically to the shape of the query - it says nothing about queries that can accidentally leak information from other means.
SQL injection is a code injection technique, used to attack data driven applications, in which malicious SQL statements [or expressions] are inserted into an entry field for execution..
Using placeholders eliminates SQL Injection1,
but..
..just because a system is free from SQL Injection does not mean that it is safe from other vulnerabilities.
For instance, imagine this query, where #OWNER represents a placeholder.
select *
from emails
where owner = #OWNER
This query is free from SQL injection, but if an attacker can specify an arbitrary "OWNER" value, then they can access someone else's email - oops! This is just a security vulnerability; not SQL Injection.
1 Use placeholders for all data that comes from variables.
It doesn't matter if it is from the user or not. It doesn't matter if the value is guaranteed to be an integer (even one from an auto-increment column) or not. Just use placeholders consistently - then you'll have cleaner queries and more time to focus on other problems.
Everyone who is looking up on SQL injection, have to understand that there is no way to exploit a non-existent injection. On the other hand, once injection is possible, there is potentially infinite number of possible exploits.
Means one should never care of particular exploits. But always concentrate on making injection impossible.

Mysql Database Attacks other than Sql Injection

I am using mysqli prepared statements and bound variables.
Then to prevent sql injection, am I need to do anything else(eg: data type validation, filtering, sanitize, string escape etc ) with user input ?
Is there any other way of attacking MySql database other than Sql Injection ?
To prevent SQL injection you have to format your query properly.
Every literal that have to be added to the query dynamically, have to be properly formatted.
Not only data literals like strings and numbers but all of them, including operators and identifiers.
The only proper way to make values formatted is prepared statements.
For the identifiers and operators you will need also filtering, to let only allowed ones into query.
Whatever user input should not be involved at all. It's destination, not source that matters.
Is there any other way of attacking MySql database other than Sql Injection ?
sure thing. But the topic is too broad to make you secured by means of a forum post. Better hire a DBA.

What is the MySQL session variable equivalent to Sybase ASE's APPLICATIONNAME?

APPLICATIONNAME in Sybase is used in information schema queries (current connections, slow queries, etc.), so the results contian not just a thread/process id, but a more human readable description of the application responsible for the given query.
Is there an equivalent to it in mysql? My google fu failed me
On an SQL email list (sq-l at list.prog.hu) I got the answer that no, this is not supported on MySQL, but a relatively common workaround is to prefix each SQL statement with a descriptive comment identifying the issuing application.
E.g.:
/* cms_blog_module */ select * from blog_posts where id = ....
And this way, wherever a query is present, its source is present as well