游客发表
MSSQL注入的攻击面,往往比想象中要宽得多。上周帮一家做跨境电商的客户做渗透测试,他们的后台订单查询接口,仅仅因为拼接了用户输入的排序字段,就让我拿到了`sa`权限。更讽刺的是,他们的WAF规则里明明写了拦截`'`和`--`,可我用一个分号加注释符`/*`就绕了过去——WAF只防了脚本小子,没防住真正懂协议的人。
注入的本质是数据与代码的边界被打破。在MSSQL里,这种打破比MySQL更致命,因为它的存储过程、`xp_cmdshell`、`OPENROWSET`这些特性,让攻击者从“读数据”直接跃迁到“控制操作系统”。比如经典的`';exec master..xp_cmdshell 'whoami'--`,在2008版本之前几乎畅通无阻。我见过最极端的案例,是某银行内部系统被注入后,攻击者用`sp_addlogin`给自己加了账号,再通过`OPENQUERY`跨库查询,把整个内网数据库拖了个遍——整个过程没触发任何告警,因为他们的审计只盯着`SELECT`语句,忽略了`EXEC`。
但别急着背payload,先理解MSSQL的独特语法习惯。它不像MySQL那样用`#`注释,而是用`--`和`/* */`。它的字符串拼接用`+`,不像Oracle用`||`。它的错误信息详细得吓人,`CONVERT(int, @@version)`直接能把版本号炸出来。这些细节决定了注入手法的差异。比如判断列数,MSSQL里用`ORDER BY n`配合`HAVING`报错,比MySQL的`UNION SELECT`更隐蔽——因为很多开发者会过滤`UNION`,却漏了`HAVING`。
绕过过滤的骚操作更多。我常用的是`%25`编码配合`DECLARE`声明变量,把敏感词拆开再拼接。比如`DECLARE @s varchar(99) SET @s='xp_'+'cmdshell' EXEC(@s)`,这种写法能骗过所有基于正则的检测。还有个偏门技巧:MSSQL的`QUOTENAME`函数会把输入自动加方括号,利用`QUOTENAME('dbo')`来构造闭合,有时能绕过参数化查询的严格校验——当然这需要对方代码写得足够烂,但现实是,很多老系统的存储过程里,动态SQL满天飞。
修复方式其实不复杂,但企业总爱走弯路。参数化查询是正解,可有些DBA觉得改代码成本高,就只封了`xp_cmdshell`。结果呢?攻击者改用`sp_oacreate`调用COM对象,照样能执行命令。还有更狠的,用`OPENROWSET`连接回自己的SQL Server,把数据通过DNS请求外带——这招连防火墙都拦不住,因为DNS流量通常是被放行的。我见过一个案例,对方封了所有出站端口,唯独漏了53端口,攻击者就用`xp_dirtree`配合UNC路径,把数据藏在SMB请求里传出去。
说到底,MSSQL注入的核心不是某个漏洞,而是对数据库特性的理解深度。你越了解它的扩展功能,攻击面就越大。我见过最离谱的修复方案,是有人把所有存储过程都禁了,结果业务系统直接瘫痪——因为连`sp_who`都用不了。安全不能靠一刀切,得在功能与风险之间找平衡。比如给`public`角色去掉`VIEW ANY DEFINITION`权限,比删存储过程实际得多。或者用`LOGON TRIGGER`限制特定IP的登录,比改代码更立竿见影。
最后说个实战细节:测注入时别总盯着报错信息。MSSQL的`WAITFOR DELAY '0:0:5'`是最干净的盲注验证方式,延迟5秒比任何报错都可靠。而且它不会在日志里留下`EXEC`记录——因为它是T-SQL语句,不是存储过程调用。你要是真想隐藏痕迹,就用`IF (SELECT COUNT(*) FROM sysobjects) > 100 WAITFOR DELAY '0:0:5'`,这种条件延迟比直接sleep更难被IDS识别。
友情链接