Anti SQL Inject

Anti SQL Inject

1.Web 应用程序执行时如果发生异常,通过配置严禁将任何技术信息暴露:
 Web.Config:  

<
customErrors 
mode
=”RemoteOnly”
 
/>

2.在客户端应用程序
 2.1 程序代码中一定要拼接 “参数化 SQL” ,并采取安全的”命令参数式” ADO.Net API
  ,连接数据库并提交该查询,另外今后尽量减少应用程序拼接 SQL,而多使用存储过程。
  参阅如下代码:

ContractedBlock.gif
ExpandedBlockStart.gif
Code

private void cmdLogin_Click(object sender, System.EventArgs e)
{

 
string strCnx = ConfigurationSettings.AppSettings[cnxNWindBad];
 
using (SqlConnection cnx = new SqlConnection(strCnx))
 {

  SqlParameter prm;
  cnx.Open();
  
string TableName = [users];
  
string strQry =
   
//注意 @username 和 @password 就是前面所指参数化 SQL 中的参数
   
//可以理解为是 “字段值” 的”值占位符”,不要用它去占位表名、列名、以及关键字
   
//同时用户交互录入的也的确只能是 “字段值”
   
//这样 ADO.Net + SQL Server 就可以自动免疫,免于被注入恶意但语法正确的 SQL
   SELECT Count(*) FROM  + TableName +   WHERE UserName=@username  +
   
AND Password=@password;
  
int intRecs;
  SqlCommand cmd 
= new SqlCommand(strQry, cnx);
  cmd.CommandType
= CommandType.Text;
  prm 
= new SqlParameter(@username,SqlDbType.VarChar,50);
  prm.Direction
=ParameterDirection.Input;
  prm.Value 
= txtUser.Text;
  cmd.Parameters.Add(prm);
  prm 
= new SqlParameter(@password,SqlDbType.VarChar,50);
  prm.Direction
=ParameterDirection.Input;
  prm.Value 
= txtPassword.Text;
  cmd.Parameters.Add(prm);
  intRecs 
= (int) cmd.ExecuteScalar();
  
if (intRecs>0)
  {

   FormsAuthentication.RedirectFromLoginPage(txtUser.Text, 
false);
  }
  
else
  {

   lblMsg.Text 
= Login attempt failed.;
  }
 }
}

 2.2 程序代码中直接调用存储过程,采取安全的”命令参数式” ADO.Net API,连接数据库并提交,
  不要以 CommandType.Text 的方式使用ADO.Net API 执行类似 exec sp_help ‘sysobjects’ 语句。
  参阅代码同前
3.数据库服务器端程序
 3.2 存储过程 T-SQL 程序代码中,如果其传入参数只用于静态 SQL ,且客户端采取安全的”命令参数式”
  ADO.Net API 调用该存储过程,则是安全代码,自动免疫 SQL 注入攻击。
  参阅如下代码:

ContractedBlock.gif
ExpandedBlockStart.gif
Code

静态 SQL 代码:
declare @value varchar(100)
set @value = sys or 1=1 — 根本无法注入恶意 sql,得到所有记录,因为 @value 被认为是一个”值”
select * from sysobjects where name like % + @value +%

存储过程:
create procedure zsp_WithStaticSQL
@Parameter varchar(100)
as
select *
from sysobjects
where name = @Parameter

 3.3 存储过程 TSQL 程序代码中,如果其传入参数被用于拼接动态 SQL,该参数应该只接受”值”,
  ,而不要用于传入包含表名、列名、关键字的 SQL 语句的一部分,并将该存储过程参数用于
  构造参数化的动态 SQL,并使用 sp_executesql 及其形参声明参数,实参参数执行,
  而绝对禁止直接拼接 SQL,并 
exec 执行
create proc zsp_WithParameterizedDynamicSQL
 
@Value varchar(20)
,
@OutValue int output
as
用于保存动态 SQL 的一定要使用 nvarchar 数据类型
declare @sql nvarchar(200
set @sql = select * from sysobjects 
if @value = null or len(@value> 0
begin
  
@value 是存储过程的参数,将其拼接到动态 sql 语句中,起到了一个”字段值”的”值占位符”的作用
  (一般是”=”右边的以”@”开始的 T-SQL 变量)
  从而构造出安全的 “参数化动态SQL”
  set @sql = @sql +  where name like (% + @ +%)
end

select @sql

exec sp_executesql @sql
  , N
@ varchar(20)
  , 
@value

set @OutValue = @@rowcount
GO

declare @ varchar(100)
set @ = sys
set @ = ”’%
declare @i int
exec zsp_WithParameterizedDynamicSQL @,@i out
select @i

Anti SQL Inject

SQL 2000+ XQuery解决参数化In子句的问题

ContractedBlock.gif
ExpandedBlockStart.gif
Code

建测试表
create table #testTable (UserID int,UserName varchar(50))
插测试数据
insert into #testTable(UserID,UserName) values (1,aaa)
insert into #testTable(UserID,UserName) values (2,aaa)
insert into #testTable(UserID,UserName) values (3,aaa)
insert into #testTable(UserID,UserName) values (4,aaa)

declare @ids xml
set @ids = cast(<ids><id>1</id><id>2</id><id>3</id></ids> as xml)

select A.* from TestUser A
 
inner join
 (
  
select X.c.value(.intas UserID 
   
from @ids.nodes(/ids/idas X(c)
 ) B 
on A.UserID = B.UserID 
 
 
drop table #testTable

SQL 2008 UDT 解决参数化 In 子句的问题

ContractedBlock.gif
ExpandedBlockStart.gif
Code

In(‘a’,’b’,’c’) 转换为 in (select colname from @Table)

D
 ================================
 Create User-defined Table Type
 ================================
USE Test
GO
 Create the data type
CREATE TYPE dbo.MyType AS TABLE 
(
 col1 
int NOT NULL
 col2 
varchar(20NULL
 col3 
datetime NULL
 
PRIMARY KEY (col1)
)
GO

DECLARE @MyTable MyType
INSERT INTO @MyTable(col1,col2,col3)
VALUES (1,abc,1/1/2000),
 (
2,def,1/1/2001),
 (
3,ghi,1/1/2002),
 (
4,jkl,1/1/2003),
 (
5,mno,1/1/2004)
 
SELECT * FROM @MyTable 

go
CREATE PROC usp_test @MyTableParam MyType READONLY
as
begin
 
select *
 
from [Table_1]
 
where f2 in(select col1 FROM @MyTableParam)
end 
GO

 

ContractedBlock.gif
ExpandedBlockStart.gif
Code

Create a local table
Dim table As New DataTable(temp)
Dim col1 As New DataColumn(col1, System.Type.GetType(System.Int32))
Dim col2 As New DataColumn(col2, System.Type.GetType(System.String))
Dim col3 As New DataColumn(col3, System.Type.GetType(System.DateTime))
table.Columns.Add(col1)
table.Columns.Add(col2)
table.Columns.Add(col3)
        
Populate the table
For i As Integer = 20 To 30
    
Dim vals(2As Object
    vals(
0= i
    vals(
1= Chr(i + 90)
    vals(
2= System.DateTime.Now
    table.Rows.Add(vals)
Next

Code
Create a command object that calls the stored proc
Dim command As New SqlCommand(usp_AddRowsToMyTable, conn)
command.CommandType = CommandType.StoredProcedure

Create a parameter using the new type
Dim param As SqlParameter = command.Parameters.Add(@MyTableParam, SqlDbType.Structured)
command.Parameters.AddWithValue(@UserIDKathi)

Code
Set the value of the parameter
param.Value = table

Execute the query
command.ExecuteNonQuery()

SQL 2000 + Split String to Table

ContractedBlock.gif
ExpandedBlockStart.gif
Code

CREATE function [dbo].[zufn_SplitStringToTable]
(
    
@Text   varchar(8000),  待分拆的字符串
    @Separator varchar(10= ,     数据分隔符
)RETURNS @Table TABLE(id int,F varchar(100))
AS
/*
select *
from zufn_SplitStringToTable(‘,,44,,,55,77,77,’,’,’)
*/

BEGIN
set @Text = replace(@Text, ,)
set @Separator = ,
DECLARE @SeparatorLen int
SET @SeparatorLen=LEN(@Separator+$)2
set @Text = replace(@Text, ,)
declare @i int
set @i = 1
WHILE CHARINDEX(@Separator,@Text )>0
BEGIN
    
declare @v varchar(100)
    
set @v = (LEFT(@Text ,CHARINDEX(@Separator,@Text )1))
    
INSERT @Table (id,F)
    
select @i,@v
    
where rtrim(ltrim(@v)) !=  
            
and not exists (select 1 from @Table  where F = @v)
    
if @@rowcount > 0
    
begin
        
set @i = @i + 1
    
end
    
SET @Text = STUFF(@Text ,1,CHARINDEX(@Separator,@Text )+@SeparatorLen,)
END
INSERT @Table  (id,F)
select @i,@Text
where rtrim(ltrim(@Text)) != 
        
and not exists (select 1 from @Table where F = @Text)
return
end

C# 参数化 SQL in 子句

ContractedBlock.gif
ExpandedBlockStart.gif
Code

//参数化 SQL in 子句
namespace Microshaoft.Test
{

    
using System;
    
using System.Data;
    
using System.Data.SqlClient;
    
using Microshaoft.ParameterizedSqlTest;

    /// <summary>
    
/// Class1 的摘要说明。
    
/// </summary>
    public class Class1
    {

        
/// <summary>
        
/// 应用程序的主入口点。
        
/// </summary>
        //[STAThread]
        static void Main(string[] args)
        {

            
//
            
// TODO: 在此处添加代码以启动应用程序
            
//
            Console.WriteLine(Hello World);
            Console.WriteLine(Environment.Version.ToString());

            DataTable dt = DataAccess.Execute_SQL
                                (
                                    
abc
                                    , 
d
                                    , 
a,b,c,d
                                    , SqlDbType.VarChar
                                    , 
3
                                    , 
sqlPara
                                );
            Console.WriteLine(dt.Rows.Count);
            Console.ReadLine();
        }
    }
}

namespace Microshaoft.ParameterizedSqlTest
{

    
using System;
    
using System.Data;
    
using System.Data.SqlClient;

    using System.Text;

    class DataAccess
    {

        public static string _ConnectionString = @”Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Northwind;Data Source=.\sqlexpress;//ConfigurationManager.ConnectionStrings[“ConnectionString”].ConnectionString;
        public static DataTable Execute_SQL
                                (
                                    
string Parameter1                    //普通参数
                                    , string Parameter2                    //普通参数
                                    , string inClause                    //in 子句字段值列表
                                    , SqlDbType inClauseSqlDbType        //in 子句字段类型
                                    , int inClauseSqlDbTypeSize            //in 子句字段大小
                                    , string prefixSqlParameterName        //参数前缀
                                )
        {

            SqlConnection connection 
= new SqlConnection(_ConnectionString);

            StringBuilder sql = new StringBuilder(select 1 where ‘abc’ = @Parameter1);

            SqlCommand command = new SqlCommand();
            command.CommandType 
= CommandType.Text;

            SqlParameter sqlParameter1 = command.Parameters.Add(@Parameter1, SqlDbType.VarChar, 3);
            sqlParameter1.Direction 
= ParameterDirection.Input;
            sqlParameter1.Value 
= Parameter1;

            SqlParameter sqlParameter2 = command.Parameters.Add(@Parameter2, SqlDbType.VarChar, 3);
            sqlParameter2.Direction 
= ParameterDirection.Input;
            sqlParameter2.Value 
= Parameter2;

            string[] a = inClause.Split(,);
            
if (a.Length > 0)
            {

                sql.Append(
 and @Parameter2 in ();
                
int i = 0;

                foreach (string var in a)
                {

                    i 
++;
                    
if (i > 1)
                    {

                        sql.Append(
,);
                    }
                    
string sqlParameterName = @ + prefixSqlParameterName + _ + i;
                    sql.Append(sqlParameterName);
                    SqlParameter parameter;
                    
if (inClauseSqlDbTypeSize > 0)
                    {

                        parameter 
= command.Parameters.Add(sqlParameterName, inClauseSqlDbType, inClauseSqlDbTypeSize);
                    }
                    
else
                    {

                        parameter 
= command.Parameters.Add(sqlParameterName, inClauseSqlDbType);
                    }
                    parameter.Direction 
= ParameterDirection.Input;
                    parameter.Value 
= var;

                }
                sql.Append());
            }
            command.CommandText 
= sql.ToString();
            command.Connection 
= connection;

            Console.WriteLine(command.CommandText);
            SqlDataAdapter sda = new SqlDataAdapter(command);
            DataSet ds 
= new DataSet();
            sda.Fill(ds);
            connection.Close();
            
return ds.Tables[0];
            
        }

    }
}

1. 采用最少权限的原则
运行脚本或执行代码的进程应当尽可能用权限最少的帐户运行,从而在危及进程安全时限制可能造成的破坏。如果恶意用户设法将代码注入某个服务器进程,那么授予该进程的权限会在很大程度上决定该用户可执行的操作类型。应当将需要更多信任(和更高权限)的代码分别隔离在不同的进程内。
2. 使用纵深防御
在应用程序中的每一层和每个子系统中设置检查点。检查点是网关守卫,它们确保只有经过身份验证和授权的用户能够访问下一个下游层。
3. 不要信任用户输入
应用程序彻底验证所有用户输入,然后再根据用户输入执行操作。验证可能包括筛选特殊字符。针对用户意外地错误使用和某些人通过在系统中注入恶意命令蓄意进行攻击的情况,这种预防性措施对应用程序起到了保护作用。常见的攻击包括 SQL 注入攻击、脚本注入和缓冲区溢出。
4. 使用默认安全设置
杜绝仅仅为了使应用程序运行而使用安全性较低的设置。如果应用程序所需的功能不得不减小默认安全设置的安全级别或更改默认的安全设置,在更改前,充分测试更改所带来的后果,并了解可能带来的隐患。
5. 不要通过隐藏来保障安全
尝试使用让人迷惑的变量名来隐藏机密信息或将它们存储在不常用的文件位置,这些方法都不能提供绝对的安全保障。最好使用平台功能或使用已被证实可行的技术来保护数据。
6. 在关口进行检查
在关口检查客户端意思是在第一个身份验证点(例如,Web 服务器上的 Web 应用程序内)授予用户权限,并确定允许用户访问的资源和操作(可能由下游服务提供)。如果在关口设计可靠的身份验证和授权策略,就不必将原调用方的安全上下文一路委派到应用程序数据层。
7. 假定外部系统是不安全的系统
如果外部系统不归您所有,不要假定有人为您保证安全。
8. 减小表面区域
避免公开不需要公开的信息。如果公开这些信息,就可能进一步引起漏洞。同时,处理错误的方式一定要适当。向最终用户返回错误消息时,不要公开任何不需要公开的信息。
9. 以安全的方式显示错误消息
如果应用程序失败,一定要保护好机密数据。同时,不要在错误消息中提供过于详细的数据,也就是不要提供任何有助于攻击者发现应用程序漏洞的详细信息。详细的错误信息应写入 Windows 事件日志。
10, 不要忘记您的安全程度受最薄弱环节制约
考虑安全性时,应该将应用程序所有层的安全性都考虑在内。
11. 禁用不使用的内容
通过禁用应用程序不需要的模块和组件来去除一些潜在的攻击点。例如,如果应用程序不使用输出缓存,则应禁用 ASP.NET 输出缓存模块。这样,即使以后在该模块中发现安全漏洞,应用程序也不会受到威胁。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/110888.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 解决cookie跨域访问_cookie 跨域

    解决cookie跨域访问_cookie 跨域浏览器对于javascript的同源策略(请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同.)的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(因为a.cn和b.cn是不同域),但是在前后端分离时我们经常会把服务端和前端放到不同域上,这时就需要跨域了.今天记录的是cookie的跨域访问。问题在此之前一直以为传统的服务器使用se…

    2022年10月1日
    0
  • Navicat for oracle创建数据库

    Navicat for oracle创建数据库前言其实在Oracle中的概念并不是创建数据库,而是创建一个表空间,然后再创建一个用户,设置该用户的默认表空间为我们新创建的表空间,这些操作之后,便和你之前用过的mysql数据库创建完数据库一模一样了(如果你用过mysql的话,当然如果Oracle是你用的第一个数据库系统,那上面这段话其实看不看并不重要)。但是,鉴于很多用过mysql的用户,在刚开始使用Oracle的时候都会不知道如何创建数据…

    2022年7月13日
    15
  • intellij 2021激活码【在线注册码/序列号/破解码】

    intellij 2021激活码【在线注册码/序列号/破解码】,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月19日
    40
  • 机器学习之支持向量机原理和sklearn实践

    1.场景描述问题:如何对对下图的线性可分数据集和线性不可分数据集进行分类?思路:(1)对线性可分数据集找到最优分割超平面(2)将线性不可分数据集通过某种方法转换为线性可分数据集下面将带着这

    2021年12月30日
    41
  • idea2022.01永久激活码[最新免费获取]

    (idea2022.01永久激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年4月2日
    205
  • getElementById获取元素

    getElementById获取元素<!DOCTYPEhtml><htmllang=”en”><head><metacharset=”UTF-8″><metaname=”viewport”content=”width=device-width,initial-scale=1.0″><metahttp-equiv=”X-UA-Compatible”content=”ie=edge”><title>D.

    2022年7月15日
    19

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号