(OWASP汉化)攻击系列大全(二十六):拒绝服务

最近修订日期(年/月/日):3/2/2005

漏洞描述

拒绝服务(DoS)攻击的目标是使得资源(站点、应用程序、服务器)不能实现它预订的设计目的。有许多方法(比如操纵网络数据包、编程、逻辑或资源处理漏洞等等)能够使得合法用户无法使用服务。如果一项服务收到了大量的请求,那么它可能会停止向合法用户提供。同样的道理,当程序漏洞被利用时,服务会可能会停止或者处理它使用的资源的方式。
有时候攻击者能够在服务器被DoS攻击时进行注入或执行任意代码以获得关键信息或在服务器上执行命令。
DoS攻击严重地降低了合法用户的使用体验。这些攻击会导致大量响应延迟,过度损耗和服务中断,从而直接影响可用性。

风险因数

风险因数可以分为很多种。风险的两个主要来源包括资源不足和非技术威胁因素。
当系统架构的设计没有考虑到访问流量溢出时,则需要关注风险因素的第一个例子 – 资源不足。这种风险降低了成功执行DoS攻击的难度并且可以在不进行实际攻击的情况下造成DoS症状。
第二个例子可能是最大的风险因素,它并不是技术性的问题,而是在于公共关系或者关键性通信的范围上。一个组织应该避免一些可能使其成为DoS攻击目标的行动,除非这样做的好处超过潜在的成本或者能够减轻管理权。
其他的风险因素可能依赖于具体的环境而存在。

例子

以下的DoS攻击技术和例子是从OWASP Testing Guide v2中提取的。

DoS用户指定的对象分配

如果用户可以直接或间接地提供一个能够指定在应用程序服务器上创建多少个对象的值,且如果服务器没有对其进行严格的控制,那么可能会导致环境运行所需内存超过可用内存。服务器一开始可能会分配指定数量的对象,但如果数量非常庞大,那可能使服务器出现严重的问题,比如填满整个可用内存空间并破坏其性能。
以下是Java中易受攻击代码的一个简单示例:

String TotalObjects = request.getParameter(“numberofobjects”);
int NumOfObjects = Integer.parseInt(TotalObjects);
ComplexObject [] anArray = new ComplexObject [NumOfObjects]; //错了!

DoS用户对循环计数器的输入

与前面用户指定的对象分配的问题类似,如果用户可以直接或间接指定一个值为循环函数所用,这可能会导致服务器出现问题。
以下是Java中易受攻击的代码示例:

public class MyServlet extends ActionServlet {
   public void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
          . . . 
          String [] values = request.getParameterValues("CheckboxField");
      // 处理未经合理范围检查的数据——错误!
          for ( int i=0; i<values.length; i++) {
                // 大量的逻辑来处理请求
         }
         . . . 
   }
    . . . 
}

正如我们在例子中所看到的,用户可以对循环计数器进行控制。如果循环的代码对资源要求非常高,并且攻击者强制它多次执行,这就可能会降低服务器处理其他请求的性能,从而导致DoS条件。

DoS未能释放资源

如果应用程序发生错误使得正在使用的资源不被释放,那么它可能将无法被继续使用。可能的例子有;
– 应用程序锁定一个文件进行写入操作,并且在这时候发生了异常,使其没有明确地关闭或者解锁该文件。
– 内存泄漏发生在开发者对内存管理负有责任的编程语言中,比如C和C++。在错误导致正常的逻辑流程被绕过的情况下,所分配的内存可能不会被移除或者出于一个垃圾收集器是否需要将其回收的状态。
– 如果一个异常出现,则使用DB去连接没有释放对象的地方。许多这样的重复请求可能会导致应用程序使用所有数据库连接,因为代码仍然会保存打开的数据库对象,而不释放资源。
以下是Java中易受攻击代码的示例。在这个例子中,Connection和CallableStatement都应该在finally块中关闭。

public class AccountDAO {
    … …
    public void createAccount(AccountInfo acct)  
                 throws AcctCreationException {
       … …
           try {
            Connection conn = DAOFactory.getConnection();
            CallableStatement  calStmt = conn.prepareCall(…);
          …  …  
           calStmt.executeUpdate();
           calStmt.close();
          conn.close();
       }  catch (java.sql.SQLException e) {
            throw AcctCreationException (...);
       }
    }
}

DoS缓冲区溢出

任何由开发者负责对内存分配直接管理的编程语言,特别是C和C++,具有缓冲区溢出的潜在可能。能够在服务器执行任意的代码是缓冲区溢出相关的最严重的风险,但第一个风险来自于当程序奔溃时可能发生的拒绝服务。
以下是C中易受攻击代码的简单示例:

void overflow (char *str) {
   char buffer[10];
   strcpy(buffer, str); // 危险!
}

int main () {
  char *str = "This is a string that is larger than the buffer of 10";
  overflow(str);
}

如果这段代码被执行,那么他将会导致分段错误或者中心丢失。原因是strcpy会尝试将53个字符复制到只包含10个元素的数组中,覆盖相邻的内存位置。虽然上面这个例子是一个非常简单的例子,但实际情况中,在基于Web的应用程序中很可能会有用户输入的长度没有被充分检查使得这种攻击成为可能的地方。

DoS会话中存储太多数据

需要注意不要在用户会话对象中存储太多数据。在会话中存储太多信息(比如从数据库中检索大量的数据)可能会导致拒绝服务的问题产生。如果会话数据在登录之前就被追踪,那么问题将会恶化,因为用户可以在不需要帐户的情况下启动攻击。

DoS锁定用户帐户

DoS案例中首先要考虑的就是应用程序所涉及的身份验证系统。常见的防止暴力破解用户密码的防御措施是在三次到五次登录失败之后对用户进行锁定。这意味着,直到他们的帐号被解锁前,即使合法用户提供了正确的密码后也无法登录到系统。如果能够预测到有效用户登录的方法,则可把这种防御机制转为针对应用程序的DoS攻击。
请注意,这里有一个关于商业与安全之间的平衡,这必须根据给定应用程序的具体情况而定。锁定帐户有利有弊,对用户来说,可以选择自己的帐户名称,使用CAPTCHA等系统。每个企业都需要平衡风险与收益,但不是所有这些决策的细节都取决于这里。

相关的威胁代理

相关攻击

相关的漏洞

相关控件

参考

  • http://capec.mitre.org/data/index.html – 通过资源耗尽拒绝服务