How to prevent SQL injection in classic ASP [duplicate] - asp-classic

My db access code is like following:
set recordset = Server.CReateObject("ADODB.Recordset")
set cmd1 = Server.CreateObject("ADODB.Command")
cmd1.ActiveConnection = Conn //connection object already created
cmd1.CommandText = "SELECT * FROM lbr_catmaster where catname = ?"
cmd1.CommandType = adCmdText
set prm = cmd1.CreateParameter("#prm", 200, 1,200 , "development")
cmd1.Parameters.Append prm
set recordset = cmd1.Execute
But there is no db hit going. Please help with this. I am using sql server 2005.
Thanks.

In my code, this is how I get a recordset from a command:
Set rs = server.createobject("ADODB.Recordset")
Set cmd = server.createobject("ADODB.Command")
cmd.ActiveConnection = Conn //connection object already created
cmd.CommandText = "SELECT * FROM lbr_catmaster where catname = ?"
cmd.CommandType = adCmdText
cmd.CommandTimeout = 900
set prm = cmd.CreateParameter("#prm", 200, 1, 200, "development")
cmd.Parameters.Append prm
' Execute the query for readonly
rs.CursorLocation = adUseClient
rs.Open cmd, , adOpenForwardOnly, adLockReadOnly
Hope it helps

I like using Parameters.Refresh, i.e.
set recordset = Server.CReateObject("ADODB.Recordset")
set cmd1 = Server.CreateObject("ADODB.Command")
cmd1.ActiveConnection = Conn ' connection object already created
cmd1.CommandText = "SELECT * FROM lbr_catmaster where catname = ?"
cmd1.CommandType = adCmdText
cmd1.Prepared = True ' only needed if u plan to reuse this command often
cmd1.Parameters.Refresh
cmd1.Parameters(0).Value = "development"
set recordset = cmd1.Execute

Looks like you aren't referencing your named parameter correctly in your query.
Try replacing:
cmd1.CommandText = "SELECT * FROM lbr_catmaster where catname = ?"
with:
cmd1.CommandText = "SELECT * FROM lbr_catmaster where catname = #prm"
and see if that helps.

If you have a complex criteria using parameters here is an example I had to create based on my requirements
declare #loc smallint = ? , #dt1 date = ? SET #loc = ISNULL(#loc, 999)
SELECT m.* , c.*
FROM Costs c INNER JOIN MbrData m ON c.SN = m.SN and c.startDT = m.startDT
WHERE (m.LocationID = #loc OR #loc = 999) AND (MonthYear = #dt1 OR #dt1 IS NULL)
ORDER BY m.LocationID
then in your asp
cmd.CommandText = strSQL ' the string above
cmd.CommandType = 1 ' adCmdText
cmd.Parameters.Append cmd.CreateParameter("#loc",2,1) 'adSmallInt=2, adParamInput=1
cmd.Parameters("#loc") = rptlocation ' scrubbed location ID
cmd.Parameters.Append cmd.CreateParameter("#dt1",7,1) 'adDate=7, adParamInput=1
cmd.Parameters("#dt1") = scrubbed formatted date
set rst = cmd.Execute

Try leaving off the parameter name:
set prm = cmd1.CreateParameter(, 200, 1,200 , "development")

Related

Response.Redirect error

I have form page that collects data. The user clicks SUBMIT, which goes to a "post page. At the end of this page is the redirect code I am using.
response.redirect( "test.asp?ChecklistID=" + ChecklistID )
For some reason, the result is this.
/test.asp?ChecklistID=4784,%204784
Why is this returning in TWO ID's? I only have ONE record in the 'results' table. And it is '4784'.
Adding the code
<%
'Option Explicit
Dim SQLStmt, sql, RS, ChecklistID, Location, ChecklistDate, Driveup,
ConnectString, conn, objconn
Dim weeds, parking_lot, sidewalk, windows, exterior_trash, door_clean
Dim mats_clean, Notes_page1
Location = Request("Location")
ChecklistDate = Request("ChecklistDate")
Driveup = Request("Driveup")
ChecklistID = Request("ChecklistID")
weeds = Request("weeds")
parking_lot = Request("parking_lot")
sidewalk = Request("sidewalk")
windows = Request("windows")
exterior_trash = Request("exterior_trash")
door_clean = Request("door_clean")
mats_clean = Request("mats_clean")
Notes_page1 = Request("Notes_page1")
ConnectString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &
Server.MapPath("../xyz/mydatabase.mdb")
Set conn = Server.CreateObject("ADODB.Connection")
conn.open ConnectString
SQLStmt = "SELECT * FROM Results WHERE ChecklistID =" & ChecklistID & " ; "
Set RS = Server.CreateObject("ADODB.Recordset")
RS.open "Results", conn, 3, 3
RS.Update
RS("ChecklistDate") = ChecklistDate
RS("Driveup") = Driveup
RS("weeds") = weeds
RS("parking_lot") = parking_lot
RS("sidewalk") = sidewalk
RS("windows") = windows
RS("exterior_trash") = exterior_trash
RS("door_clean") = door_clean
RS("mats_clean") = mats_clean
RS("Notes_page1") = Notes_page1
RS.Update
RS.close
set RS = nothing
conn.close
set conn = nothing
response.redirect( "test.asp?ChecklistID=" + ChecklistID )
%>
The browser might be retaining some history with response.redirect. Try using Server.Transfer. Or, if it's the same page, you might not have to re-add the query string.
Solved
I had the same hidden field in there twice causing the issue.

Trouble getting date value

I am modifying a webpage. Webpage is using visual basic and my database is a SQL database.
The webpage gives me the total Sick, Comp, and Vacation time off. Right now, I get the logon name of whoever's logged onto the computer, and I look up the EmployeeID in a tblEmployees so I can search tblTimeAvailable by the EmployeeID, and then add up the different times.
I want to also get the StartDate from tblEmployees so I can also search by anniversary date (after I calculate it from the Start Date). I'm getting an error "Value of type 'Integer' cannot be converted to 'Date' on the rvsd=command2.ExecuteNonQuery line. Here's my code:
Dim rve As Object
Dim rvsd As Date
Dim dt As Date = Today
'Get network login name (name only)
split = windowsLoginName.Split("\".ToCharArray)
vname = split(1)
'Get employeeid from table that matches login name
Dim Connection As String = "Data Source=WillSQL\ict2;Initial Catalog=timesql_testing;Integrated Security=SSPI"
Using con As New SqlConnection(Connection)
Dim sqlemp As String = "SELECT EmployeeID FROM tblEmployees where login = #loginname"
Dim sqlstdt As String = "SELECT StartDate FROM tblEmployees where login = #loginname"
Dim command As New SqlCommand(sqlemp, con)
Dim command2 As New SqlCommand(sqlstdt, con)
con.Open()
command.Parameters.Add(New SqlParameter With {.ParameterName = "#loginname", .SqlDbType = SqlDbType.NVarChar, .Value = vname})
command2.Parameters.Add(New SqlParameter With {.ParameterName = "#loginname", .SqlDbType = SqlDbType.NVarChar, .Value = vname})
rve = command.ExecuteScalar
rvsd = command2.ExecuteNonQuery
End Using
Dim theDateThisYear As Date
theDateThisYear = DateSerial(Year(Now), Month(rvsd), Day(rvsd))
If theDateThisYear < Now() Then
theDateThisYear = DateAdd("yyyy", 1, theDateThisYear)
End If
Dim NextAnniversary As Date = theDateThisYear
MsgBox(NextAnniversary)
'Get Sick Time - DOES NOT INCLUDE CHECKING TO MAKE SURE LESS THAN ANNIV DATE YET
Using con As New SqlConnection(Connection)
Dim sqls1 As String = "Select SUM(NoofHours) as Total from tblTimeAvailable where workcode = 1 and EmployeeID = #emp"
Dim command As New SqlCommand(sqls1, con)
con.Open()
command.Parameters.Add(New SqlParameter With {.ParameterName = "#emp", .SqlDbType = SqlDbType.NVarChar, .Value = rve})
rvsa = command.ExecuteScalar
End Using
Thanks in advance for any help you can give me!
Assuming that the column [StartDate] in the database has a type of DateTime then all you need to do is
rvsd = CDate(command2.ExecuteScalar)
Although you could have retrieved both values with one query:
SELECT [EmployeeID], [StartDate] FROM [tblEmployees] where [login] = #loginname"
and so
Dim rve As String
Dim rvsd As Date
Dim connStr As String = "Data Source=WillSQL\ict2;Initial Catalog=timesql_testing;Integrated Security=SSPI"
Dim sql = "SELECT [EmployeeID], [StartDate] FROM [tblEmployees] where [login] = #loginname"
Using conn As New SqlConnection(connStr)
Using cmd As New SqlCommand(Sql, conn)
cmd.Parameters.Add(New SqlParameter With {.ParameterName = "#loginname", .SqlDbType = SqlDbType.NVarChar, .Value = vname})
conn.Open()
Dim rdr = cmd.ExecuteReader()
If rdr.HasRows Then
rdr.Read()
rve = rdr.GetString(0)
rvsd = rdr.GetDateTime(1)
End If
End Using
End Using

Stored Procedure Variable (Code error I believe is there)

I am trying to create a script to tidy all the columns and rows in SQL Server (I will be doing more than trimming but once it works I can plug into app-code I have already)
I think I am there but it does not seem to update - maybe the stored procedure is wrong? I believe the error is here.. -- I have looked around about variables in stored procedures and think it looks correct to me.
Insert statements for procedure here
UPDATE systemUsers
SET #ColumnName = #Update
WHERE ID = #ID
Full script...
Protected Sub btnTest_Click(sender As Object, e As System.EventArgs) Handles btnTest.Click
'Select the column names
Dim cn As SqlConnection = New SqlConnection()
Dim cmd As SqlCommand = New SqlCommand()
Dim dr As SqlDataReader
Dim i As Integer = 0
cn.ConnectionString = ConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
cmd.Connection = cn
' this gets the colum name
cmd.CommandText = "select COLUMN_NAME FROM INFORMATION_SCHEMA.Columns where TABLE_NAME = 'systemUsers'"
'Open the connection to the database
cn.Open()
' Execute the sql.
dr = cmd.ExecuteReader()
' Read all of the rows generated by the command (in this case only one row).
CheckBoxList1.Items.Clear() 'remove all items for the new list
Do While dr.Read()
i = i + 1
Session.Item("ColumnName" & i) = dr.Item("COLUMN_NAME").ToString()
Loop
' Close your connection to the DB.
dr.Close()
cn.Close()
Dim j As Integer = 1
For j = 1 to i
cn.ConnectionString = ConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
cmd.Connection = cn
cmd.CommandText = "Select * From [systemUsers]"
'Open the connection to the database
cn.Open()
' Execute the sql.
dr = cmd.ExecuteReader()
' Read all of the rows generated by the cmd (in this case only one row).
Dim vName As String = ""
If vName = "ID" Then
'skip as ID should never be edited!!
Else
Do While dr.Read()
vName = Session.Item("ColumnName" & j).ToString ' put into vName for Stored Procedure
Dim sConnString As String = System.Web.Configuration.WebConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
Dim dsNames As SqlDataSource
dsNames = New SqlDataSource
dsNames.ConnectionString = sConnString
Dim sSQL As String
sSQL = "SPTidy"
dsNames.UpdateCommand = sSQL
dsNames.UpdateCommandType = SqlDataSourceCommandType.StoredProcedure
dsNames.UpdateParameters.Clear()
dsNames.UpdateParameters.Add("ID", dr.Item("ID").ToString())
dsNames.UpdateParameters.Add("Update", Trim(dr.Item(vName).ToString()))
dsNames.UpdateParameters.Add("ColumnName", vName)
dsNames.Update()
dsNames = Nothing
Loop
End If
j = j + 1
' Close your connection to the DB.
dr.Close()
cn.Close()
Next
End Sub
Stored procedure:
create PROCEDURE [dbo].[SPTidy]
#ID bigint,
#Update nvarchar(max),
#ColumnName nvarchar(max)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE systemUsers
SET #ColumnName = #Update
WHERE ID = #ID
END
That code won't throw an error message because it's simply updating the variable. To have a dynamic column name you need to use dynamic SQL (or complicated case statements) but dynamic SQL is better in this instance.
DECLARE #sql nvarchar(max) = '';
SET #sql = N'UPDATE systemUsers SET ' + #ColumnName + N' = ' + #Update + N' WHERE ID=' + #ID
EXEC sp_executesql #sql
Hope this helps :)

Parameterised query asp classic missing operand error

I am trying to get a paramterised query to work in asp classic. Any help appreciated
Here is the error
Microsoft OLE DB Provider for Visual FoxPro error '80040e14'
Missing operand.
/portal/jobportal/getaddress1.asp, line 141
function paramQuery()
code = ucase(request.querystring("code"))
stype = request.querystring("type")
cAddressType = request.querystring("caddresstype")
Set rs = Server.CreateObject("ADODB.recordset")
Set cmd = server.CreateObject("ADODB.Command")
If IsObject(Session("portal_conn")) Then
Set conn = Session("portal_conn")
Else
Set conn = Server.CreateObject("ADODB.Connection")
cConnString = "Provider=vfpoledb;Data Source="+session("portaldata")+"portal.dbc"
conn.open cConnString,"",""
Set Session("portal_conn") = conn
end if
cmd.ActiveConnection = conn
cmd.Prepared = true
cmd.CommandType = 1
cmd.CommandText = "SELECT * from uaddress where userid = "+cstr(session("userid"))+" and upper(name) like ? + % "+" and type = '"+ trim(cAddresstype)+"' order by add1"
set param1 = cmd.CreateParameter("#name",200,2,40)
cmd.Parameters.append param1
cmd.Parameters("#name") = code
cmd.Execute() <-- missing operand error
rs.Open cmd
end function
When using parameter for SQL like clause you need to pass the % as part of the parameter value.
Also to protect against SQL Injection attacks you really better use parameters for the other values as well:
cmd.CommandText = "SELECT * FROM uaddress WHERE userid=? AND UPPER(name) LIKE ? AND type=? ORDER BY add1"
set param1 = cmd.CreateParameter("#id", 200, 2, 40)
cmd.Parameters.append param1
cmd.Parameters("#id") = cstr(session("userid"))
set param2 = cmd.CreateParameter("#name", 200, 2, 40)
cmd.Parameters.append param2
cmd.Parameters("#name") = "%" & code & "%"
set param3 = cmd.CreateParameter("#type", 200, 2, 40)
cmd.Parameters.append param3
cmd.Parameters("#type") = trim(cAddresstype)
cmd.Execute()
You need quotes around the % character:
... +" and upper(name) like ? + '%' "+ ...
It seems like VFP does not support named parameters , just add your params in the order that apears in the query by using (?) instead of the named param and it will work.
instead of :
cmd.Parameters("#name") = code
Use :
cmd.Parameters("?") = code

Updateing NText causing long delay/timeouts

I'm trying to update an NText field in SQL 2000 using Classic ASP. Here is the code I'm using to do it. Any one have any pointers on how to maybe speed it up? Or am I stuck with it.
set Cnn = server.CreateObject("ADODB.connection")
Cnn.ConnectionString = Application("Cnn_ConnectionString")
Cnn.open
set rs = server.CreateObject("ADODB.Recordset")
rs.CursorType = adoOpenDynamic
rs.LockType = adLockOptimistic
conChunkSize = 100
rs.Open "MyTable",Cnn, , , adCmdTable
rs.Find "MyDataId=" & request("DataId"),,adSearchForward,1
lngOffset = 0
lngLogoSize = len(request("txtMyEntry"))*2
Do while lngOffset < lngLogoSize
varChunk = LeftB(RightB(request("txtMyEntry"), lngLogoSize - _
lngOffset), conChunkSize)
rs("MyDataField").AppendChunk varChunk
lngOffset = lngOffset + conChunkSize
Loop
rs.Update
rs.Close
Oh and this code is almost verbatim from the MSDN site.
First I would eliminate the chunking which is so 90's.
Then there is:-
rs.Open "MyTable",Cnn, , , adCmdTable
rs.Find "MyDataId=" & request("DataId"),,adSearchForward,1
Yikes! You'd like to think that ADO intelligently asked SQL server to find that record based on the indexed MyDataId field but bet it doesn't. Its most likely pulling the entire contents of the table across until the record is arrived at.
This really should be done with an UPDATE T-SQL statement and an ADODB.Command object.
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = cnn
cmd.CommandType = 1 '' // adCmdText
cmd.CommandText = "UPDATE MyTable SET MyDataField = ? WHERE MyDataId = ?"
cmd.Parameters.Append cmd.CreateParameter("dataField", 203, 1, Len(txtMyEntry), txtMyEntry) '' // 203 = asLongVarWChar, 1 = adParamInput
cmd.Parameters.Append cmd.CreateParameter("id", 3, 1, , CInt(DataID)) '' // 3 = adInteger
cmd.Execute

Resources