Escaping values in Mysqljs - mysql

https://github.com/mysqljs/mysql#introduction
mysqljs is pretty inconsistent with escaping values, or I am not understanding the docs.
Error:
this.table = 'elections';
mysql.query('SELECT * FROM ? where name = ?', [this.table, this.votesTable]
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax error:
'SELECT * FROM \'elections\' where name = \'prim1000\''
But this works:
`mysql.query('UPDATE elections SET updated_at = ? WHERE name = ?', [this.getTimeStamp(), this.votesTable])
But if I remove "elections" in the query above and put "?" instead it will throw an error. So the following won't work.
mysql.query('UPDATE ? SET updated_at = ? WHERE name = ?', [this.table, this.getTimeStamp(), this.votesTable])

Referring to the documentation page you linked to, under the section "Escaping query identifiers", you should be able to do this:
mysql.query('SELECT * FROM ?? where name = ?', [this.table, this.votesTable]
Most SQL frameworks do not allow parameters to be used for anything besides individual values. I.e. not table identifies, column identifiers, lists of values, or SQL keywords. The mysqljs library is uncommon in that it has support for quoting identifiers and key/value pairs.
Re your comment:
The ?? placeholder is for identifiers. Identifiers must be quoted differently from values. In MySQL, a string value is quoted like 'string' but an identifier is quoted with back-ticks.
SELECT * FROM `mytable` where name = 'myname'
The mysqljs class uses the ?? as a special placeholder for an identifier, so you can tell the class it must be quoted with back-ticks.

Related

how can I avoid sql inject when using "order by case when" in Golang?

there is a param representing userName;
I need to get some sorted records,if column "starred_by" contains 'userPrefix',it should be at the front,others should be at the end.
var userPrefix string; //userPrefix is a Request Param.
usePrefix = `%` + userPrefix + `%`
if userPrefix != "" {
order := fmt.Sprintf("CASE \nWHEN starred_by LIKE %q THEN 1\nELSE 2\nEND", userPrefix)
db = db.Order(order)
}
db = db.Order(otherParam1).Order(otherParam2)
db = db.Model(***).Scan(***)
the raw sql likes below:
SELECT * FROM `***` ORDER BY
CASE WHEN starred_by LIKE "%prefix1%" THEN 1 ELSE 2 END,otherParam1,otherParam2,otherParam3
but apparently this causes sql inject problem , how can i fix this?
the way to solve sql inject.
These elements cannot be bound into JDBC and gorm doesn't support them as parameterized queries or escape them - they are dangerous to use with untrusted input.
There are two options to do this safely - ideally you should use both:
Validate the columns in these via positive / whitelist validation. Each column name should be checked for existence in the associated tables.
You should enquote the column name - adding single quotes around the columns. If you do this, you need to be careful to validate there are no quotes in the name, and error out or escape any quotes. You also need to be aware that (in most databases) adding quotes will make the name case sensitive.

MySQL Syntax with FROM with a var

I got some problems with my MySQL Syntax.
This is my code:
Config.SocietyMoneyTable = 'addon_account_data'
local result = MySQL.Sync.fetchAll("SELECT money FROM #account_table WHERE account_name = #society", {
['#account_table'] = Config.SocietyMoneyTable,
['#society'] = society
})
Error:
[ERROR] [MySQL] [maze_management] An error happens on MySQL for query "SELECT money FROM
'addon_account_data' WHERE account_name = 'society_police'": ER_PARSE_ERROR: You have an
error in your SQL syntax; check the manual that corresponds to your MariaDB server version
for the right syntax to use near ''addon_account_data' WHERE account_name = 'society_police''
at line 1
The Syntax does work when I change the #account_table to the string which is in Config.SocietyMoneyTable. But I need this configed so this is no solution for me.
A query parameter annotated with the # sigil can only be used in place of a scalar value, not a table name or other identifier. You need to use string formatting to get your configurable table name into the query, not a query parameter.
Something like the following:
Config.SocietyMoneyTable = 'addon_account_data'
local queryString = string.format("SELECT money FROM `%s` WHERE account_name = #society",
Config.SocietyMoneyTable)
local result = MySQL.Sync.fetchAll(queryString, {
['#society'] = society
})
I have not tested this code, and I don't use Lua often, so if there are mistakes I will have to leave it to you to resolve them. But it should at least show the principle: identifiers (like table names) must be fixed in the query string, not added as query parameters.

Unknown SQL syntax error for ScalikeJDBC with SQL interpolation

To avoid DRY, I'm attempting to create an sql INSERT statement with variable column names and the data to fill those columns via ScalikeJDBC's sql interpolation:
case class MySQLInsertMessage(tableName:String, columns:List[String], values:List[String])
def depositMessage(msg: MySQLInsertMessage): Unit = {
NamedDB('MySQLMsgDepositor) localTx { implicit session =>
val sqlStmt = sql"INSERT INTO ${msg.tableName} (${msg.columns}) VALUES (${msg.values})"
println("The sql statement is: " + sqlStmt.statement)
println("The parameters are: " + sqlStmt.parameters)
sqlStmt.update().apply()
}
}
And when I call this with:
depositMessage(MySQLInsertMessage("My_Table", List("key", "email"), List("42", "user#email.com")))
the resulting console printout is:
The sql statement is: INSERT INTO ? (?, ?) VALUES (?, ?)
The
parameters are: List(My_Table, key, email, 42, user#email.com)
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 ''My_Table'
('key', 'email') VALUES ('42', 'user#emai' at line 1
java.sql.SQLSyntaxErrorException: 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 ''My_Table' ('key', 'email') VALUES
('42', 'user#emai' at line 1
I've tried wrapping the sql"..." as such instead:sql"""...""", but that doesn't seem to make a difference. I can execute the expected statement just fine in my MySQL workbench GUI. Any idea what my syntax error is?
Stemming from the hint from #scaisEdge, it seems ScalikeJDBC, when using its syntax, will always place single quotes around any parameterized values. And judging from here - https://github.com/scalikejdbc/scalikejdbc/issues/320 - this is a known issue.
With a MySQL INSERT statement (or others), your table name or column values may not have single quotes around them, though they are allowed to have backticks.
You can use their SQLSyntax.createUnsafely(str:String) method, or, if I wanted to do this as I was doing above, instead of using sql"...", I could use the old way of SQL(s"INSERT INTO ${msg.tableName} (${msg.columns.mkString(",")})")
Note - I believe both of these leave you open to injection attacks. Since, for me, this is a local API and you'd have to have the DB's username and password regardless to use it, I'm going with the createUnsafely way of doing things, with a little regex "cleaner" for a little inelegant piece of mind:
def depositMessage(msg: MySQLInsertMessage): Unit = {
NamedDB('MySQLMsgDepositor) localTx { implicit session =>
val unsafeSQLRegex = "[`'\"]".r
val table = SQLSyntax.createUnsafely(s"`${unsafeSQLRegex.replaceAllIn(msg.tableName, "")}`")
val columns = SQLSyntax.createUnsafely(msg.columns.map(value => unsafeSQLRegex.replaceAllIn(value, "")).mkString("`", "`, `", "`"))
val sqlStmt = sql"INSERT INTO $table ($columns) VALUES (${msg.values})".update().apply()
}
}
}

SQL query dosnt know variables

I am trying to query some tables in my database using a simple dropdown in which the name of the tables are listed. the query has only one record result showing the name and age of the youngest institute registered in the database!
$table = $_GET['table'];
$query = "select max('$table'.est_year) as 'establish_year' from '$table' ";
I need to send the name of the table as variable to the querier php file. no matter the method is GET or POST in both ways when I put the variable name in the query statement, it gives the error:
"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 '.order) as 'last' from 'customers'' "
You are wrapping the table name in single quotes, which is not valid SQL (that's the syntax for strings, not table names). You should either not wrap the name at all or else wrap it in backticks (on the american keyboard layout, that's the key above TAB).
You should also not quote the alias established_year:
select max(`$table`.est_year) as establish_year from `$table`
Also, your code is vulnerable to SQL injection. Fix this immediately!
Update (sql injection defense):
In this case the most appropriate action would likely be to validate the table name against a whitelist:
if (!in_array($table, array('allowed_table_1', '...'))) {
die("Invalid table name");
}
single quote ('), in mysql, it represents string value.
SELECT *, 'table' FROM `table`;
Demo
So your query should be
$table = $_GET['table'];
$query = "select max($table.est_year) as 'establish_year' from $table ";
Also read old post, phpmyadmin sql apostrophe not working.
Also your code is vulnerable to SQL Injection. You can use something like this
//Function to sanitize values received from the form. Prevents SQL injection
function clean($str) {
    $str = #trim($str);
if(get_magic_quotes_gpc()) {
$str = stripslashes($str);
}
return mysql_real_escape_string($str);
}
$firstName = clean($_POST['firstName']);
$lastName = clean($_POST['lastName']);
.
.
.

Unknown column '' in 'where clause'

My query is throwing up this error. Can anyone see why?
$query = "SELECT * FROM Units WHERE ID = `$uniqueUnits[a]`";
Unknown column '' in 'where clause'
Two problems.
You're using backticks to delimit a string. Backticks delimit fields, so MySQL thinks you're trying to give it a column name.
The error message indicates that, in fact, this value that it thinks is a column name, is empty. So your value $uniqueUnits[a] is probably broken, or not being interpolated correctly.
You should do the following:
Interpolate your variables explictly with the "complex syntax" to be sure that the string forms properly;
Check the value of $query so that you can see what's going on:
print $query;
Use actual quotation marks to delimit strings:
$query = "SELECT * FROM Units WHERE ID = '{$uniqueUnits[a]}'";
// ^ quote
// ^ PHP variable interpolation
try
$query = "SELECT * FROM Units WHERE ID = '$uniqueUnits[a]'";
^--- ^---
Backticks are for escaping reserved words, so mysql is translating your variable's contents into a field name.
Because apparently $uniqueUnits[a] resolves to the empty string. And there is no column like this in the database.
Try surrounding your array with {}, like this:
$query = "SELECT * FROM Units WHERE ID = `{$uniqueUnits[a]}`";
Also, is column ID actually in your table?