Build SQL Query in client or server side? - sql

I have doubts between two options:
Build the query in client side and send it to server.
Sending from client the needed knowledge in order to build the query in server side.
In which side I will prefer to build the query?
Advantages / Disadvantages?
Thanks.

I tend to prefer building queries on the server side and either storing them as Stored Procedures on the sql server or building the query string in a backend language like PHP.
Building the query in something like javascript and sending to the server, creates the possibility of deviants doing inline altering of your javascript and submitting the query string through something like firebug. If you build the query string in a backend (server-side) language, the only thing the user would have access to alter would be input variables (if applicable). Because of this, you should always check and cleanse all input variables for sql injection.
Removing as much access to raw code from the end user as possible seems to always be the best option, in terms of application security. Someone else may weigh-in about performance limitations; but if a user alters and submits their own query string through a javascript console and drops your entire table, performance won't really be a factor anymore will it?

Related

How should I store SQL queries in my API server?

I'm making an API server that require SQL queries that has something like 20-40 lines.
I want it to be a simple server so I'm using NodeJS, express, body-parser and a database connector.
In other environments, I understand that you either use final constants or import SQL files but I don't know what's the best method in Node.
I think reading in individual SQL file for every query will be slow and since JavaScript does not support multiline string, saving them in a json object would seem tedious.
(I know ES6/Babel exists but it seems like an overkill for just one functionality).
So the question is what's the best and the most common way to store SQL queries in the context of node/express?
20-40 lines seems like a lot... Have you considered making those queries views or stored procedures?
The other thing is that if you are using at least NodeJS 4.6.1 you can use template literals out of the box

Is it ever okay to accept client-side SQL? If so, how to validate?

I have an application in which I'd like to accept a user supplied SQL query from a front-end query builder (http://querybuilder.js.org/). That query eventually needs to make it's way to running in a postgres database to return a subset of data.
The query builder linked above can export SQL or a mongo query. I imagine using the mongo query is relatively safe, since I can add to it simply on the server:
query.owner_of_document = userId
to limit results (to documents owned by the user).
Whereas the SQL statement could potentially be hijacked in an injection attack if someone attempts to store a malicious string of SQL for execution.
Is directly accepting SQL from a client bad practice? How can I ensure the supplied SQL is safe?
Thanks!
Why do you need to accept an entire SQL statement?
Can you accept only parameters and then run a pre defined query?
There are loads of questions/answers on SO relating to SQL injection and using parameters is a first step in avoiding injection attacks, such as "Are Parameters really enough to prevent Sql injections?"
But I think this answer to a different question sums things up well:
Don't try to do security yourself. Use whatever trusted, industry
standard library there is available for what you're trying to do,
rather than trying to do it yourself. Whatever assumptions you make
about security, might be incorrect. As secure as your own approach may
look ... there's a risk you're overlooking something and do you
really want to take that chance when it comes to security?

Is parameterisation needed in this instance?

Im designing a UWP app that uses an SQLite database to store its information. From previous research I have blearnt that using the SQLite function SQLiteConnection.Update() and SQLiteConnetion.Insert() functions are safe to use as the inputs are sanitised before entering in the database.
The next step I need to do is sync that data with an online database - in this case SQL Server - using a service layer as my go between. Given that the data was previously sanitised by the SQLite database insert, do I still need to parameterise the object values using the service layer before they are passed to my SQL Server database?
The simple assumption says yes because, despite them being sanitised by the SQLite input, they are technically still raw strings that could have an effect on the main database if not parameterised when sending them there.
Should I just simply employ the idea of "If in doubt, parameterise" ?
I would say that you should always use SQL parameters. There are a few reasons why you should do so:
Security.
Performance. If you use parameters the reuse of execution plans could increase. For details see this article.
Reliability. It is always easier to make a mistake if you build SQL commands by concatenating strings.

Disable all queries in SQL Server that don't use named parameters?

It seems that one could stop all threat of Sql injection once and for all by simply rejecting all queries that don't use named parameters. Any way to configure Sql server to do that? Or else any way to enforce that at the application level by inspecting each query without writing an entire SQL parser? Thanks.
Remove the grants for a role to be able to SELECT/UPDATE/INSERT/DELETE against the table(s) involved
Grant EXECUTE on the role for stored procedures/functions/etc
Associate the role to database user(s) you want to secure
It won't stop an account that also has the ability to GRANT access, but it will stop the users associated to the role (assuming no other grants on a per user basis) from being able to execute queries outside of the stored procedure/functions/etc that exist.
There are only a couple ways to do this. OMG Ponies has the best answer: don't allow direct sql statements against your database and instead leverage the tools and security sql server can provide.
An alternative way would be to add an additional tier which all queries would have to go through. In short you'd pass all queries (SOA architecture) to a new app which would evaluate the query for passing on to sql server. I've seen exactly one company do this in reaction to sql injection issues their site had.
Of course, this is a horrible way of doing things because SQL injection is only one potential problem.
Beyond SQL Injection, you also have issues of what happens when the site itself is cracked. Once you can write a new page to a web server it becomes trivial to pass any query you want to the associated database server. This would easily bypass any code level thing you could put in place. And it would allow the attacker to just write select * from ... or truncate table ... Heck, an internal person could potentially just directly connect to the sql server using the sites credentials and run any query they wanted.
The point is, if you leverage the security built into sql server to prevent direct table access then you can control through stored procedures the full range of actions availble to anyone attempting to connect to the server.
And how do you want to check for that? Queries sometimes have constant values that would just as easy be added to the query. For instance, I have a database that is prepared to be multi lingual, but not all code is, so my query looks like this:
SELECT NAME FROM SOMETABLE WHERE ID = :ID AND LANGUAGEID = 1
The ID is a parameter, but the language id isn't. Should this query be blocked?
You ask to block queries that don't use named parameters. That can be easily enforced. Just block any query that doesn't specify any parameters. You can do this in your application layer. But it will be hard to block queries like the one above, where one value is a parameter and the other one isn't. You'll need to parse that query to detect it, and it will be hard too.
I don't think sql server has any built in features to do this.

How to confirm SQL injection

Is there any way to confirm that a particular breach of security was done through SQL injection?
There is no easy way here, but if you have the enabled the SQL server you use to log every single sql statement, here is what I would do.
Normally, when I SQL inject somewhere, i use one of these as my always true statement for passing throgh the Where clause, after ending the former string.
1=1
0=0
both being used as :
blahblahblah' or 1=1 --
You would not use this clauses in everyday code. So if you spot one of these in your history, well, it is a high candidate. Test the sql history to find :
(space)(number)(optional spaces)(equal)(optional spaces)(same number)(space)
Keep in mind that is heuristical, and will not always work, but could be the only way to give a hint after it had happened . Also, if you are in doubt about SQL injection, you should check the code for string concatenation and use of parameters.
after the attack has already happened? no. there isn't.
you'll have to check all your sql serevr access point for potential risk.
tere are some tools you can use. Check here under SQL Injection tools section.
SQL injection can happen any time you pass a query back to the database.
SQL Injection
Use mod_security to log POST requests and install an Intrusion Detection System to log/stop suspicious activity from now on. Logging every SQL request is an overhead if you are just looking for the breach points.
There are open source alternatives for IDS these days. I use PHPIDS for all my PHP applications.
Only one reliable way is probably analysing the SQL log files. Those should be done by a DBA who can spot things quickly as the size of logs would be huge.
It is better to prevent those.
There are some tools for that but the best one is the brain of the developer.
Stick with one simple rule - always use parameters when generating SQL query.
Just do the code review and if you find string cocatenations - that is first and highly possible place for SQL Injection.
You can log all http requests and check the requested pages for GET/POST sql injection tryouts.