Web应用防火墙(WAF),CC attack简介

WAF的原理

WAF一句话描述,就是解析HTTP请求(协议解析模块),规则检测(规则模块),做不同的防御动作(动作模块),并将防御过程(日志模块)记录下来。所以WAF的实现由五个模块(配置模块、协议解析模块、规则模块、动作模块、错误处理模块)组成。

WAF具体实施(以cc_attack 为例)

CC(challenge collapsar) attack是什么

CC攻击是攻击者借助代理服务器生成指向受害主机的合法请求,实现DDoS和伪装攻击。攻击者通过控制某些主机不停地发送大量数据包给对方服务器,造成服务器资源耗尽,直至宕机崩溃。例如,当一个网页访问的人数特别多的时候,用户打开网页就慢了,CC攻击模拟多个用户(多少线程就是多少用户)不停地访问需要大量数据操作(需要占用大量的CPU资源)的页面,造成服务器资源的浪费,CPU的使用率长时间处于100%,将一直在处理连接直至网络拥塞,导致正常的访问被中止。

接入层如何甄别CC attack

function cc_attack_check()
    if config_cc_check == "on" then
        -- get uri from lua-nginx-module
        local ATTACK_URI=ngx.var.uri
        -- .. Concatenates two strings.
        local CC_TOKEN = get_client_ip()..ATTACK_URI
        -- create a dict called limit in ngx.shared
        local limit = ngx.shared.limit
        -- get CCcount and CCseconds (配置文件中)
        CCcount=tonumber(string.match(config_cc_rate,'(.*)/'))
        CCseconds=tonumber(string.match(config_cc_rate,'/(.*)'))
        -- get value of CC_TOKEN(client_ip..uri)
        local req,_ = limit:get(CC_TOKEN)
        -- check req times, if bigger than CCcount then log the request and 
        -- return 403 to client
        if req then
            if req > CCcount then
                log_record('CC_Attack',ngx.var.request_uri,"-","-")
                if config_waf_enable == "on" then
                    ngx.exit(403)
                end
            else
            -- if not bigger than, {CC_TOKEN: req + 1}
                limit:incr(CC_TOKEN,1)
            end
        else
            -- set limit {CC_TOKEN: 1} and exptime at first req
            limit:set(CC_TOKEN,1,CCseconds)
        end
    end
    return false
end

function get_client_ip()
    CLIENT_IP = ngx.req.get_headers()["X_real_ip"]
    if CLIENT_IP == nil then
        CLIENT_IP = ngx.req.get_headers()["X_Forwarded_For"]
    end
    if CLIENT_IP == nil then
        CLIENT_IP  = ngx.var.remote_addr
    end
    if CLIENT_IP == nil then
        CLIENT_IP  = "unknown"
    end
    return CLIENT_IP
end

变量解释
ATTACK_URI:请求uri
CC_TOKEN:请求源ip+uri(例:192.168.0.1foo.com)
limit:lua dict
CCcount:数值(单位时间内一个CC_TOKEN允许的请求次数)
CCseconds:数值(单位时间长度, second)
逻辑简述
请求源ip:192.168.0.1,uri:foo.com/img,CCcount:100,CCseconds:60
对于CC_TOKEN(192.168.0.1foo.com/img),请求会构造并更新lua dict:

1{192.168.0.1foo.com/img, 1, 60}2{192.168.0.1foo.com/img, 2, 60}
...101{192.168.0.1foo.com/img, 101, 60}

每一次代码都会检查192.168.0.1foo.com/img对应的value,上面分别是1,2,101。如果,就会执行 ngx.exit(403)的逻辑,给客户端返回403。注意CCseconds是一个固定值,表示统计请求次数的时间窗口。
以上就是一个简单的CC attack检查&处理逻辑。

一次WAF规则引起的Bug

背景
3d-tiles服务,用户通过浏览器发起请求,应私有化环境用户需求开发并部署了WAF
问题
用户在浏览器发现大量403 response,要求我们协助排查。
原因
3D Tiles 是一种用于传输和渲染大规模三维地理空间数据的规范。在使用 3D Tiles 的网页应用中,客户端通常会发送大量请求给服务端,因为地理空间数据可能非常庞大。因此对于一个上述{foo.com/tiles, count, 60}的dict,count值很容易就超过我们预设的数值。
事实上也是这样,用户使用我们的服务在浏览器渲染3D模型时,count值迅速增加,导致客户端收到大量403请求。而这些403请求正是此WAF生成并返回给客户。
解决
对于3D Tiles服务的请求uri添加白名单,防止WAF错误拦截。

引用

我们二次开发并实施的WAF参考了:unixhot/waf: https://github.com/unixhot/waf

你可能感兴趣的:(linux,ops,安全,网络,安全,web安全)