当前位置: 移动技术网 > IT编程>开发语言>.net > 深入浅析.NET应用程序SQL注入

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

2017年12月12日  | 移动技术网IT编程  | 我要评论

汉诺威大学,韦驮天翔国语版,书虫成神记

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

登录成功

输入错误的账号密码:

test test

登录失败

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

密码:123

会发现也能登录成功!

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

why?

0x03剖析

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

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

单击链接

运行

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

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

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

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

我们再来看看最后一次的输入的账号密码的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>

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

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注入就给大家介绍到这里,希望对大家有所帮助

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网