我的任务是将sql参数应用于被识别为具有sql注入点的网页。发起人使用典型的内联sql字符串进行通配符搜索。我在Stackoverflow中读过很多关于尝试几种选择方法和使用不同串联方法的文章。我已经确定了一种似乎最合理的方法,尽管我对其他建议持开放态度。我知道,由于该页面使用OleDb连接,将被@参数替换为?。
原始vb源选择:
VendorsSDS.SelectCommand = "Select ... and vnmdesc like '%" & UCase(Trim(txtRefine.Text)) & "%'"
原始aspx:
<asp:TextBox ID="txtRefine" name="txtRedfine" runat="server" Width="163px" MaxLength="5"></asp:TextBox>
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="VendorsSDS"
DataTextField="VNMDESC" DataValueField="VENDORID" Height="206px" Width="463px" AutoPostBack="True"></asp:ListBox>
<asp:SqlDataSource ID="VendorsSDS" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString5 %>"
ProviderName="<%$ ConnectionStrings:ConnectionString5.ProviderName %>"
SelectCommand="Select VNMKVPRE||VNMKVNBR as VendorID, vnmdesc||' - '||VNMKVPRE||VNMKVNBR as vnmdesc from trmsd.avnmp where VNMST = 'A' and not trim(vnmdesc) = '' and vnmkvpre in ( 'R', 'V', 'X') order by VNMDESC ">
</asp:SqlDataSource>
我的方向是利用<asp:SelectParameters>以及<asp:ControlParameter>使用txt罚款文本框。
更新aspx:
<asp:SqlDataSource ID="VendorsSDS" runat="server"
SelectCommand="Select VNMKVPRE||VNMKVNBR as VendorID, vnmdesc||' - '||VNMKVPRE||VNMKVNBR as vnmdesc from trmsd.avnmp where VNMST = 'A' and not trim(vnmdesc) = '' and vnmkvpre in ( 'R', 'V', 'X') order by VNMDESC ">
<SelectParameters>
<asp:ControlParameter ControlID="ctl00$ContentPlaceHolder1$txtRefine" Name="?" PropertyName="Text" defaultvalue=""/>
</SelectParameters>
</asp:SqlDataSource>
更新的vb:
Protected Sub btnRefine_Click(sender As Object, e As System.EventArgs) Handles btnRefine.Click
' 2020-Jul-27 Removed
' VendorsSDS.SelectCommand = "Select VNMKVPRE||VNMKVNBR as VendorID, vnmdesc||' - '||VNMKVPRE||VNMKVNBR as vnmdesc from trmsd.avnmp where VNMST = 'A' and not trim(vnmdesc) = '' and vnmkvpre in ('R', 'V', 'X') and vnmdesc like '%" & UCase(Trim(txtRefine.Text)) & "%' order by VNMDESC "
'
' 2020-Jul-27 Added sqlinjection monitoring
'
Dim wParm As String = Me.txtRefine.Text
If oSec.IsInputOk(wParm) Then
Me.txtRefine.Text = wParm
'
' 2020-Jul-27 Apply sql parameter usage
'
VendorsSDS.SelectCommand = "Select VNMKVPRE||VNMKVNBR as VendorID, vnmdesc||' - '||VNMKVPRE||VNMKVNBR as vnmdesc from trmsd.avnmp where VNMST = 'A' and not trim(vnmdesc) = '' and vnmkvpre in ('R', 'V', 'X') and vnmdesc like ('%' & ? & '%') order by VNMDESC "
VendorsSDS.DataBind()
ListBox1.DataBind()
Else
Me.txtRefine.Text = ""
End If
End Sub
我已经尝试了几种如何应用通配符选择的组合。一些帖子说要使用&其他人说+。这两种策略在绑定发生时无论组合如何都会失败:
System.Data.OleDb.OleDbException: 'SQL0104: Token '%' was not valid. Valid tokens: (.
原因…..:在标记"%"处检测到语法错误。令牌"%"不是有效的令牌。
因此,以下内容都不起作用,我需要比我聪明的人帮助我填补知识空白
and vnmdesc like '%' + ? + '%'
and vnmdesc like ('%' + ? + '%')
and vnmdesc like ('%' & ? & '%')
and vnmdesc like ('%?%')
最后,当页面第一次显示时,它应该使用sqldatasource中的初始sql来显示所有不为空的记录,但现在更新后的sqldatasource也不起作用。
任何建议都将不胜感激!
您实际上有两个错误,这使解决问题变得更加困难。
-
您的参数名称不能是
?
。选择任意名称,如下所示:<asp:ControlParameter ControlID="ctl00$ContentPlaceHolder1$txtRefine" Name="vnmdescription" PropertyName="Text" defaultvalue=""/>
-
您的SQL非常接近,但
&
是VB.NET的连接符。SQL使用+
如下:VendorsSDS.SelectCommand = "SELECT VNMKVPRE||VNMKVNBR as VendorID, vnmdesc||' - '||VNMKVPRE||VNMKVNBR as vnmdesc FROM trmsd.avnmp WHERE VNMST = 'A' and not trim(vnmdesc) = '' and vnmkvpre in ('R', 'V', 'X') and vnmdesc like ('%' + ? + '%') ORDER BY vnmdesc"
有关更多信息,请访问MSDN文档。https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.sqldatasource.selectparameters?view=netframework-4.8
又尝试了一天的各种想法。。。答案如下:
在vb端:
CONCAT(CONCAT('%', ?), '%')
感谢所有在这件事上帮助我的人。
参数化查询实际上意味着使用SQL命令对象的参数部分。编写查询时,不要将字符串连接到一个长字符串中。比方说,你有一个像奥布莱恩这样的人的名字,名字中有一句引号。现在,由于引号不匹配,查询失败。
不同的数据库(您的数据库没有标明,如MySQL、SQL Server、Oracle等(允许命名参数。其他人使用"作为参数的占位符,并且参数需要以与"占位符。
此外,对于通配符搜索,使用"%"在根据需要添加参数时,可以将正在查找的前/后文本添加到字符串中。
正如我在最初的评论中所提到的,我不知道你的"|"管道字符是for,所以我将为您制作一个示例查询和参数示例。请注意,以这种方式开始的参数与日期、日期/时间、字符串、数字等数据类型无关。您不是将字符串连接在一起。
(注意,多行SQL语句的格式对VB来说是不正确的语法,只是为了可读性(
Dim cmd As New OleDb.OleDbCommand()
cmd.CommandText =
"SELECT whateverColumn
FROM YourTable
WHERE ColumnBeingFiltered = ?
and SomeCityColumn = ?"
cmd.Parameters.AddWithValue("parmForFirstWhereCondition", variableFromYourCleansedWebPost )
cmd.Parameters.AddWithValue("parmForCity", anotherVariableFromPost )
请注意,查询是什么…"是参数的占位符。然后我按顺序添加参数。我可以命名它们以供参考,所以如果我需要更改它们,例如在循环中,我可以将它们称为
cmd.Parameters["parmForCity"].Value = "Boston"
如果您使用其他数据库,如SQL Server,允许命名参数,则可以命名占位符字段,如…
Dim cmd As New OleDb.OleDbCommand()
cmd.CommandText =
"SELECT whateverColumn
FROM YourTable
WHERE ColumnBeingFiltered = @parmForFirstWhereCondition
and SomeCityColumn LIKE @parmForCity
and Population > @parmNumber"
cmd.Parameters.AddWithValue("parmNumber", 125000 )
cmd.Parameters.AddWithValue("parmForCity", "%" & anotherVariableFromPost & "%")
cmd.Parameters.AddWithValue("parmForFirstWhereCondition", variableFromYourCleansedWebPost )
注意,在第二个查询中,我还做了添加"%"对于参数的通配符搜索,添加了第三个基于数字的参数,还更改了参数的顺序,以显示不同SQL引擎在NAMING参数时允许的差异。"@"在SQL server中被识别为命名参数,但实际的参数名称不使用"@&";。此外,我尝试总是在参数名称前面加上"或";p〃;或";parm";以区分实际列与参数。例如:其中";firstName=firstName"vs";firstName=@parmFirstName";,则在查看查询时不存在歧义。
这是否有助于现在为您澄清参数化查询。