Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1199026
  • 博文数量: 272
  • 博客积分: 3899
  • 博客等级: 中校
  • 技术积分: 4734
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-15 14:53
文章分类

全部博文(272)

文章存档

2012年(272)

分类: 网络与安全

2012-06-26 15:55:02

还是关于前两天写的 server limit dos 的问题。

    我blog上这篇文章的访问量是我所有文章里攀升最快的,看来大家对这个还是比较感兴趣。

    之所以要再次出来讲这个问题,是因为在设计修补方案的时候遇到了困难。

    luoluo之前写了篇文章讲修补的困难。

    其实造成困难的主要原因是由于在apache中无法通过mod来修补这个问题。luoluo blog上的信息不全,我转载一下luoluo的技术分析部分

这两天调研了下apache层面解决server limit dos的可行性,结论是基本认定除

了修改apache源代码之外,没办法解决。

>

下面是具体的一些分析,大家看看有没有问题:

>

> apacheserver/protocol.c里关于http请求头处理相关代码:

>

> 837 request_rec *ap_read_request(conn_rec *conn)

>

> 838 {

>

> 839 request_rec *r;

>

> ...

>

> 880 r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */

>

> ...

>

> 917 if (!r->assbackwards) {

>

> 918 ap_get_mime_headers_core(r, tmp_bb);

>

> 919 if (r->status != HTTP_REQUEST_TIME_OUT) {

>

> 920 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,

>

> 921 "request failed: error reading the headers");

>

> 922 ap_send_error_response(r, 0);

>

> 923 ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);

>

> 924 ap_run_log_transaction(r);

>

> 925 apr_brigade_destroy(tmp_bb);

>

> 926 return r;

>

> 927 }

>

这里通过调用ap_get_mime_headers_core函数处理http头,如果处理后的status

不是之前设置的HTTP_REQUEST_TIME_OUT的话,就立即返回错误了,进去

> ap_get_mime_headers_core看:

>

> 670 AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r,

> apr_bucket_brigade *bb)

>

> 671 {

>

> ...

>

> 722 apr_size_t fold_len = last_len + len + 1; /* trailing null */

>

> 723

>

> 724 if (fold_len >= (apr_size_t)(r->server->limit_req_fieldsize)) {

>

> 725 r->status = HTTP_BAD_REQUEST;

>

这里如果设置大于limit_req_fieldsize值(core模块的配置

> LimitRequestFields)的话,则设置HTTP_BAD_REQUEST

>

那么也就是说客户端过来的请求头超长的话,就立即返回错误了,ap_hook函数

apachefilter都没有在这之间插入(写了hookfilter module测试过确

实这样),apache模块就没法解决这个问题,除非修改源代码,这也不是个好办

法,所以我们得想其他办法了。


还有朋友想到个取巧的办法,直接自定义一个错误返回页面,里面加了js,可以把cookie给清理掉。

但是这个办法也不行,原因和上面apache mod的原因一样,还不到自定义错误页面,apache就返回了。

所以想在apache上解决这个问题,可能只有修改源代码了,很矬,非常矬。

apache的设计可能是为了防止dos,可是当初设计的时候明显没有预估到web2.0 蓬勃发展的今天,会出现另外一种基于XSS WORM,或者类似的客户端dos的情景。


我之前曾有另外一篇blog,提到凡是不在apache层修改的,都属于不在正确的地方做正确的事情,都不是从本质上修改。这是因为,如果仅仅处理 set-cookie 的地方,是无法防范最大的威胁来源XSS的,而XSS中直接通过设置 document.cookie, 数据是不会通过服务器的。

除了XSS外,还有CRLF 也可以在http头中注射一个set-cookie,此外类似于 DNS欺骗ARP欺骗等能够在客户端直接发起攻击,如果服务器没有从根本上解决这个问题的话,很难抵御这些攻击。


除了apache,在服务器端另外解决问题的思路就是在apache的前面做方案,比如云舒提出的使用类似iptables来做七层的应用方案就是这种考虑。或者在负载均衡设备、防火墙上,均可以考虑做类似方案,但是付出的成本都相对较高。


我今天写这篇文章的原因,是为了呼吁从客户端解决这个问题

除了浏览器本身外,杀毒软件和主机安全软件,防挂马软件应该有能力和义务去检查浏览器发送的cookie长度,发现异常后,应该报警和重置cookie。

技术上实现应该不难,就是看大家的重视程度。虽然很悲哀,但现实就是这样:只有满脸桃花开,才会知道花儿为什么这样红!
   


更新:
可以直接修改apache 的配置文件参数,将server端的限制去掉:( 设置为0,就是没有限制 )

 

Limits the size of the HTTP request header allowed from the client
LimitRequestFieldsize bytes
LimitRequestFieldsize 8190
server config
Core
core

This directive specifies the number of bytes that will be allowed in an HTTP request header.

The LimitRequestFieldSize directive allows the server administrator to reduce or increase the limit on the allowed size of an HTTP request header field. A server needs this value to be large enough to hold any one header field from a normal client request. The size of a normal request header field will vary greatly among different client implementations, often depending upon the extent to which a user has configured their browser to support detailed content negotiation. SPNEGO authentication headers can be up to 12392 bytes.

This directive gives the server administrator greater control over abnormal client request behavior, which may be useful for avoiding some forms of denial-of-service attacks.

For example:

LimitRequestFieldSize 4094

Under normal conditions, the value should not be changed from the default.
Apache 2.0.53 or higher is required for increasing the limit above the compiled-in value of DEFAULT_LIMIT_REQUEST_FIELDSIZE (8190 as distributed).

参考:
阅读(1159) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~