The classic way to query an SQL database case-insensitively from Java is as follows:
String name = ...; // get the user's input (case is unknown)
String sql = "select * from Person where lower(name) = ?";
Object jdbcBindVariable = name.toLowerCase();
// ... using JDBC, bind that variable and run the SQL query
The problem is that lower-casing is a locale-specific operation. For example, lower-casing the letter "I" gives different results in English and Turkish. In the above code, there are two lower-casing operations:
The String#toLowerCase() method
The lower() database function
How can I make sure that Java and the database are using the same locale and thereby performing a valid comparison?
I'm aware that the String class has a toLowerCase(Locale) method, but how do I know what Locale the database is using? Can I check this programatically, or do I have to hard-code the locale to the one with which I think the database (in this case Oracle 10g) is configured?
The simple answer is let the database do it.
That way the way the bind variable is put into lower case will be consistent with the way the column value is put into lowercase.
String sql = "select * from Person where lower(name) = lower(?)";
... but how do I know what Locale the database is using? Can I check this programmatically ...
There doesn't appear to be a portable (database independent) way to do this, but you can apparently use the following query to get the charset used by an Orable database:
select value from nls_database_parameters where parameter = 'NLS_CHARACTERSET';
This page gives more details.
As for actually doing the comparison, you would be best off (*) letting the database take care of the lower-casing, as #Gary suggests. The JDBC driver will take care of converting Java (UTF-16) Strings into whatever the database is using.
(* In fact, I don't think you have much choice, unless you are prepared to wear the cost of storing mixed-case and lower-case copies of all queriable strings in the database.)
Related
I am saving the output of my AnyLogic model into an SQL server database. For non-AnyLogic aficionados, AnyLogic is based on Java. However, I am not sure what data types I need to specify for my columns in the database.
So far I am using these:
double in AnyLogic : float in SQL
string in AnyLogic : varchar in SQL
int in AnyLogic : int in SQL
I also have parameters that are of type Option list, which is, if I understand correctly, a form of Java enum. I tried to save those parameters as varchar, but this (obviously) does not work. In addition, my model contains various boolean parameters. For my boolean parameters, I add columns of type bit in SQL by running:
ALTER TABLE myTable
ADD my_bool BIT NOT NULL DEFAULT 0;
However, running the model returns this error
SQLServerException: Invalid column name 'false'. Caused by: Invalid column name 'false'
So concretely, how can I export parameters of type Option list and boolean?
This addresses the original question which was tagged MySQL.
I don't know all the issues around "option list". Seems like a string (with a length such as varchar(255)) would work. You can also look into the built-in enum type, although I would not normally recommend using enums.
I would recommend using boolean instead of bit as the equivalent for boolean. Seems more mnemonic.
That said, MySQL understands false as a constant. You can check this by running:
select false
This also works:
select "false"
However, this returns the error that you specify:
select `false`
I suspect that the code being generated is using this construct. You will need to look at the code -- and you might need to figure out some other way of handling this. In MySQL you can use 0 for false and that might fix your problem.
The AnyLogic database is a standard HSQLDB database (not something proprietary) but they've added AnyLogic client functionality to define 'column types' as though they are Java types (with special types for option lists and compiled-on-the-fly-and-run Java code).
If you look at the db.script file (HSQLDB just stores the persistent DB data as an SQL script which creates the tables and INSERTs the values) you can see the underlying HSQLDB types which map closely to SQL Server types.
boolean --> BOOLEAN
double --> DOUBLE
int --> INT
String --> VARCHAR(16777216)
Date --> TIMESTAMP
Code --> VARCHAR(16777216)
Option List --> VARCHAR(255)
NB: The 'Java column types' are supposed to make it easier for a non-technical user to understand what they will get from a Java perspective when querying that column but, for example, they are confusing in that queries will return Java nulls for missing values, so a boolean column actually effectively returns a Boolean.
That should help.
I managed to address part of my problem. I am now able to store String variables from Java into my SQL database. The issue was due to incorrect use of quotations.
Java uses double quotations for String variables (e.g.: ""). SQL expects single quotations (e.g.: '') for string-like columns such as varchar() and char()
I had to amend my SQL query to this:
String insertTableSQL = "INSERT INTO test (my_string) VALUES(" +" '"+my_variable_string+"' )";
Note that my_variable_string is a derivative of a Java enum, which I obtained by executing String my_variable_string= my_enum.name();
From https://en.wikipedia.org/wiki/Code_injection#Preventing_problems
To prevent code injection problems, utilize secure input and output handling, such as:
Using APIs that, if used properly, are secure against all input characters. Parameterized queries (also known as "Compiled queries", "prepared statements", "bound variables") allows for moving user data out of string to be interpreted. Additionally Criteria API[7] and similar APIs move away from the concept of command strings to be created and interpreted.
I was wondering how and why "parameterized queries (also known as "Compiled queries", "prepared statements", "bound variables") allows for moving user data out of string to be interpreted" and prevent or mitigate code injection problems?
Can you also provide some examples in explanation?
Thanks.
Compiled queries use special syntax that the database understands. They usually add placeholders for parameters such as in:
select * from applicant where name = ?
select * from applicant where name = :name
The exact syntax depends on the specific technology: JDBC, ODBC, etc.
Now, once those queries are sent to the database (without the specific parameter values), the database "saves" them. Later on (usually in the same database session), you can run them many times, by just providing the parameter values each time.
SQL Injection Safety
They are also safe against SQL injection. For example, if in the previous query instead of a simple value such as Mary you used the value x'; delete from applicant; -- the database will work safely. It would run something like:
select * from applicant where name = 'x; delete from applicant; --'
This query won't probably find anything and will be safe.
If instead you didn't use compiled query, but just decided to concatenate the SQL as a string you would do something like:
String sql = "select * from applicant where name = '" + param1 + "'";
And would end up with the UNSAFE query:
select * from applicant where name = 'x'; delete from applicant; --
This one would run two queries. The second one will delete all the information from your table. Probably not what you want.
I'm so confused or rather I'm like, soooooooooo confused with pdo prepared statements. I know that prepared statements are the best way to keep data safe from hackers.
From : How can prepared statements protect from SQL injection attacks?
We are sending program to the server first
$db->prepare("SELECT * FROM users where id=?"); where the data is
substituted by some variable called "placeholder".
Note that the very same query being sent to the server, without any
data in it! And then we're sending the data with the second request,
totally separated from the query itself:
$db->execute($data);
query-
$query=$db->prepare("SELECT * FROM USERS WHERE username=?");
$query->execute(array($tex));
$tex=blah; DROP TABLE users;--
then it will be like - SELECT * FROM USERS WHERE username=blah; DROP TABLE users;--
how prepare statements will help me with this example above?
I'm really sorry if this question is vague to understand. Any help would be appreciated. Thanks in advance.
The prepared statement handler will make sure the bound value is always used as valid SQL value/literal (ie. an SQL string or a number) and never as 'raw SQL text'1.
This is why placeholders values cannot be used as identifiers such as column or table names or act as other SQL keywords; and cannot generate the vulnerable query hypothesized. Instead it is treated as the following:
WHERE username='blah; DROP TABLE users;--'
--^ placeholder ensures valid SQL string value is used
-- (note automatic/implicit addition of SQL quotes)
And even when binding with 'more tricky' data:
$tex = "blah'; DROP TABLE users;--"; // embedded SQL quote character
It would still be safe:
WHERE username='blah''; DROP TABLE users;--'
--^ placeholder STILL ensures valid SQL string value is used
Thus, when using placeholders, it is impossible to generate the SQL that is vulnerable (in this way).
For SQL Injection the 'shape' of the query (which includes keywords and identifiers, but excludes values) must itself be altered by the input.
1 Technically placeholders values can also be sent through a separate data channel (depending on adapter/driver) and thus might not even appear in the raw SQL query itself.
However a simple way to think about why placeholders are safe, or how they 'work' is:
When using placeholders the adapter ensures that the equivalent of 'sql really safe escape' and applicable quoting is always used for every bound text value - and is thus impossible for accidentally forget.
I have a query like
SELECT *
FROM myTable
WHERE key LIKE 'XYZ'
The value 'XYZ' is entered by users (and may include % and _)
If I construct the query using string concatenation it runs in 10 seconds.
But this is unsafe, and I should use a parameterised query.
So I'm constructing the query using the odbc command object and it's execute method, and passing a parameter.
SELECT *
FROM myTable
WHERE key LIKE ?
Unfortunately the parameterised SQL execute method takes a full minute.
This query is one of many that are part of a drill-down / investigation package, and I've had similar slow downs with all the parameterised queries (compared to string concatenation).
How do I find out where the time is going (and fix it) ?
Here's my guess without further information.
I've had similar problems on SQL Server. In SQL Server when the column on your table is 'varchar' and the parameterised query parameter is 'nvarchar' (or vice versa), this causes SQL Server to ignore an available index because the parameter type doesn't match the index type, which in turn results in a table scan.
It's possible the same thing happens for Sybase. If you can see the generated query you can confirm if there's a type mismatch.
If this is the case, then two solutions would be
explicitly set the type of the parameter to match the column type
change the type of the column to match the parameter type being generated
Mitch had the right suggestion.
I had to change the connection string to use the OLEDB driver, then I could set the options:
Optimize Prepare=None
Select Method=Direct
The website i worked was recently attempted to be hacked by the following SQL injection script
boys' and 3=8 union
select 1,
concat(0x232425,ifnull(`table_name`,0x30),char(9),ifnull(`table_rows`,0x30), char(9),0x252423),
3,4,5,6,7,8,9
from `information_schema`.`tables`
where table_schema=0x62646B3032 limit 44,1 -- And '8'='8
This injection returned the mysql table name. This was reported by the error reporting system on that website and we managed to fix that part however I am not able to understand what does the above injection mean?
Anyone can explain this?
Penuel
They're using a select from the Information Schema views in mysql server :
http://dev.mysql.com/doc/refman/5.0/en/information-schema.html
They use some clever hacks to rout out simple sql injection prevention techniques.
According to this the MySQL concat()
Returns the string that results from
concatenating the arguments. May have
one or more arguments. If all
arguments are nonbinary strings, the
result is a nonbinary string. If the
arguments include any binary strings,
the result is a binary string. A
numeric argument is converted to its
equivalent binary string form
So 0x232425 is converted to #$% which is simply added to the begining and end of the table_name field. Maybe just to make it easier for them to pull out the Table names later using Regex.
Later on the char(9) is equivalent to a tab as you can see here and is just there to format the output nicer.
The 3,4,5,6,7,8,9 is just there so that the columns match the boys table that they are performing the Union on.
This injection returned the mysql table name.
Do you mean that your website displayed the table name when you gave it this input, or that the query returns that when run from the mysql client? If it showed on your website, then the attacker has the ability to inject much more harmful queries. Check your data.