Is this Sql-injection-proof Asp.net code? - asp.net

Problem: I have a form with text values, and a function that must return a string query based on the values of the text values too.
Solution: I created a SQLCommand query with parameters, then I put the SQLCommand.CommandText to a string and I returned it (to the business logic that is going to handle the query)
Main Question: Is it sql-injection proof?
Code Example:
sQuery = "select * from xy where x like '%#txtNameParameter%'";
SqlCommand cmd = new SqlCommand(sQuery);
cmd.Parameters.Add("#txtNameParameter", SqlDbType.VarChar);
cmd.Parameters["#txtNameParameter"].Value = txtName.Text;
string query = cmd.CommandText;
return query;
Sub question if main question is ok:
Should I put into parameters also values of a radiobutton and dropdownmenu or are they injection-proof?

What you are doing here is injection proof because you are not injecting anything. In fact, your parameter isn't even used (because the only reference to it is inside a string literal so the SQL Parser won't even see where you are attempting to use the parameter because it will treat it as a string literal.)
You may want to change that line of code to:
sQuery = "select * from xy where x like '%'+#txtNameParameter+'%'";
Which would make the SQL look like this:
select * from xy where x like '%'+#txtNameParameter+'%'
Which is just string concatenation in a place where a string is expected in the SQL command anyway.
However, your description of what you are doing with this afterwards possibly blows all that out of the water. I cannot understand why you would want to send just the where clause of the query to the business layer.
Also, the substringed WHERE clause will not contain the data you are putting in the parameter. So you are getting no more benefit that just returning
return "where x like '%#txtNameParameter%'";
The parameter value is lost.

Related

The multi-part identifier could not be bound error won't fix

The Variable fileName contains the name of two columns to fetch value of it, which is in the type of "email,address"
The output of the fileName variable is sam#gmail.com102streetN, which is what I need
but when I try to insert that value into another column table then it throws me an error
The multi-part identifier "sam#gmail.com102streetN" could not be bound.
I don't know how to fix it
for each a in idParase
strSQL = "Select Award, Year, ("&fileName&") as dynamicColumns FROM dbo.Awards_TABLE Where awardID = "&a&""
cmdCRProc.CommandText = strSQL
Set rsCR = cmdCRProc.Execute
nameParase = rsCR("dynamicColumns")
sql2 = "Insert Into dbo.Queue (Award,Year,awardID,FileName) Values ("&rsCR(0)&", "&rsCR(1)&", "&a&", "&nameParase&") "
cmdCRProc.CommandText = sql2
Set rsCR = cmdCRProc.Execute
next
I think this isn't going wrong in the INSERT, but in the SELECT.
If I write out your SELECT it would be something this I think (I don't know the value of "a", but let's say it's 2):
Select Award, Year, (sam#gmail.com102streetN) as dynamicColumns FROM dbo.Awards_TABLE Where awardID = 2
I very much doubt you have a column named 'sam#gmail.com102streetN', right?
I don't know what your goal is, but it seems like you're building a query with a dynamic column name that doesn't exist.
What you can do is Response.Write() your SQL statements and see what the result is. Then maybe run them in your database management tool to check what's going on:
Response.write(strSQL)
And
Response.write(sql2)

ibm bpm - execute sql statement return type

how to manage the result of a query that returns an integer "select count(*) from table"?
1) I've tried to bind the output of a SQL Execute Statement service to an integer variable and doesn't work. (type mistmatch)
2) i've tried to use types like 'SQLResult', SQLResultRow, SQLResultColumn as well but they dont work:
Caused by: com.lombardisoftware.core.TeamWorksException: Type ismatch the value "[Element: ]" must be and instance of type atructured IBM BPM Java Class found: org.jdom.Element
3) i've tried to bind the output to a XMLElement variable and i've got this value
< resultSet recordCount=\"1\" columnCount=\"1\">5< /columnn>< /record>< /resultSet>
so now... how can I access the recordCount attribute of this node?
anyway, I don't like so manipulate a variable of XMLType, when are the types SQLResult, SQLResultRow, SQLResultColumn used?
****** EDITED *******
even if i get a result as XMLElement.. i can't manipulate it.
methods like: tw.local.result[0].rows[0].column[0].getText() don't work (the intellisense as well)
the XMLElement as an attribute "recordCount" but i don't know how to get his value..
Anyway, the only workaround that i found is to change the query in order to return a normal set of records(not a scalar value)
select field from table instead of select count(field) from table
so i could to map the output value to a list of objects and than count its length...
ugly and dirty :-(
anyone know how manipulate the XMLElement in a script block?
Please try this.
Bind the output variable from sql execute statement as 'ANY' type.
variable name - result (ANY)
Query - select count(field) as COUNTVAL from table
tw.local.totalCount = tw.local.result[0].rows[0].indexedMap.COUNTVAL;
Use Return type as XMLElement then bind a XMLElement in output mapping.
For eg: If you are using tw.local.output as ouput mapping (of type XMLElement) then,
log.info("Count "+tw.local.output.xpath('/resultSet/record/column').item(0).getText());
This will print the count
If you want to get "recordCount" Attribute then use
tw.local.output.getAttribute("recordCount");

Classic ASP + ADODB -- how to see actual query being run (for testing)

I'm using Classic ASP. I have a wrapper function for database queries that accepts a query string and an array of parameters, and auto-creates the proper query object and runs the query. Very handy and has been working great.
Here's my problem: When testing, I often want to see the exact text of the query being passed to SQL. Back in the "bad old days" of assembling queries through concatenation I could just write out the string. Now that I'm using parameterization it's a bit more tricky.
How do I take a peek at the fully-assembled query string just before it's passed to the database connection?
Here is the function I'm using, simplified. (The actual function doesn't assume string, for example.)
Public Function pquery( strQuery, params )
Dim cmd, param, thisParam, rs
Set cmd = Server.CreateObject( "ADODB.Command" )
cmd.ActiveConnection = MyConn
cmd.CommandText = strQuery
If IsArray( params ) then
Dim adVarChar : adVarChar = 200
For Each param In params
Set thisParam = cmd.CreateParameter( "#p", adVarChar, , len( param ), param )
cmd.Parameters.Append thisParam
Next
End If
Set rs = cmd.Execute
Set pquery = rs
End Function
I would consider using Sql Query Profiler, as it'll allow you to view the sql text as well as the values being passed in. It'll allow you to set breakpoints, as well as see how long it takes to run a query. However, this requires the query to be sent to the actual database (you had asked for before).
To do it beforehand, you would need to loop through the parameters collection in the command object, then do a find/replace with the key/value pairs in the command text property. it would be hackish at best, if you can use Profiler, go with that.

SqlCommand slow when executing a query with parameters

DbDataAdapter.Fill() is extremly slow when performing parameters!
I have a query with 2 parameters inside, and when I put those parameters hardcoded in the query it takes 1 second to execute (in a 470k table rows, returning only 20 rows).
I found many posts similars here and I tried all those solutions (set arithabort, option recompile, option optimize for, ...) with no luck.
I just perform a query (sql server 2008) and not a stored procedure, so the query with arithabort is like this:
string strSql = #"set ARITHABORT ON;
select TOP 20 ....
Also I tried to call set arithabort in the same transaction but performing that query first..
I don't know if I'm doing something wrong, but the sensation is the ado.net is performing a very bad execution plan in ado.net when I have defined parameters on it.
As a result of this bad choice, the execution time in SSMS is 1 second (after being cached) but in asp is like 9 seconds!
The query is something like this:
strSQL #="
select *
from Table1
where Name like #name";
And then:
DbProviderFactory factory = DbProviderFactories.GetFactory(mProvider);
DbCommand dbcmd = factory.CreateCommand();
if (CommandTimeout != null)
dbcmd.CommandTimeout = CommandTimeout.Value;
if(this.transaccion != null)
dbcmd.Transaction = this.transaccion;
dbcmd.Connection = dbc;
dbcmd.CommandText = strSQL;
if (parametros != null)
dbcmd.Parameters.AddRange(parametros);
DbDataAdapter dbda = factory.CreateDataAdapter();
dbda.SelectCommand = dbcmd;
DataTable dt = new DataTable();
dbda.Fill(dt);
return dt;
EDIT 14/01/2013 (18:44)
I'm not longer retrieve the connection from DbProviderFactory, insted I'm using directly SqlConnection and SqlCommand. I know DbCommand and DbProvider are a base clase... but I think there is something more in there.. because the performance drasticaly increase like 300%!
It's not the fill method, because I already tried in the code shown before..
Anyway, I don't know the reason why but using a SqlConnection is much faster! Any idea? Maybe isn't making that bad execution plan made before?
SqlCommand objCmd = new SqlCommand(strSQL, sqlConn);
if (CommandTimeout != null)
objCmd.CommandTimeout = CommandTimeout.Value;
if (this.transaccion != null)
objCmd.Transaction = SQLtransaccion;
if (parametros != null)
objCmd.Parameters.AddRange(parametros);
DbDataReader dbReader = objCmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dbReader);
dbReader.Close();
return dt;
Any help will be greatly appreciated,
Thanks,
I found the solution!
It was parameters!
I was using a wrong type in the the List!
Parametross.Add(bd.MakeParameter("#val", "%" + txtFind.Text + "%",
DbType.String));
DbType.String vs. DbType.AnsiString
Although both DbType.String and DbType.AnsiString deal with character data, these datatypes are processed differently, and using the wrong data type can have a negative effect on the application’s performance. DbType.String identifies the parameter as a 2-byte Unicode value and is sent to the server as such.DbType.AnsiString causes the parameter to be sent as a multibyte character string. To avoid excessive string conversions, use:
DbType.AnsiString for char or varchar columns and parameters.
DbType.String for unichar and univarchar columns and parameters.
Source:
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc20066.0115/html/adonet/adonet49.htm
In my query there is a:
....
where Table.Col1 like #val
But the column type was varchar and I should use DbType.AnsiString, instead of DbType.String
Parametross.Add(bd.MakeParameter("#val", "%" + txtFind.Text + "%",
DbType.AnsiString));
In my huge table I was making a lot of unnecesary casts and this is the reason why the performance drastically fall down!
Hope this will help someone,

Having problems with sqlDataReader

I am using a sqlDataReader to get data and set it to session variables. The problem is it doesn't want to work with expressions. I can reference any other column in the table, but not the expressions. The SQL does work. The code is below. Thanks in advance, Anthony
Using myConnectionCheck As New SqlConnection(myConnectionString)
Dim myCommandCheck As New SqlCommand()
myCommandCheck.Connection = myConnectionCheck
myCommandCheck.CommandText = "SELECT Projects.Pro_Ver, Projects.Pro_Name, Projects.TL_Num, Projects.LP_Num, Projects.Dev_Num, Projects.Val_Num, Projects.Completed, Flow.Initiate_Date, Flow.Requirements, Flow.Req_Date, Flow.Dev_Review, Flow.Dev_Review_Date, Flow.Interface, Flow.Interface_Date, Flow.Approval, Flow.Approval_Date, Flow.Test_Plan, Flow.Test_Plan_Date, Flow.Dev_Start, Flow.Dev_Start_Date, Flow.Val_Start, Flow.Val_Start_Date, Flow.Val_Complete, Flow.Val_Complete_Date, Flow.Stage_Production, Flow.Stage_Production_Date, Flow.MKS, Flow.MKS_Date, Flow.DIET, Flow.DIET_Date, Flow.Closed, Flow.Closed_Date, Flow.Dev_End, Flow.Dev_End_Date, Users_1.Email AS Expr1, Users_2.Email AS Expr2, Users_3.Email AS Expr3, Users_4.Email AS Expr4, Users_4.FNAME, Users_3.FNAME AS Expr5, Users_2.FNAME AS Expr6, Users_1.FNAME AS Expr7 FROM Projects INNER JOIN Users AS Users_1 ON Projects.TL_Num = Users_1.PIN INNER JOIN Users AS Users_2 ON Projects.LP_Num = Users_2.PIN INNER JOIN Users AS Users_3 ON Projects.Dev_Num = Users_3.PIN INNER JOIN Users AS Users_4 ON Projects.Val_Num = Users_4.PIN INNER JOIN Flow ON Projects.id = Flow.Flow_Pro_Num WHERE id = "
myCommandCheck.CommandText += QSid
myConnectionCheck.Open()
myCommandCheck.ExecuteNonQuery()
Dim count As Int16 = myCommandCheck.ExecuteScalar
If count = 1 Then
Dim myDataReader As SqlDataReader
myDataReader = myCommandCheck.ExecuteReader()
While myDataReader.Read()
Session("TL_email") = myDataReader("Expr1").ToString()
Session("PE_email") = myDataReader("Expr2").ToString()
Session("DEV_email") = myDataReader("Expr3").ToString()
Session("VAL_email") = myDataReader("Expr4").ToString()
Session("Project_Name") = myDataReader("Pro_Name").ToString()
End While
myDataReader.Close()
End If
End Using
This may be because column names need to be unique for the SqlDataReader to be able to index them using a string name for the column.
A couple of things:
1) You are executing the query 3 times. You can lose the ExecuteNonQuery and ExecuteScalar calls, and replace the while loop with "if myDataReader.Read() / end if" to get the data values for the first resulting record. If no records are found, no session variables are set, just as in your current code.
2) It looks more like the problem lies in your session management (ie getting values from Session) rather than your sql query, which looks OK to me.
Check:
that you have sessionState enabled in your web.config file,
that you don't reset the Session values anywhere, and
that you ask for the same Session field name when you are trying to send the email. (e.g. are you setting Session("DEV_Email") but asking for Session("DEV Email") (space instead of underscore) ?
Sorry everyone. The code works just fine. The sqlDataReader WILL accept expressions as column names.
The reason I was getting an error saying the value of the from and to parameters cannot be null. There was no data in that column for any of the records in my table.

Resources