首页 > 安全 > 网站安全 >

Sybase内的MS SQL Server 注入技术

2009-12-27

西关注:原文来自数据库黑客大曝光—— 数据库服务器防护术,真正要研究数据库安全的可以买一本看看,支持正版。本文来自第十四章。 Sybase的攻击和防御是一个广泛的主题,因此本章试图提取问题的本质,并演示一些有趣的攻击和场景。在

西关注:原文来自数据库黑客大曝光—— 数据库服务器防护术,真正要研究数据库安全的可以买一本看看,支持正版。本文来自第十四章。

Sybase的攻击和防御是一个广泛的主题,因此本章试图提取问题的本质,并演示一些有趣的攻击和场景。在防御方面,如果可能的话,可以采取很多措施以增加攻击的难度。本章涉及了很多防御问题。

但是首先需要定位Sybase服务器并确定其配置。

14.1 发现目标
攻击Sybase服务器的第一步是在网络中定位服务器。本节描述了多种定位Sybase服务器的方法。

14.1.1 扫描Sybase
正如前面已经注意到的,Sybase通常监听一 些众所周知的TCP端口—— 5000-5004、8181和8182。配置Sybase监听不同的端口是很容易的,但是这些众所周知的端口真的帮了大忙。使用端口扫描工具,例如 Fyodor的nMap(http://www.insecure.org/nmap),是通过特定已知的开放端口定位主机的最好的方式。

如果可以在网络内远程访问Windows注册表,检查ODBC数据源将非常有用。在

HKEY_LOCAL_MACHINESoftwareODBC

内仅仅搜索SybaseServerName和NetworkAddress就可以看到主机名、IP地址和配置在有疑问的主机上的任何ODBC数据源的TCP端口。

如果公司有LDAP基础结构,也可以使用LDAP查询。

14.1.2 Sybase版本号
Sybase身份验证失败的响应数据包内包含了服务器的主(major)版本号和次(minor)版本号,因此嗅探身份验证失败的数据包可以获得版本号。该数据包看起来就像如下所示:

Ethernet Header

IP Header

TCP Header

Source port: 5000

Dest port: 1964

Flags: 0×18 (ACK PSH )

Raw Data

04 01 00 4e 00 00 00 00 ad 14 00 06 05 00 00 00 ( N )

0a 73 71 6c 20 73 65 72 76 65 72 0c 05 00 00 e5 ( sql server )

23 00 a2 0f 00 00 01 0e 05 5a 5a 5a 5a 5a 00 01 (# ZZZZZ )

00 0e 00 4c 6f 67 69 6e 20 66 61 69 6c 65 64 2e ( Login failed. )

0a 00 00 00 00 fd 02 00 02 00 00 00 00 00 ( )

紧跟在字符串“sql server”后面的4个字节是版本号—— 0×0c=12,0×05=5,因此该主机的版本号是12.5.0.0。用这种方式取得版本号并不是故事的全部—— 需要去验证并select @@version以得到那些信息—— 至少能得到某种暗示。发送前述数据包的服务器实际上正在运行ASE 12.5.1。

利用轻微删简的身份验证数据包有可能得到Sybase服务器的版本号。根据我们的试验,即使设置了身份验证日志选项,被删简的身份验证尝试也不会被记入日志。这就很好了,因为我们并不真的要尝试身份验证;我们只想在错误响应中获得服务器的版本信息。

为了可以把失败与成功的身份验证尝试记录到日志中,执行如下命令:

sp_configure ‘log audit logon failure’, 1

sp_configure ‘log audit logon success’, 1

在本章的末尾您可以找到实现一个简化工具的C源代码,该代码实现了通过删简的身份验证数据包来获得Sybase版本。

14.1.3 窥探身份验证
在默认的“即开即用”(out of the box)配置内,Sybase以明文形式在网络上传递口令。这是一个如此明显和著名的安全风险,以至于几乎所有的公司都曾采用某种缓解措施—— 或者采用Sybase的建议并部署一种更高级的身份验证方式,例如Kerberos,或者使用加密的IPSec通道或类似措施。虽然如此,默认配置偶尔还 是会出现,因此要留意从Sybase客户机到普通Sybase服务器端口5000-5004的通信量,那里也许很可能就有明文的口令。

因为支持多数本地数据库身份验证机制,也有可能 发动中间人(man-in-the-middle)攻击。当攻击者假装是数据库服务器时,就会出现该场景。通常,攻击者将不得不侵入一台DNS或WINS 服务器才能这么做,但是这依赖于网络内的名字解析基础结构,也许可以直接攻击。

14.2 攻击Sybase
本节讨论攻击Sybase服务器的技术。这些技术可应用于多种情况;例如,在“SQL注入”下列举的几个技术与攻击者可以发出任意SQL查询的每个情况都相关。

14.2.1 Sybase中的SQL注入
Sybase在SQL注入方面有一个特有的问 题,这部分地是因为它共享了基于Microsoft SQL Server的ancestral代码。因为Microsoft平台上的SQL注入已经被研究得非常透彻,并且因为Sybase共享了很多相同的性质,这 使得Microsoft SQL Server相当容易遭受SQL注入攻击(成批查询、全面subselect支持、非常有帮助的错误消息),即使攻击者对Sybase了解不多,也非常有 可能“找到附近的路”。此外,Sybase提供了一整套新功能,该功能可被攻击者在SQL注入攻击的上下文内利用,Java集成就是一个非常典型的示例。

本节提供了简短的SQL注入的最新技术资料,评估被到处宣扬的Sybase环境内的Microsoft SQL Server攻击技术的有效性,然后研究一些Sybase特有的技术,例如Java-In-SQL和通过proxy表进行的文件系统交互。

在深入涉及SQL注入机制之前,先简短地讨论一 下严重性和有效范围。如果Sybase服务器(和XP服务)正以低特权用户运行,Web应用程序用于连接的Sybase用户是低特权的,并且全面安装了最 新的补丁,那么就从根本上降低了SQL注入的实际影响。但这仍是个严重的问题,因为攻击者仍然可以对数据做应用程序可以做的每件事情,但是降低了攻击者把 数据库服务器作为进入内部网络的登陆场的可能性。

我们将在本章的后续部分对防御做大体上的讨论。

14.2.2 SQL注入基础
为了恰当地讨论SQL注入,需要一个可以充分演 示该问题的应用程序样例。通常人们最关心Web应用程序内的SQL注入,因此我们将用一个非常简单的Web应用程序做样例。对于应用程序样例在决定技术平 台时存在困难,因为Sybase支持很多种机制。因为Java是Sybase策略的一个关键部分,一个小型的基于Servlet的Java Web应用程序可能是恰当的样例。

下面是一个小型Java Servlet样例的源代码,该程序在Sybase默认数据库pubs2内按照包含特定搜索字符串的标题查询书籍。可以将其安装在任何支持Servlet的Web服务器上,例如Tomcat。

import java.io.*;

import java.lang.*;

import java.net.*;

import java.sql.*;

import javax.servlet.*;

import javax.servlet.http.*;

import com.sybase.jdbc2.jdbc.*;

public class BookQuery extends HttpServlet

{

public void init(ServletConfig config) throws.ServletException

{

super.init(config);

}

public void destroy(){}

protected void processRequest(

HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException

{

PrintWriter out = response.getWriter();

try

{

response. setContentType (“text/html”);

out.println(“<html><headxtitle>Book Title Search

Results</title></head>”);

out.println(“<bodyxhl>Search results</hl>”) ;

Class.forName(“corn.Sybase.jdbc2.jdbc.SybDriver”);

Connection con = DriverManager.getConnection(“jdbc:

Sybase:Tds:sybtest:5000″,”sa”, “sapassword”);

Statement stmt = con.createStatement();

String search = request.getParameter(“search”);

ResultSet rs = stmt.executeQueryt”select * from

pubs2..titles where UPPER(title) like UPPER(‘%” + search + “%’)”);

int numberOfColumns = rs.getMetaData().getColumnCount();

rs.next();

out.println(“<TABLE border=l>”);

while( !rs.isAfterLast())

{

out.print(“<TR>”) ;

for(int i = 1; i <= numberOf Columns; i++)

{

out.print(“<TD>”);

out.print(rs.getString(i));

out.print(“</TD>”);

}

out.print(“</TR>”);

rs.next();

}

rs.close();

out.println(“</TABLE>”);

out.println(“</body>”);

out.println(“</html>”);

}

catch( SQLException e )

{

while( e != null )

{

out.println(e);

e = e.getNextException();

}

}

catch( Exception e )

{

out.printin(“Exception:” + e);

}

}

protected void doGet(HttpServletRequest request, HttpServletResponse

response)

throws ServletException, IOException

{

processRequest(request, response);

}

protected void do Post(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException

{

processRequest(request

相关文章
最新文章
热点推荐