欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

深入浅析.NET应用程序SQL注入

程序员文章站 2023-11-30 08:05:34
1.准备工具:sql server ,visual studio 2.数据库脚本和.net代码(c#) 3.sqlserver profiler sql脚本代码:...

1.准备工具:sql server ,visual studio

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

3.sqlserver profiler

sql脚本代码:

use master 
go
--检索sqltmp数据库是否存在
if exists(select * from sysdatabases where name = 'sqltmp')
--删除sqltmp数据库
drop database sqltmp
go
--创建数据库
create database sqltmp
go
--使用sqltmp数据库
use sqltmp
go
-------------创建一张表用来验证sql注入漏洞----------------
--检索表是否存在
if exists(select * from sysobjects where name = 'admin')
--删除表
drop table admin
go
--创建表
create table admin
(
id int primary key identity(1,1),--设置主键
name varchar(20) not null,--用户名
pass varchar(20) not null--密码
)
-------------插入一条测试数据---------------------------
insert into admin values('admin','admin')
--查询插入数据
select * from admin

下面是一段验证用户名密码的c#代码:

<font size="3" color="#ff00ff">using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using system.data;
using system.data.sqlclient;
namespace sqltmp
{
class program
{
//数据库连接字符串
public static string strcon = "data source=.;initial catalog=sqltmp;integrated security=true";
//创建数据库连接对象
static sqlconnection sqlcon = new sqlconnection(strcon);
static void main(string[] args)
{
console.writeline("请输入用户名:");
string name = console.readline();
console.writeline("请输入密码:");
string pass = console.readline();
try
{
program p = new program();
//打开数据库连接
p.open();
string sql = "select count(*) from admin where name = '"+name+"'and pass = '"+pass+"'";
sqlcommand sqlcom = new sqlcommand(sql, sqlcon);
int i = (int)sqlcom.executescalar();
if (i > 0)
{
console.writeline("登录成功!");
}
else
{
console.writeline("登录失败!");
}
console.readline();
}
catch (exception)
{
throw;
}
finally {
//关闭数据库连接
pass.clone();
}
}
//打开数据库连接
public void open()
{
//关闭状态下打开数据库连接
if (sqlcon.state == connectionstate.closed)
{
sqlcon.open();
}
//中断情况下打开数据库连接
if (sqlcon.state == connectionstate.broken)
{
//关闭
sqlcon.close();
sqlcon.open();
}
}
//关闭数据库连接
public void close() {
if (sqlcon.state == connectionstate.open || sqlcon.state == connectionstate.broken)
{
sqlcon.close();
}
}
}
}
</font>

我们来测试一下

输入正确的账号密码:

admin admin

深入浅析.NET应用程序SQL注入

登录成功

输入错误的账号密码:

test test

深入浅析.NET应用程序SQL注入

登录失败

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

密码:123

深入浅析.NET应用程序SQL注入

会发现也能登录成功!

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

why?

0x03剖析

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

利用我的sql语句跟踪工具(sql server profiler)

深入浅析.NET应用程序SQL注入

单击链接

深入浅析.NET应用程序SQL注入

运行

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

深入浅析.NET应用程序SQL注入

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

深入浅析.NET应用程序SQL注入

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

深入浅析.NET应用程序SQL注入

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

深入浅析.NET应用程序SQL注入

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

深入浅析.NET应用程序SQL注入

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

<font size="3" color="#ff00ff">select count(*) from sqltmp where name = 'admin' and pass = 'admin'
select count(*) from sqltmp where name = '' or 1=1 -- ' and pass = '123'
</font>

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

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

<font size="3" color="#ff00ff"> string sql = "select count(*) from admin where name = '"+name+"'and pass = '"+pass+"'";
</font>

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

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

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

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

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

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

<font size="3" color="#ff00ff">select count(*) from sqltmp where name = '' or 1=1</font>

0x04防御

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

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

1.通过sqlparameter

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

用法:

<font size="3" color="#ff00ff">string sql = "select count(*) from admin where name = [url=home.php?mod=space&uid=116087]@name[/url] and pass = @pass "; 
//创建sparameter[]
sqlparameter[] para = {
new sqlparameter("@name",name),
new sqlparameter("@pass",pass)
};
sqlcommand sqlcom = new sqlcommand(sql, sqlcon);
//通过parameters.addrange方法将para[]放进去
sqlcom.parameters.addrange(para);
int i = (int)sqlcom.executescalar();
</font>

@符号代表的参数,我们把拼接的方式换成了参数的形式

深入浅析.NET应用程序SQL注入

2.存储过程

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

<font size="3" color="#ff00ff">create proc login (@name varchar(20) ,@pass varchar(20))
as
select count(*) from admin where name =@name and pass = @pass
go
</font>

2. 调用存储过程

<font size="3" color="#ff00ff">sqlparameter[] para = {
new sqlparameter("@name",name),
new sqlparameter("@pass",pass)
};
sqlcommand sqlcom = new sqlcommand();
sqlcom.connection = sqlcon;
sqlcom.commandtext = "login";
//指定执行类型为存储过程
sqlcom.commandtype = commandtype.storedprocedure;
sqlcom.parameters.addrange(para);
int i = (int)sqlcom.executescalar();
</font>

深入浅析.NET应用程序SQL注入

好了,关于本文给大家介绍的.net应用程序sql注入就给大家介绍到这里,希望对大家有所帮助