中国教育和科研计算机网
EDU首页 |  中国教育 |   高校科技 |   教育信息化 |   CERNET
教育信息化

资讯 | 专题 会议 观点 专栏 访谈 企业 产品 CIO 技术 校园信息化 下一代互联网 IPv6视频课堂

中国教育网 > 教育信息化
您现在的位置: EDU首页 > 教育信息化 > 网络安全
做好网络安全防护 让Web远离木马
http://www.edu.cn   2009-12-30 中国教育和科研计算机网 作者:戴世冬

字体选择:【大】 【中】 【小】

  破解Web典型攻击

  作为Web攻击的典型应用,SQL注入和跨站攻击一直是人们关注的热点。
  SQL注入
  1.原理
  SQL注入是通过把SQL命令注入到B/S应用或C/S应用中,最终达到欺骗服务器执行恶意SQL命令的一种攻击行为。
  产生SQL注入漏洞的根源在于程序命令和用户数据之间没有做到泾渭分明,这使得攻击者有机会将程序命令当作用户输入的数据提交给程序执行。如果编写B/S应用或C/S应用的程序员未对用户输入进行仔细检查就传入SQL语句,即导致SQL注入漏洞的产生。
  目前常见的SQL注入一般存在于B/S模式的Web应用中。各种架构类型的网站,包括ASP+SQL Server,ASP+Access,PHP+MySQL等都是通过SQL语句与数据库进行交互,SQL的广泛应用导致SQL注入成为攻击Web系统的一个重要手段。
  一般来说,攻击者通过SQL注入可以猜测用户密码、获取数据库内容和系统权限。

  2.演示
  本文通过一个简单的演示来展示攻击者通过SQL注入能够达到的目的。
  最常见的SQL注入存在于如:http://xxx.xxx.xxx/xxx.php?x=y的动态页面中。这种动态页面带有1个或多个参数,只要该页面用所带的参数与数据库进行交互,那么就有可能存在SQL注入漏洞。下面以http://127.0.0.1/show.php?id=x为例,进行一次针对PHP+MySQL架构的虚拟SQl注入。

  (1)用1=1,1=2测试法判断漏洞存在与否
  发送以下三个请求:
  http://127.0.0.1/show.php?id=1
  http://127.0.0.1/show.php?id=1 and 1=1
  http://127.0.0.1/show.php?id=1 and 1=2
  存在注入漏洞的表现是:
  第一个请求正常显示,此时提交给数据库的SQL语句类似:select * from 表名 where id=1。
  第二个请求正常显示,内容与上一个的相同,此时提交给数据库的SQL语句类似:select * from表名 where id=1 and 1=1。
  第三个请求显示错误信息或显示自定义的信息,此时提交给数据库的SQL语句类似:select * from 表名 where id=1 and 1=2。
  满足以上3个条件的页面肯定存在SQL注入漏洞。

  (2)判断数据库类型
  不同类型的数据库使用的函数和注入方法都有差异,因此在注入前需要判断数据库的类型。
  方法一,根据出错信息判断数据库类型。
  如果服务器未关闭出错信息,那么通过构造错误的SQL语句就可以从返回的出错信息中得到数据库类型。
  方法二,通过数据库内置函数或系统表判断数据库类型。
  如果服务器关闭了出错信息,那么可以通过数据库的内置函数或系统表来判断数据库的类型。
  利用数据库的系统表也可以达到相同的目的。例如MySQL数据库有个mySql.user表,记录着数据库的用户信息,构造SQL语句查询该表就可以判断服务器端是否使用MySQL数据库。当请求http://127.0.0.1/show.php?id=1 and (select count(*) from mySQL.user)>0的结果时,能够返回正常的内容说明服务器端使用MySQL数据库。

  (3)猜解当前数据库用户名
  利用MySQL的内置函数,用ASCII解码法可以逐字猜解当前的数据库用户名。由于MySQL数据库默认使用root用户,因此可以通过发送下面这个请求进行验证:http://127.0.0.1/show.php?id=1 and ord(mid(user(),1,1))=114。其中114是字符r对应的ASCII码。如果页面返回正常内容,则表示当前数据库用户名的第一个字母是r,用此方法可以逐字推测出当前数据库用户名。

  (4)猜解数据表
  猜解表名可以用类似http://127.0.0.1/show.php?id=1 and (select count(*) from member)>=0的请求。如果页面返回正常内容,则说明数据库中存在member这个表,否则就说明不存在这个表。循环此操作,直到猜解出表名为止。
  请求http://127.0.0.1/show.php?id=1 and (select count(*) from member)>=0返回页面异常,说明不存在member这个表。
  请求http://127.0.0.1/show.php?id=1 and (select count(*) from user)>=0返回正常页面,说明存在user这个表。

  (5)猜解字段名和字段数
  猜解字段名可以采用跟猜解表名类似的方法,将select count(*)改为select count(字段名)。请求http://127.0.0.1/show.php?id=1 and (select count(id) from user)>=0猜解user表中是否有id这个字段,返回正常页面说明存在id这个字段。
  利用SQL语句中union的特性,提交类似http://127.0.0.1/show.php?id=1 union select 1,1这样的请求可以快速确定当前表中的字段个数。此时提交的SQL语句相当于“select * from 表名 where id=1 union select 1,1”,只有union select的个数与当前表中的字段数相同时,这个SQL语句才能正常执行,页面才能返回正常的内容,而select 1的个数就相当于当前表中的字段数。
  当union select的个数与当前表中字段数不一致时,返回页面异常。
  当union select的个数与当前表中的字段数相同时,返回正常页面。

  (6)猜解字段内容
  猜解字段分为猜解本表的字段和猜解跨表的字段。
  首先是猜解本表的字段。假设已经猜解出本表的表名是article,其中有一个字段是title,接下来就要猜解各列对应的title字段的内容。采用与猜解数据库用户名类似的ASCII解码法,提交请求http://127.0.0.1/show.php?id=1 and ord (mid(title,1,1))=116,页面返回正常内容说明当前表中id为1的记录所对应的title字段第一个字母为t。
  依次类推,可以猜解出本表各字段的完整内容。
  接下来猜解跨表的字段。假设已经猜解出另一个表名为user,其中包含id,username,password三个字段。此时需要用到union的一个特性:用union连接的两条SQL语句,当前一个select语句为假时,最终只返回第2个select语句的结果。因此可以构造特殊的SQL语句,让页面显示我们需要的特定数据。构造请求http://127.0.0.1/show.php?id=999 union select 1, username, password from user where user.id=1时,原先显示文章内容的位置现在显示的是user表中id为1的username列内容。
  类似的,调换第2个select中的username和password的顺序构造请求http://127.0.0.1/show.php?id=999 union select 1, password, username from user where user.id=1时候,原先显示文章内容的位置现在显示的是user表中id为1的password列内容。以此类推,可以猜解出user表中其他的username和password内容。

  3.防御方法
  防御SQL注入一般从两个方面着手:一是对服务器端进行安全设置,二是对客户端的输入进行严格验证。
  服务器端的安全设置:
  (1)关闭服务器的错误信息。攻击者可以从服务器返回的错误信息中得到很多有用的信息,包括服务器端的数据库类型、Web服务器类型、数据表的名称等。
  (2)对于使用PHP的服务器,设置magic_quotes_gpc为on。这一设置使得传递参数时自动过滤一些特殊字符,给攻击者的注入行为制造一些麻烦。
  (3)不要使用默认的管理员账号连接数据库。默认的数据库管理员账号,如MySQL的root账号和MSSQL的SA账号,都拥有系统权限,如果没有设置密码或者设置弱密码,易于被攻击者侵入并拿到系统权限。
  (4)根据实际情况,不同的数据库账号只分配满足需求的最小权限。
  (5)给数据库账号设置较强的密码,必要时定期更换密码。
  (6)及时更新系统补丁,避免攻击者利用系统漏洞进行攻击。

  客户端的输入验证:
  (1)验证客户端输入的类型。例如对于要求是整形的客户端输入,在PHP程序中可以先用intval()函数处理,然后再提交执行。在上文演示的服务端程序中,将SQL查询语句改为:mysql_query("SELECT * FROM article WHERE id=".intval($id)."");这样就将客户端输入先转换为整型,然后再提交给SQL语句执行,这提高了整个程序的安全系数。
  (2)过滤敏感数据。敏感数据主要是与SQL语句相关的字符和字符串,如“’”,“;”,“=”,“<”,“>”,“and”,“or”,“union”,“select”,“insert”,“delete”,“update”等,同时也包括这些字符和字符串的十进制和十六进制形式。服务端程序先对接收到的客户端输入进行验证,只有通过验证全部合法的输入数据才提交给SQL语句执行。

页面功能 【打印】 【关闭】 【我有话说

MOOC风暴来袭

版权所有:中国教育和科研计算机网网络中心 CERNIC,CERNET,京ICP备15006448号-16,京网文[2017]10376-1180号

关于假冒中国教育网的声明 | 有任何问题与建议请联络:Webmaster@staff.cernet.com