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 存储过程 T–SQL 程序代码中,如果其传入参数被用于拼接动态 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(‘.‘, ‘int‘) as UserID 
   
from @ids.nodes(‘/ids/id‘) as 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(20) NULL, 
 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(2) As 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(“@UserID“, “Kathi“)

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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Android Studio实现多媒体播放器,音乐视频一体化

    Android Studio实现多媒体播放器,音乐视频一体化这次的网络版音乐视频播放器是在前面讲到的音乐播放器项目(AndroidStudio如何实现音乐播放器)基础上,将音乐文件与项目文件独立开,放在服务器的文件夹里面进行访问,除此之外还添加了视频播放器功能。本次项目综合了Android几乎所有知识,可以让大家熟练掌握Android程序开发的基本技术,涉及Android基础知识、UI界面、数据存储、四大组件、网络编程、高级编程、多媒体播放器、适配器配置等。大家熟练掌握可以对以后的Android开发有非常大的帮助。

    2022年6月26日
  • 喊山第二部_软组raid0

    喊山第二部_软组raid0原题链接喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤。呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的。原来它是彝族先民用来求援呼救的“讯号”,慢慢地人们在生活实践中发现了它的实用价值,便把它作为一种交流工具世代传袭使用。(图文摘自:http://news.xrxxw.com/newsshow-8018.html)一个山头呼喊的声音可以被临近的山头同时听到。题目假设每个山头最多有两个能听到它的临近山头。给定任意一个发

    2022年8月9日
  • DatabaseMetaData元数据

    DatabaseMetaData元数据通过java.sql.DatabaseMetaData接口,您可以获得有关您已连接到的数据库的元数据。例如,你可以看到哪些表的数据库,和什么中定义的列的每个表的数量,是否是给定功能支持等。DatabaseMetaData接口包含很多的方法,和并不是所有将在本教程中覆盖。你应该看看的JavaDoc。此文本将只是覆盖面不够,给你一种感觉,你可以用它。获得一个DatabaseMetaData实例

    2022年6月19日
  • Jenkins自动构建部署项目到远程服务器上

    Jenkins自动构建部署项目到远程服务器上1.下载jenkins下载地址:https://jenkins.io/启动jenkins方式有2种1.1切换到jenkins.war包的存放目录启动命令:java-jarjenkins.war启动jenkins访问:localhost:8080就能…

    2022年6月2日
  • wpsword表格转换成excel表格_wps文档表格怎么转换成wps表格

    wpsword表格转换成excel表格_wps文档表格怎么转换成wps表格相信经常做表的小伙伴,总会遇到Excel的格式转换问题,那么其实只要你通过以下几个方式,即可快速实现文件格式的转换,不信的话接下来就带各位一起看看吧!一、电脑端1.WPS格式转换首先是我们的WPS里面自带的格式转换功能,只要我们选择【PDF转Excel】按钮,然后就可以快速对PDF里面的表格提取出来,非常方便,平时需要做数据分析的小伙伴一定要记住这个操作了。2.office当然,如果你平时打印表格…

    2022年8月22日
  • phpmyadmin安装教程及配置设置

    phpmyadmin安装教程及配置设置.一般网上下载到的phpmyadmin是一个压缩包,我们将其释放到htdocs目录中,例如htdocs\phpmyadmin。  2.打开phpmyadmin目录,在此目录下是否有config.sample.inc.php文件,如果存在,那么将其改名为config.inc.php。(根据版本不同,有可能直接就有config.inc.php文件,那就无需改名,也有可能根本就没有config.

    2022年6月1日

发表回复

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

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