owasp-modsecurity / ModSecurity-nginx

ModSecurity v3 Nginx Connector
Apache License 2.0
1.56k stars 281 forks source link

[Feature request] Expose Modsecurity variables to ngx/LUA #234

Open cbornet opened 3 years ago

cbornet commented 3 years ago

It would be nice to have the variables of Modsecurity exposed to ngx/LUA (ngx.var). So we can do some treatment on the transaction (eg. increment a Prometheus counter, set headers, ...) Something like having the variables $modsecurity_tx, $modsecurity_env, $modsecurity_geo available. Also having the possibility to get all the rules that matched and their metadata (I'm not sure in which var they are stored). Do you think that's feasible ?

zimmerle commented 3 years ago

That sounds like a great idea.

We already exchange variables within Lua - https://github.com/SpiderLabs/ModSecurity/blob/f18595f42830f2f0ac27362a8b31120e3dfb850c/src/engine/lua.cc#L258-L281

We also exchange transformations - https://github.com/SpiderLabs/ModSecurity/blob/f18595f42830f2f0ac27362a8b31120e3dfb850c/src/engine/lua.cc#L412-L478

Alternatively, libModSecurity could be ported to Lua (bindings) and all the inspection could be held on a Lua script.

fl0ppy-d1sk commented 3 years ago

Hello @zimmerle, any news on that feature ?

pr4u4t commented 2 years ago

Hi, @zimmerle, @fl0ppy-d1sk, @cbornet. I've been investigating this topic for a while.

  1. Nginx variables are defined 'statically', every variable must be defined by filling ngx_http_variable_t and then calling ngx_http_add_variable. Handler to add variables must be placed in ngx_http_module_t ngx_http_modsecurity_ctx in preconfiguration. So using modsecurity variables in ngx configuration is highly ineffective.
  2. Situation looks better with Lua, libModsecurity must be patched with: pull style API and following code must be added to _ngx_http_modsecuritymodule.c of ModSecurity-nginx
const char *ngx_modsecurity_lua_ffi_transaction_variable(ngx_http_request_t *r,const char *v){
    ngx_http_modsecurity_ctx_t *ctx = NULL;
    Transaction *t = NULL;

    ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
    if (ctx == NULL){
        dd("no ctx found");
        return NULL;
    }

    t = ctx->modsec_transaction;

    if (t == NULL){
        dd("no transaction found")
        return NULL;
    }

    return msc_get_transaction_variable(t,v);
}

Having this, variable value can be obtained from Lua code using FFI function call:

local base = require "resty.core.base"
local get_request = base.get_request
local ffi = require "ffi"
local C = ffi.C
local msc = {}

ffi.cdef[[
        typedef void ngx_http_request_t;
        const char *ngx_modsecurity_lua_ffi_transaction_variable(ngx_http_request_t *r, const char *var_name);
]]

msc.transaction_variable  = C.ngx_modsecurity_lua_ffi_transaction_variable

local anoscore = msc.transaction_variable(get_request(),'tx:anomaly_score') 

I could provide patch and pull request for existing ModSecurity-nginx connector with Lua code to obtain variable in such way.

  1. libModSecurity functions can be called from Lua, I'm finishing a binding that could be used with nginx/openresty to perform security evaluation. Which can be viewed pr4u4t/ModSecurity-Lua