I am trying to select a column from Filemaker using JDBC that has a special character in it. I have seen other posts related to having spaces or other special characters in them and have tried quoting my columns but the question mark throws another kink into it because the JDBC driver seems to try and bind to it.
select "Job Number", "Job Completed?" from "ORDERS"
gives me com.filemaker.jdbc.FMSQLException: [FileMaker][FileMaker JDBC] Invalid parameter binding(s).
Trust me I'd love to just change the column name but I am hitting a legacy DB that is still being accessed from another system. Any help is appreciated.
Edit: After some experimentation I've found that this only happens when using PreparedStatement. If I just use Statement.executeQuery(sql) then I can get around the issue. Would much rather use prepared statements instead of building queries using string concatenation but at least I can move forward. Will leave this open in case anyone knows how to escape the question mark.
ExecuteSQL ( "select \"Job Completed?\" from \"ORDERS\"";"";"")
Didn't read careful. The question is about JDBC ...
I'm one of the authors of WooF, a JDBC driver we wrote for FileMaker which goes through the XML publishing engine. I haven't tested this, but suspect it will work fine with oddly named fields and prepared statements. File a bug report if it doesn't and it should get fixed pretty quickly.
https://code.google.com/p/prosc-woof/
After some experimentation I've found that this only happens when using PreparedStatement. If I just use Statement.executeQuery(sql) then I can get around the issue. Would much rather use prepared statements instead of building queries using string concatenation but at least I can move forward. Will leave this open in case anyone knows how to escape the question mark.
Related
First of all, I know this is bad practice but regardless I'm still looking for an answer.
In our web application we have a textarea where the user can write SQL to bring in custom data sets and view them in a chart. The way this works is essentially taking the written string and executing it as a query. What I'm looking for is everything I need to implement in our application server back end security wise as to disallow the execution of queries that produce results other than SELECT type queries.
The user won't be able to execute any type of SELECT query he wants since the app server backend expends the returned result set to have 2 columns named X_FIELD and Y_FIELD so we're not so much worried about the user being able to view data as much as him executing SQL that will break the database.
What we thought of doing is parsing the string for keywords such as DROP, ALTER, CREATE etc. Are there specific things that we have to look out for? Is there a tool/library that automates this? We're using java for our back end code.
Filtering queries can be done at the application level but it requires much more database-specific expertise than creating separate security systems for each database.
As an example, I created an open source program that can do this for Oracle. It won't solve your problem but the code can at least help explain why this is a bad idea.
First, it's important to understand that Oracle SQL syntax is much more complicated than most programming languages, such as Java.
Oracle has 2175 keywords and almost none of them are reserved. Forget about parsing SQL - none of the existing 3rd party parsers are accurate enough to do this securely.
Luckily a full parser is not needed for this task. Oracle syntax is structured in such a way that any statement can be classified with only 8 tokens, excluding
whitespace and comments.
But building a tokenizer and a
statement classifier is still difficult. That solution will handle
unusual kinds of selects, such as (select * from dual) or with asdf as (select 1 a from dual) select a from asdf;. But even a SELECT statement can cause
changes to the database; either through PL/SQL hidden in a function or type, or locking rows through a for update.
And don't forget to remove the (sometimes optional) terminator. They work fine
in most IDEs, but they are not allowed in dynamic SQL. Don't just remove the last characters, or the last token, because some SELECT statements allow semicolons in the middle.
That's a lot of work for just one database! If you want to use this method to implement security policies you need almost 100% accuracy. Very few people are fanatical enough about any database to build this. There's no chance you can do this for multiple databases.
I've been using H2 on the functional tests part of a MySQL based application with Hibernate. I was finally fed up with it and I decided to usq jOOQ mostly so I could still abstract myself from the underlying database.
My problem is that I don't like this code generation thing jOOQ does at all since I'm yet to see an example with it properly set up in multiple profiles, also don't like connecting to the database as part of my build. It's overall quite a nasty set-up I don't want to spend a morning doing to realise is very horrible and I don't want it in the project.
I'm using tableByName() and fieldByName() instead which I thought was a good solution, but I'm getting problems with H2 putting everything in uppercase.
If I do something like Query deleteInclusiveQuery = jooqContext.delete(tableByName("inclusive_test"))... I get table inclusive_test not found. Note this has nothing to do with the connection delay or closing configuration.
I tried changing the connection to use ;DATABASE_TO_UPPER=false but then I get field not found (I thought it would translate all schema).
I'm not sure if H2 is either unable to create non-upper cased schemas or I'm failing at that. If the former then I'd expect jOOQ to also upper case the table and field names in the query.
example output is:
delete from "inclusive_test" where "segment_id" in (select "id" from "segment" where "external_taxonomy_id" = 1)
which would be correct if H2 schema would have not been created like this, however the query I'm creating the schema with specifically puts it in lowercase, yet in the end it ends up being upper cased, which Hibernate seems to understand or solve, but not jOOQ
Anyway, I'm asking if there is a solution because I'm quite disappointed at the moment and I'm considering just dropping the tests where I can't use Hibernate.
Any solution that is not using the code generation feature is welcome.
My problem is that I don't like this code generation thing jOOQ does at all since I'm yet to see an example with it properly set up in multiple profiles, also don't like connecting to the database as part of my build. It's overall quite a nasty set-up I don't to spend a morning doing to realise is very horrible and I don't want it in the project.
You're missing out on a ton of awesome jOOQ features if you're going this way. See this very interesting discussion about the rationale of why having a DB-connection in the build isn't that bad:
https://groups.google.com/d/msg/jooq-user/kQO757qJPbE/UszW4aUODdQJ
In any case, don't get frustrated too quickly. There are a couple of reasons why things have been done the way they are. DSL.fieldByName() creates a case-sensitive column. If you provide a lower-case "inclusive_test" column, then jOOQ will render the name with quotes and in lower case, by default.
You have several options:
Consistently name your MySQL and H2 tables / columns, explicitly specifying the case. E.g. `inclusive_test` in MySQL and "inclusive_test" in H2.
Use jOOQ's Settings to override the rendering behaviour. As I said, by default, jOOQ renders everything with quotes. You can override this by specifying RenderNameStyle.AS_IS
Use DSL.field() instead of DSL.fieldByName() instead. It will allow you to keep full control of your SQL string.
By the way, I think we'll change the manual to suggest using DSL.field() instead of DSL.fieldByName() to new users. This whole case-sensitivity has been causing too many issues in the past. This will be done with Issue #3218
I am aware that using Prepared Statements is the best way to protect against SQL Injection (and syntax errors due to unescaped characters in unchecked input).
My current situation is that I am writing some Java code to move data from one third party application to another. The destination application uses a proprietary version of Sybase and so whilst I do have the JTDS JDBC driver PreparedStatement fails, as the driver uses temporary stored procedures which aren't supported in this particular flavour of the database. So I only have Statement to work with and I have no control over the user input as it is coming from another application.
There is this similar question but that is focused on fixing the problem where you have a parameter such as a table which cannot be handled via a Prepared Statement. My case is different and hopefully simpler, since I have straightforward SQL statements. I would like to know if there is a best practice for replicating something like the following without using PreparedStatement:
PreparedStatement statement = connection.prepareStatement("UPDATE mytable SET value=? WHERE id=?");
statement.setInt(1, getID());
statement.setString(2,userInput);
statement.executeUpdate();
So I guess the problem is how can I sanitise the user input reliably? I can try to do that myself from scratch but this seems like a bad idea as there is likely to be at least one edge case I'd miss, so I was hoping there was a library out there that would do that for me, but I haven't been able to find one so far.
The ESAPI library has procedures for escaping input for SQL and for developing your own db specific encoders if necessary.
Check out JTDS FAQ - I'm pretty confident that with a combination of properties prepareSQL and maxStatements you could go there (or "could have gone" as you probably completed that task years ago :-) )
I have a java app + SQL server database. DB operation use JDBC with dynamic SQL string. Example:
Select Column from tab where column=StringParm
StringParam is user input. if the stringParm include apostrophe, Java app will throw exception and said Can't execute the SQL.
How to resolve this problem with no java code changing?
I'm guessing you construct the SQL in some manner like
String sql = "Select Column from tab where column='" + StringParm + "'";
Or something like it ? If you do that, you're open to all kinds of exploits and you'll also see behavior like you describe, where the resulting string is no longer valid SQL. You'd have to escape the user supplied parameter first.
The best solution is to use PreparedStatements, so you do
Statement stmt = conn.prepareStatement("Select Column from tab where column=?");
stmt.setString(1,StringParam);
I can't see any quick way of solving your problem without altering any Java code though, bar perhaps escaping/sanitizing the input before it hits your code (e.g. javascript if you're a webapp)
Never put user input directly in a SQL query. You need to use a PreparedStatement with parameters. Without changing the Java code, I don't see any way to make this safe.
You should really use java.sql.PreparedStatement to set parameters. The code changes should be minimal and it is less problematic that trying to escape user input.
You can not fix this without changing the application. SQL Server can handle quotes, however your application (Java code) is not properly escaping the quotes when you build your dynamic SQL commands. I prefer using stored procedures and passing in parameters, this way there are never any quotes issues or injections.
You could fix this by putting a trigger in the database to clean up the entry - i.e. when an insert is attempted, instead do proper escaping on the input, and then continue with the new insert input. However, this is the wrong layer and it should probably not be done down there. A much better solution (IMO) is to use a prepared statement, and do variable replacements, letting JDBC do the escape work for you.
I had a really huge problem recently which took me a lot of time to debug. I have an update statement which updates 32 columns in table. I did that with PreparedStatement. Accidentaly I deleted one setParameter() call so update could not be finished successfully.
I got exception from JDBC (Apache Derby) telling: "At leas one parameter is not initialized" and was not able to figure out which parameter is not set since driver would not tell you nothing about name or ordinal number of at least first parameter which is not set...
I was googleing unsuccessfully for some utility which will produce plain old SQL out of (nearly-finished) prepared statement. It would help a lot in situations like this one, since I will be able to see what is not set.
Have anyone faced this problem? Got any solution?
Have a look at P6Spy. It can intercept all your JDBC calls and log them before forwarding them onto your database.
Alternatively, think about using Springs JDBCTemplate which can take out alot of your boilerplate JDBC coding and help avoid these kind of mistakes. You don't need the rest of the Spring framework to use this bit.
Since the parameters in a prepared statement are just a List or Map in the PreparedStatement Object you should be able to inspect the values.
Also you could write a very simple Wrapper around you jdbc driver that creates wrapped PreparedStatements and logs all parameters and there settings before actually executing the statement.