T-SQL SQL injection using JDBCConnector and StoredProcedures - sql-server

I want to know if there is a possibility to inject sql query into procedure argument. I have particular case:
ALTER PROCEDURE [Test].[Injection]
#Query varchar(250) = null
AS
SET NOCOUNT ON
SET #Query = REPLACE(#Query,'','') COLLATE Latin1_General_CI_AI
... more sql code
SELECT * FROM Customers
WHERE (#Query IS NULL OR (Name COLLATE Latin1_General_CI_AI like '%'+#Query+'%'))
ORDER BY ExternalCode ASC
I want to inject sql query using #Query variable and possibly comment the rest of the code. Procedure is called via Web Service using JDBCConnector. I tried passing (and many others combinations):
'''abc'','''','''');SELECT * FROM [DummyTable][Dummy];--'
as #Query argument but it didn't work out.

No worries, SQL injection is impossible like this.
The way SQL injection works is by sneaking in (injecting) SQL code into the target query.
That is not possible to do with parameters, since SQL parameters are treated as data, not as code. You can pass any SQL code you want inside the parameter, but it will not pose an SQL injection threat.
However - please note that if you are using dynamic SQL inside your stored procedure, and concatenate the parameters into the SQL string, then your query is vulnerable to SQL injection attacks.
This code is not safe!
DECLARE #Sql nvarchar(max) = N'SELECT * FROM Customers
WHERE ('+ #Query +' IS NULL '....
EXEC(#SQL)
To safely run dynamic SQL in SQL Server you can use sp_executeSql and pass the parameters as parameters:
DECLARE #Sql nvarchar(max) = N'SELECT * FROM Customers
WHERE (#TheQuery IS NULL '....
EXEC sp_ExecuteSql
#Sql,
N'#TheQuery varchar(250)',
#TheQuery = #Query

Related

How to we prevent SQL Injection by Regular Expression or any other way in asp.net

Before I ask - I do know about stored procedure is best way to prevent sql injection. We can achieve by parameterized stored procedure.
But in my application I am using dynamic queries as well in stored procedure where sql injection is possible.
Please suggest me a way to stop sql injection like any regular expression or some other way.
Example :
CREATE PROCEDURE [dbo].[USP_BusinessSearch]
#Product INT = NULL,
#BusinessName VARCHAR(100) = NULL
AS
DECLARE #AdditionalCriteria AS NVARCHAR(MAX)
DECLARE #BaseQuery AS NVARCHAR(MAX)
BEGIN
SET NOCOUNT ON
SET #BaseQuery = 'Select * FROM Business WHERE ProductID = ' + #Product
SET #AdditionalCriteria = ' AND BusinessName = '+#BusinessName+' '
SET #BaseQuery = #BaseQuery + #AdditionalCriteria
EXEC SP_EXECUTESQL #BaseQuery
END
Thanks in advance.
I truly hope that the procedure you've posted is not one you are using in a production environment, because it is not safe at all. The fact that you are using parameters does not mean you are safe from SQL Injection - it's how you use the parameters. This procedure can be written without dynamic SQL which would make it safe from SQL injection like this:
CREATE PROCEDURE [dbo].[USP_BusinessSearch]
#Product INT = NULL,
#BusinessName VARCHAR(100) = NULL
AS
SELECT *
FROM Business
WHERE ProductID = #Product
AND BusinessName = #BusinessName
Please note that this doesn't mean that any dynamic SQL approach is vulnerable to SQL Injection - it's quite possible to prevent SQL Injection using dynamic SQL if needed:
CREATE PROCEDURE [dbo].[USP_BusinessSearch]
#Product INT = NULL,
#BusinessName VARCHAR(100) = NULL
AS
DECLARE #ParamDefinition AS NVARCHAR(MAX)
DECLARE #BaseQuery AS NVARCHAR(MAX)
SELECT #BaseQuery = N'Select * FROM Business WHERE ProductID = #Product AND BusinessName = #BusinessName',
#ParamDefinition = N'#Product INT, #BusinessName VARCHAR(100)'
EXEC SP_EXECUTESQL #BaseQuery, #ParamDefinition, #Product, #BusinessName
END
The key difference between this approach and the procedure in the question is that the query in the question simply concatenates the parameter values into the dynamic SQL, thus making it vulnerable to SQL Injection, whereas the procedures in the answers use the parameters the way they are intended to be used - as parameters.

select with parameter instead of field name

How can I use a parameter instead of a field name like:
Declare #Thecode varchar(10)
Set #Thecode= ‘code’ --'code' is field name.
Select #Thecode from sqltable
Here is the correction in your query:
SET #Thecode= ‘code’ --'code' is field name.
SET #query='Select '+#Thecode+' from sqltable'
EXECUTE(#query)
There are two ways to execute dynamic SQL in SQL Server: use the sp_executesql system stored procedure or the EXECUTE() operator.
And for more details about the dynamic SQL execution Follow the below link:
https://www.mssqltips.com/sqlservertip/1160/execute-dynamic-sql-commands-in-sql-server/
I think you are looking for the Dynamic SQL.
If it is so then please check the following solution:
Note: Tested in SQL Server 2008 R2
Declare #Thecode varchar(10)
DECLARE #query VARCHAR(MAX)
Set #Thecode= 'code' --'code' is field name.
SET #query = 'SELECT '+ #Thecode +' from sqltable';
EXEC(#query)
Always mention the DBMS in the tags while posting the question. And take care of SQL Injection
For more details about Dynamic SQL.

How to pass a variable value in a FROM clause in Microsoft TSQL

sorry I am uploading a pic of my query as I dont know to format my text...as a newbie its confusing.
So you want to execute:
select * from File_20170703 -- where your table name is a variable.
It is not possible to use variables for table or column names, what you need to do is to build a dynamic sql and execute it using sp_executesql.
here is an example:
DECLARE #sql nvarchar(4000)
SELECT #sql = 'SELECT * FROM File_20170703'
EXEC sp_executesql #sql
More info about dynamic sql
A simple TSQL "dynamic sql" looks like this:
DECLARE #file_name AS VARCHAR(100)
DECLARE #query AS VARCHAR(MAX)
SET #file_name = 'file_20170101'
SET #query = 'SELECT * FROM ' + #file_name
execute(#query)
Basically you need to create a valid sql query by concatenating various parts of the query together, then you can execute that whole big string as your query.
You can use SQL Cursor along with while loop. Examples are given here:
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql

How to insert into table the results of a dynamic query when the schema of the result is unknown a priori?

Observe the following simple SQL code:
CREATE TABLE #tmp (...) -- Here comes the schema
INSERT INTO #tmp
EXEC(#Sql) -- The #Sql is a dynamic query generating result with a known schema
All is good, because we know the schema of the result produced by #Sql.
But what if the schema is unknown? In this case I use Powershell to generate a Sql query like that:
SET #Sql = '
SELECT *
INTO ##MySpecialAndUniquelyNamedGlobalTempTable
FROM ($Query) x
'
EXEC(#Sql)
(I omit some details, but the "spirit" of the code is preserved)
And it works fine, except that there is a severe limitation to what $Query can be - it must be a single SELECT statement.
This is not very good for me, I would like to be able to run any Sql script like that. The problem, is that no longer can I concatenate it to FROM (, it must be executed by EXEC or sp_executesql. But then I have no idea how to collect the results into a table, because I have no idea of the schema of that table.
Is it possible in Sql Server 2012?
Motivation: We have many QA databases across different Sql servers and more often than not I find myself running queries on all of them in order to locate the database most likely to yield best results for my tests. Alas, I am only able to run single SELECT statements, which is inconvenient.
We use SP and OPENROWSET for this purpose.
At first create SP based on a query you need, than use OPENROWSET to get data into temp table:
USE Test
DECLARE #sql nvarchar(max),
#query nvarchar(max)
SET #sql = N'Some query'
IF OBJECT_ID(N'SomeSPname') IS NOT NULL DROP PROCEDURE SomeSPname
SET #query =N'
CREATE PROCEDURE SomeSPname
AS
BEGIN
'+#sql+'
END'
EXEC sp_executesql #query
USE tempdb
IF OBJECT_ID(N'#temp') IS NOT NULL DROP TABLE #temp
SELECT *
INTO #temp
FROM OPENROWSET(
'SQLNCLI',
'Server=SERVER\INSTANCE;Database=Test;Trusted_Connection=yes;',
'EXEC dbo.SomeSPname')
SELECT *
FROM #temp

Passing concat query parameters to SQL OPENQUERY

Due to the constraints within the workplace I have to use a local stored procedure to call another remote stored proc on a linked sql server, however the problem lies in passing a necessary parameter to the remote stored proc.
This is the query I constructed:
select *
from OPENQUERY([REMOTE_SRVR],'exec db.dbo.dwStoredProc_sp ''#id''')
In order to pass #id to the remote stored proc I understand I could concatenate the above as a string and then use exec
Something along the lines of:
set #query = 'select * from OPENQUERY([REMOTE_SRVR], ''EXEC db.dbo.dwStoredProc_sp '' #id '''''
exec(#query)
I cannot get the local stored proc to successfully call the other. The single quote mess doesn't help!
I get the error: Could not find stored procedure 's'
To help with the quote mess I like to do this in steps. It is more code but easier to understand. I am not sure from your example if #id is an integer. In that case you can lose the double quotes around __ID__.
set #query = 'EXEC db.dbo.dwStoredProc_sp ''__ID__'''
set #query = REPLACE(#query,'__ID__',#id)
set #query = REPLACE(#query,'''','''''')
set #query = REPLACE('SELECT * FROM OPENQUERY([REMOTE_SRVR], ''__REMOTEQUERY__'')','__REMOTEQUERY__',#query)
You could avoid dynamic queries by simply by using EXEC (..., ParamValue) AT LinkedServer (see product's documentation, example [L. Using a parameter with EXECUTE and AT linked_server_name]):
1) On target server:
CREATE PROCEDURE dbo.Proc1( #id NVARCHAR(50) )
AS
SELECT #id AS [id];
GO
2) On the source server you create the linked server and then you can call the stored procedure using EXEC ... AT ... syntax:
DECLARE #p1 NVARCHAR(50);
SET #p1 = N'DROP TABLE dbo.CocoJambo'
EXECUTE (N'dbo.Proc1 ? ' , #p1 ) AT LOCALINKEDSEREV
Output:
id
------------------------
DROP TABLE dbo.CocoJambo

Resources