Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement libModsecurity as WASM extension for envoy #17463

Closed
M4tteoP opened this issue Jul 23, 2021 · 10 comments
Closed

Implement libModsecurity as WASM extension for envoy #17463

M4tteoP opened this issue Jul 23, 2021 · 10 comments
Labels
area/wasm question Questions that are neither investigations, bugs, nor enhancements stale stalebot believes this issue/PR has not been touched recently

Comments

@M4tteoP
Copy link

M4tteoP commented Jul 23, 2021

I'm working on porting the library libModsecurity to WASM architecture to use it as a envoy extension for istio. The idea behind this project is to experiment with a granular and easily configurable security control (a WAF) that can be put in front of any needed pod.
Emconfigure and emmake tools from Emscripten seems very promising to accomplish this task, however, I'm stuck on header inclusion errors.
Action performed are just:
./build.sh
emconfigure ./configure
emmake make
Resulting in this error:

/bin/bash ../libtool  --tag=CXX   --mode=compile /home/user/Tesi/extensions/manualBuild/emsdk/upstream/emscripten/em++ -DHAVE_CONFIG_H -I.  -std=c++11 -I.. -g -I../others -fPIC -O3 -I../headers -DWITH_CURL_SSLVERSION_TLSv1_2 -DWITH_CURL -DWITH_GEOIP -I/usr/include          -I/usr/include/libxml2 -DWITH_LIBXML2   -g -O2 -MT parser/libmodsecurity_la-seclang-parser.lo -MD -MP -MF parser/.deps/libmodsecurity_la-seclang-parser.Tpo -c -o parser/libmodsecurity_la-seclang-parser.lo `test -f 'parser/seclang-parser.cc' || echo './'`parser/seclang-parser.cc
libtool: compile:  /home/user/Tesi/extensions/manualBuild/emsdk/upstream/emscripten/em++ -DHAVE_CONFIG_H -I. -std=c++11 -I.. -g -I../others -fPIC -O3 -I../headers -DWITH_CURL_SSLVERSION_TLSv1_2 -DWITH_CURL -DWITH_GEOIP -I/usr/include -I/usr/include/libxml2 -DWITH_LIBXML2 -g -O2 -MT parser/libmodsecurity_la-seclang-parser.lo -MD -MP -MF parser/.deps/libmodsecurity_la-seclang-parser.Tpo -c parser/seclang-parser.cc  -fPIC -DPIC -o parser/.libs/libmodsecurity_la-seclang-parser.o
In file included from parser/seclang-parser.cc:41:
In file included from seclang-parser.yy:11:
In file included from /home/user/Tesi/extensions/manualBuild/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/string:511:
In file included from /home/user/Tesi/extensions/manualBuild/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/string_view:179:
In file included from /home/user/Tesi/extensions/manualBuild/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__string:57:
In file included from /home/user/Tesi/extensions/manualBuild/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/algorithm:651:
In file included from /home/user/Tesi/extensions/manualBuild/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/cstring:60:
/usr/include/string.h:26:10: fatal error: 'bits/libc-header-start.h' file not found
#include <bits/libc-header-start.h>
         ^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
em++: error: '/home/user/Tesi/extensions/manualBuild/emsdk/upstream/bin/clang++ -target wasm32-unknown-emscripten -DEMSCRIPTEN -fignore-exceptions -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -D__EMSCRIPTEN_major__=2 -D__EMSCRIPTEN_minor__=0 -D__EMSCRIPTEN_tiny__=25 -D_LIBCPP_ABI_VERSION=2 -Dunix -D__unix -D__unix__ -Werror=implicit-function-declaration -Xclang -iwithsysroot/include/SDL --sysroot=/home/user/Tesi/extensions/manualBuild/emsdk/upstream/emscripten/cache/sysroot -Xclang -iwithsysroot/include/compat -DHAVE_CONFIG_H -I. -std=c++11 -I.. -g -I../others -fPIC -O3 -I../headers -DWITH_CURL_SSLVERSION_TLSv1_2 -DWITH_CURL -DWITH_GEOIP -I/usr/include -I/usr/include/libxml2 -DWITH_LIBXML2 -g -O2 -MT parser/libmodsecurity_la-seclang-parser.lo -MD -MP -MF parser/.deps/libmodsecurity_la-seclang-parser.Tpo -c -fPIC -DPIC parser/seclang-parser.cc -o parser/.libs/libmodsecurity_la-seclang-parser.o' failed (returned 1)
make[3]: *** [Makefile:2072: parser/libmodsecurity_la-seclang-parser.lo] Error 1
make[3]: Leaving directory '/home/user/Tesi/extensions/manualBuild/ModSecurity/src'
make[2]: *** [Makefile:3479: all-recursive] Error 1
make[2]: Leaving directory '/home/user/Tesi/extensions/manualBuild/ModSecurity/src'
make[1]: *** [Makefile:1224: all] Error 2
make[1]: Leaving directory '/home/user/Tesi/extensions/manualBuild/ModSecurity/src'
make: *** [Makefile:1035: all-recursive] Error 1
emmake: error: 'make' failed (returned 2)

Based on this and this issues, I'm aware that:

  1. The first problem is about header file inclusions, Emscripten wants its own inclusions, so -I/usr/include -I/usr/include/libxml2 should be removed from the command. But I do not understand deep enough all the build process to figure out the correct fix that I have to make.
  2. As far as I understood, the whole wasm extension works inside an isolated Wasm VM, so all the dependencies that the program may have must be embedded inside the WASM itself. Am I wrong about it? If I am not, it means that the whole Modsecurity and its dependencies must be statically build for wasm and provided inside the final wasm file. How can the compiler satisfy all the dependencies without having to manually compile each library? Or am I missing something about provide libraries to the Wasm VM?

I provide some details about my environment:
OS: Ubuntu 20.04.2
emsdk: 2.0.25
ModSecurity: v3.0.5-2-g465db29b

I also post the result of emconfigure ./configure to show all the dependencies installed:

ModSecurity - v3.0.5-2-g465db29b for Linux

 Mandatory dependencies
   + libInjection                                  ....v3.0.5-2-g465db29b
   + SecLang tests                                 ....465db29b

 Optional dependencies
   + GeoIP/MaxMind                                 ....found
      * (GeoIP) v
         /usr/lib/x86_64-linux-gnu//libGeoIP.so, /usr/include
   + LibCURL                                       ....found v7.68.0
      -lcurl,  -DWITH_CURL_SSLVERSION_TLSv1_2 -DWITH_CURL
   + YAJL                                          ....not found
   + LMDB                                          ....not found
   + LibXML2                                       ....found v2.9.10
      -lxml2, -I/usr/include/libxml2 -DWITH_LIBXML2
   + SSDEEP                                        ....not found
   + LUA                                           ....not found

 Other Options
   + Test Utilities                                ....disabled
   + SecDebugLog                                   ....enabled
   + afl fuzzer                                    ....disabled
   + library examples                              ....enabled
   + Building parser                               ....disabled
   + Treating pm operations as critical section    ....disabled

Thanks for any support!

@M4tteoP M4tteoP added the triage Issue requires triage label Jul 23, 2021
@htuch htuch added area/wasm question Questions that are neither investigations, bugs, nor enhancements and removed triage Issue requires triage labels Jul 23, 2021
@htuch
Copy link
Member

htuch commented Jul 23, 2021

@PiotrSikora
Copy link
Contributor

@M4tteoP exciting!

As you correctly noted, all the dependencies must be build for the Wasm architecture and linked into the final Wasm module (same as linking static executables on any other platform) in order for ModSecurity to work.

See: https://emscripten.org/docs/compiling/Building-Projects.html#using-libraries

Because of that, I recommend starting from the minimal ModSecurity build, which depends only on the PCRE:

emconfigure ./configure --without-geoip --without-maxmind --without-curl --without-libxml --without-lmdb --without-lua --without-ssdeep --without-yajl --disable-examples

and once you have it working (you need to build PCRE), keep adding one dependency at a time.

Basically, you need to add support for static linking in ModSecurity, and then Emscripten would take care of Wasm.

@leyao-daily
Copy link
Member

And I successfully build the modsecurity wasm library with removing some unsupport system call based on the minimal ModSecurity (only PCRE)
Maybe you can take a look at
https://github.com/leyao-daily/ModSecurity/blob/v3/master/modsecurity2wasm.md

You need a WASM PCRE and ModSecurity library when you build your own wasm filter in envoy bazel toolchain.

@mathetake
Copy link
Member

@leyao-daily Cool good job. I imagine ModSecurity by default uses C++ exceptions so maybe we have to patch it so it does not expect Envoy to handle emscripten exceptions (See proxy-wasm/proxy-wasm-cpp-host#116).

Could you share the list of the system calls which must be supported in Envoy (or even wasi-libc)?

@leyao-daily
Copy link
Member

@mathetake Yes. The system calls I meet until now are list:
some ipc calls needed in ModSecurity:

_ftok 
_popen
_shmat
_shmctl
_shmdt
_shmget
_wordexp
_wordfree

And calls may request support:

_fchmod
chmod
unlink
mkdir
uname
wait4
getaddrinfp
cxa_rethrow

@leyao-daily
Copy link
Member

Most of them are needed when ModSecurity process with the file system.

@nullpo-head
Copy link

Your project sounds exiting! Actually, I've done a similar thing and I'd like to point out that proxy-wasm/proxy-wasm-cpp-host#143 has to be resolved in order to make a reliable ModSecurity WAF with proxy-wasm. @PiotrSikora Most security rules, including OWASP core rule set, need to inspect the request body to decide whether to accept or reject the request header. Thus, it needs the ability to pause the request header until it handles the request body.

@M4tteoP
Copy link
Author

M4tteoP commented Jul 28, 2021

@leyao-daily @PiotrSikora, thank you all for your interest in the project and for all the provided valuable information!

I succeeded in compiling both PCRE and the minimal ModSecurity.
I'm now trying to create a scaffold project in which these libraries are included. The Bazel toolchain and the relative building phase went well, but the problem that I am facing now is that there are still some missing dependencies (_ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE17__assign_externalEPKc) that arise only at runtime and I'm not even able to figure out from which library they are.
The error log is:

2021-07-28T13:45:41.025406Z     error   envoy wasm      Failed to load Wasm module due to a missing import: env._ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE17__assign_externalEPKc
2021-07-28T13:45:41.025414Z     error   envoy wasm      Wasm VM failed Failed to initialize Wasm code
2021-07-28T13:45:41.026504Z     critical        envoy wasm      Plugin configured to fail closed failed to load
2021-07-28T13:45:41.026517Z     critical        envoy wasm      Plugin configured to fail closed failed to load
2021-07-28T13:45:41.026534Z     critical        envoy wasm      Plugin configured to fail closed failed to load
2021-07-28T13:45:41.026609Z     warning envoy config    gRPC config for type.googleapis.com/envoy.config.core.v3.TypedExtensionConfig rejected: Unable to create Wasm HTTP filter

The minimal version of the extension just includes few Modsec header files

#include "modsec/include/modsecurity/rule_message.h"
#include "modsec/include/modsecurity/modsecurity.h"
#include "modsec/include/modsecurity/rules_set.h"

and creates a modsecurity::ModSecurity object.

  modsecurity::ModSecurity *modsec;
  modsec = new modsecurity::ModSecurity();

Thanks again for the support, even just a .cc example file would be awesome.

@leyao-daily
Copy link
Member

leyao-daily commented Jul 30, 2021

Hi, what is your emscripten toolchain version? You should use 2.0.7 which is used in envoy. @M4tteoP

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in the next 7 days unless it is tagged "help wanted" or "no stalebot" or other activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale stalebot believes this issue/PR has not been touched recently label Aug 29, 2021
@M4tteoP M4tteoP closed this as completed Aug 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/wasm question Questions that are neither investigations, bugs, nor enhancements stale stalebot believes this issue/PR has not been touched recently
Projects
None yet
Development

No branches or pull requests

6 participants