安装使用 lua-resty-waf

系统:CentOS 8.0 域名:https://freewisdom.cn

安装 OpenResty

安装依赖

dnf install pcre-devel openssl-devel gcc gcc-c++ curl

参考官网文档先添加 OpenResty 仓库

wget https://openresty.org/package/centos/openresty.repo
mv openresty.repo /etc/yum.repos.d/

更新软件仓库

dnf update

安装 openresty, openresty-resty, openresty-opm

dnf install openresty openresty-resty openresty-opm

将 Nginx 迁移到 OpenResty

停止 nginx 服务

nginx -s stop

找到 nginx 和 openresty 的配置目录

find / -name nginx.conf -type f

# /etc/nginx/nginx.conf
# /usr/local/openresty/nginx/conf/nginx.conf

nginx 的配置目录为 /etc/nginx//etc/nginx/conf.d/ openresty 对应的 nginx 配置目录为 /usr/local/openresty/nginx/conf/

复制配置

cp /etc/nginx/conf.d/* /usr/local/openresty/nginx/conf/

然后对照 /etc/nginx/nginx.conf 修改 /usr/local/openresty/nginx/conf/nginx.conf 需要使用 include 将原 etc/nginx/conf.d 下的文件包含进来

使用 openresty -t 命令测试配置是否正确,使用 openresty 命令开启 openresty

安装 lua-resty-waf

克隆代码

git clone https://github.com/p0pr0ck5/lua-resty-waf.git
git submodule init
git submodule update

直接 make 找不到 ~lua.h~,安装 lua-devel

dnf install lua luarocks
dnf install http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/lua-devel-5.3.4-11.el8.x86_64.rpm

修改 lua 版本,这样会导致后面 rexpcre.so 启动不起来,还是需要强制安装 lua 5.1 修改 lua-aho-corasick/Makefile 以及 lua-resty-htmlentities/Makefile

sed -i 's/LUA_VERSION = 5.1/LUA_VERSION = 5.3/' \
lua-aho-corasick/Makefile \
lua-resty-htmlentities/Makefile

Centos 8 强制安装 lua-5.1, lua-devel-5.1, luarocks

wget http://mirror.centos.org/centos/7/os/x86_64/Packages/lua-5.1.4-15.el7.x86_64.rpm
rpm -i ./lua-5.1.4-15.el7.x86_64.rpm --nodeps
dnf install http://mirror.centos.org/centos/7/os/x86_64/Packages/lua-devel-5.1.4-15.el7.x86_64.rpm
dnf install https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/l/luarocks-2.3.0-1.el7.x86_64.rpm

要使得 lua 5.1 正常运行,需要链接一些资源文件

# find / -name libreadline.so
cd /usr/lib64
ln -s libreadline.so.7.0 libreadline.so.6
ln -s libncurses.so.6.1 libncurses.so.5
ln -s libtinfo.so.6.1 libtinfo.so.5

测试 lua 能否正常运行

lua -v
# Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
lua
# Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
# >

Centos 8 默认没有 python 命令,可修改 .py 文件的 pythonpython2

set -i 's/#!\/usr\/bin\/env python/#!\/usr\/bin\/env python2/' \
libinjection/src/fingerprints2sqli.py \
libinjection/src/make_parens.py \
libinjection/src/sqlparse2c.py \
libinjection/src/sqlparse_map.py

make 以及 make install

编译完成后重启 openresty

# openresty -s reload
openresty -s stop
openresty

测试 lua-resty-waf

测试网址:

https://freewisdom.cn/
https://xampp.freewisdom.cn/

访问 https://freewisdom.cn/?id=<script>alert(123)</script>, https://freewisdom.cn/?id=1'or'1=1 均返回 403,服务器日志如下:

{
  "timestamp": 1614936394,
  "client": "107.150.120.83",
  "method": "GET",
  "uri": "/",
  "id": "e62f6b10a7f0a593de01",
  "alerts": [
    {
      "msg": "SQL Tautologies",
      "id": 41005,
      "match": 2
    },
    {
      "msg": "SQL Injection character anomaly - ARGS",
      "id": 41015,
      "match": 1
    },
    {
      "msg": "XSS (Cross-Site Scripting)",
      "id": 42043,
      "match": 9
    },
    {
      "msg": "XSS (Cross-Site Scripting)",
      "id": 42059,
      "match": 1
    },
    {
      "msg": "XSS (Cross-Site Scripting) - HTML Tag Handler",
      "id": 42069,
      "match": 1
    },
    {
      "msg": "XSS (Cross-Site Scripting) - JS Fragments",
      "id": 42076,
      "match": 9
    },
    {
      "msg": "XSS (Cross-Site Scripting) - IE Filter",
      "id": 42083,
      "match": 1
    },
    {
      "msg": "Request score greater than score threshold",
      "logdata": 28,
      "id": 99001,
      "match": 28
    }
  ],
  "uri_args": {
    "id": "<script>alert(123)</script>"
  }
}

附录

nginx.conf

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;
    #tcp_nodelay    on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    # Avoid Attack
    server_tokens off;

      # WAF
    init_by_lua_block {
        -- use resty.core for performance improvement, see the status note above
        require "resty.core"

        -- require the base module
        local lua_resty_waf = require "resty.waf"

        -- perform some preloading and optimization
        lua_resty_waf.init()
    }

    gzip on;

    include allHTTPS.conf;
    # WAF
    include xampp.conf;
    include www.conf;

    server {
        listen       80 default_server;
        server_name  _;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        rewrite      ^(.*) https://freewisdom.cn;

        location / {
            #root   html;
            #index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
}

www.conf

    server {
        listen       443;
        server_name  freewisdom.cn;
        root         /var/web/public;
        index        index.html index.htm;
        #error_log logs/www.error.log;

        location / {
            #expires 7d;
            access_by_lua_block {
                local lua_resty_waf = require "resty.waf"

                local waf = lua_resty_waf:new()

                -- define options that will be inherited across all scopes
                waf:set_option("debug", true)
                waf:set_option("mode", "ACTIVE")

                waf:set_option("event_log_target", "file")
                waf:set_option("event_log_target_path", "/tmp/event.log")

                waf:set_option("debug_log_level", ngx.DEBUG)
                waf:set_option("event_log_altered_only", false)
                waf:set_option("event_log_request_arguments", true)
                waf:set_option("event_log_request_body", true)
                waf:set_option("event_log_verbosity", 4)

                waf:set_option("event_log_periodic_flush", 30)
                waf:set_option("event_log_buffer_size", 128)

                -- this may be desirable for low-traffic or testing sites
                -- by default, event logs are not written until the buffer is full
                -- for testing, flush the log buffer every 5 seconds
                --
                -- this is only necessary when configuring a remote TCP/UDP
                -- socket server for event logs. otherwise, this is ignored
                -- waf:set_option("event_log_periodic_flush", 5)

                -- run the firewall
                waf:exec()
            }

            header_filter_by_lua_block {
                local lua_resty_waf = require "resty.waf"

                -- note that options set in previous handlers (in the same scope)
                -- do not need to be set again
                local waf = lua_resty_waf:new()

                waf:exec()
            }

            body_filter_by_lua_block {
                local lua_resty_waf = require "resty.waf"

                local waf = lua_resty_waf:new()

                waf:exec()
            }

            log_by_lua_block {
                local lua_resty_waf = require "resty.waf"

                local waf = lua_resty_waf:new()

                -- waf:exec()
                waf:write_log_events()
            }
        }

        location ~ .*\.(php?|cgi|pl|py)$ {
            deny all;
        }

        location ~ /\.ht {
            deny all;
        }

        location ~ /.+\.(inc|conf|cnf) {
            deny all;
        }

        #fastcgi_intercept_errors on;

        error_page 404 /404.html;
            location = /404.html {
            root /var/web/public;
        }
    }
湘ICP备19014083号-1