配色: 字号:
深入浅析
2016-10-26 | 阅:  转:  |  分享 
  
深入浅析.NET应用程序SQL注入

这篇文章主要介绍了.NET应用程序SQL注入的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下

1.准备工具:SQLSERVER,VisualStudio

2.数据库脚本和.net代码(c#)

3.SqlServerProfiler

SQL脚本代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30 USEMASTER

GO

--检索SQLTMP数据库是否存在

IFEXISTS(SELECTFROMSYSDATABASESWHEREname=''SQLTMP'')

--删除SQLTMP数据库

DROPDATABASESQLTMP

GO

--创建数据库

CREATEDATABASESQLTMP

GO

--使用SQLTMP数据库

USESQLTMP

GO

-------------创建一张表用来验证SQL注入漏洞----------------

--检索表是否存在

IFEXISTS(SELECTFROMSYSOBJECTSWHEREname=''admin'')

--删除表

DROPTABLEadmin

GO

--创建表

CREATETABLEadmin

(

idINTPRIMARYKEYIDENTITY(1,1),--设置主键

nameVARCHAR(20)NOTNULL,--用户名

passVARCHAR(20)NOTNULL--密码

)

-------------插入一条测试数据---------------------------

INSERTINTOadminVALUES(''admin'',''admin'')

--查询插入数据

SELECTFROMadmin 1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74 usingSystem;

usingSystem.Collections.Generic;

usingSystem.Linq;

usingSystem.Text;

usingSystem.Threading.Tasks;

usingSystem.Data;

usingSystem.Data.SqlClient;

namespaceSQLTmp

{

classProgram

{

//数据库连接字符串

publicstaticStringstrCon="DataSource=.;InitialCatalog=SQLTMP;IntegratedSecurity=True";

//创建数据库连接对象

staticSqlConnectionSqlCon=newSqlConnection(strCon);

staticvoidMain(string[]args)

{

Console.WriteLine("请输入用户名:");

Stringname=Console.ReadLine();

Console.WriteLine("请输入密码:");

Stringpass=Console.ReadLine();

try

{

Programp=newProgram();

//打开数据库连接

p.Open();

stringsql="SELECTCOUNT()FROMadminWHEREname=''"+name+"''ANDpass=''"+pass+"''";

SqlCommandsqlcom=newSqlCommand(sql,SqlCon);

inti=(int)sqlcom.ExecuteScalar();

if(i>0)

{

Console.WriteLine("登录成功!");

}

else

{

Console.WriteLine("登录失败!");

}

Console.ReadLine();

}

catch(Exception)

{

throw;

}

finally{

//关闭数据库连接

pass.Clone();

}

}

//打开数据库连接

publicvoidOpen()

{

//关闭状态下打开数据库连接

if(SqlCon.State==ConnectionState.Closed)

{

SqlCon.Open();

}

//中断情况下打开数据库连接

if(SqlCon.State==ConnectionState.Broken)

{

//关闭

SqlCon.Close();

SqlCon.Open();

}

}

//关闭数据库连接

publicvoidClose(){

if(SqlCon.State==ConnectionState.Open||SqlCon.State==ConnectionState.Broken)

{

SqlCon.Close();

}

}

}

}

我们来测试一下

输入正确的账号密码:

adminadmin



登录成功

输入错误的账号密码:

testtest



登录失败

我们在用户名输入:''or1=1--

密码:123



会发现也能登录成功!

数据库中没有这个账号密码,还会登录成功?

why?

0x03剖析

我们来剖析一下SQL语句的运行过程

利用我的SQL语句跟踪工具(SQLServerProfiler)



单击链接



运行

我们来看一下输正确的账号密码SQL语句的样子



在我们的SQLServer中执行看看,有符合条件的数据



我们再来看看输入错误的账号密码SQL语句的样子



在我们的SQLServer中执行看看,没有符合条件的数据



我们再来看看最后一次的输入的账号密码的SQL语句的样子



我们来看看图片中的SQL语句我们的上面的SQL语句对比一下

1

2

3 SELECTCOUNT()FROMSQLTMPWHEREname=''admin''ANDpass=''admin''

SELECTCOUNT()FROMSQLTMPWHEREname=''''or1=1--''ANDpass=''123''

我们会发现我们输入的用户名变成了空,后面多了or1=1--''这又是为什么,什么原因导致的???

到离这里我们就应该看看这一段代码:

1

2 stringsql="SELECTCOUNT()FROMadminWHEREname=''"+name+"''ANDpass=''"+pass+"''";

我们可以看出SQL是中的name和pass是变量是用户输入的账号和密码

我们来看一下输入的用户名:''or1=1--

那么用户如输入''的时候就会自动把name=''''闭合

而or1=1将where条件永远成立

--在SQL是注释的意思会将后面的SQL语句注释掉!!!

那么我们就可以这么认为SQL语句到最后是这个样子的

1 SELECTCOUNT()FROMSQLTMPWHEREname=''''or1=1 0x04防御

有攻击的方式是会有防御的方式

据我所知常用的有俩种方式:

1.通过SQLParameter

好处:预编译SQL语句防止被转意

用法:

1

2

3

4

5

6

7

8

9

10

11 stringsql="SELECTCOUNT()FROMadminWHEREname=[url=home.php?mod=space&uid=116087]@name[/url]ANDpass=@pass";

//创建SParameter[]

SqlParameter[www.visa158.com]para={

www.hunanwang.net"@name",name),

newSqlParameter("@pass",pass)

};

SqlCommandsqlcom=newSqlCommand(sql,SqlCon);

//通过Parameters.addRange方法将para[]放进去

sqlcom.Parameters.AddRange(para);

inti=(int)sqlcom.ExecuteScalar();



2.存储过程

1.首先在数据库中创建存储过程

1

2

3

4

5 CREATEPROCLogin(@nameVARCHAR(20),@passVARCHAR(20))

AS

SELECTCOUNT()FROMadminWHEREname=@nameANDpass=@pass

GO

2.调用存储过程

1

2

3

4

5

6

7

8

9

10

11

12 SqlParameter[]para={

newSqlParameter("@name",name),

newSqlParameter("@pass",pass)

};

SqlCommandsqlcom=newSqlCommand();

sqlcom.Connection=SqlCon;

sqlcom.CommandText="Login";

//指定执行类型为存储过程

sqlcom.CommandType=CommandType.StoredProcedure;

sqlcom.Parameters.AddRange(para);

inti=(int)sqlcom.ExecuteScalar();





















献花(0)
+1
(本文系白狐一梦首藏)