- In Windows build, replaced usage of fcntl with cmd F_SETLKW with Win32 APIs to do file locking (LockFileEx & UnlockFileEx). - Reintroduced the reference counting initially present in the class which is necessary to correctly handle merging of rules. This allows for correctly closing the file and removing the associated entry from m_handlers when the file is no longer used. - The need for reference counting can be seen in the example simple_example_using_c, where rules are initially loaded locally and then further rules are loaded remotely. This will initially open a shared file for a log, then in order to merge rules, the shared file is opened again for the new configuration. Then, the previous configuration closes the shared file on destruction. That is, two consecutive opens are done on a shared file, which is followed by a close. If the shared file is not reference counted, the shared file will be closed while there is still a reference active. The current version works because closing of the file has been disabled after reference counting was removed. - Replaced `std::vector` data structure with `std::unordered_map` to improve lookup/update times, and simplify code. - Removed unused code - Shared memory to store msc_file_handler structure - Initially SharedFiles used shared memory to store information about each shared file, including its file pointer and a mutex to synchronize access to the file on write. See code at commit 01c13da, in particular, usage of lock & fp fields in the msc_file_handler_t structure. - At that time, msc_file_handler_t included reference counting too with the using_it field, which was incremented when a file was opened and decremented on close. If the reference count reached zero, the shared file would be closed, the lock destroyed and the file handler entry removed from m_handlers. - Reference counting was removed in commit 7f9cd76, which introduced the following issues in SharedFiles::close: - No longer closes the file pointer. - The file pointer appears to be reset when a.second = 0, but this is a local copy of the data pair obtained from m_handlers, so this is essentially a nop (updating a local variable that is not referenced later in the function). - NOTE: The file pointer was moved out of the shared memory in this commit too, and stored alongside the msc_file_handler_t instance in the m_handlers entry associated to the shared file. - The lock is no longer destroyed. - The shared memory is marked to be destroyed in the call to: shmctl(a.first->shm_id_structure, IPC_RMID, NULL); - The shared file entry is not removed from m_handlers, so: - the file pointer is still valid, which is how writing to the file continues to work, - the reference to the shared memory is also present and will be marked to be destroyed whenever close is called again on the shared file. - File locking using the mutex in msc_file_handler_t was replaced in commit 3d20304 with usage of fcntl with cmd F_SETLKW. - At this time, it appears that the shared memory is no longer used, as the file pointer and locking no longer depend on it. - MODSEC_USE_GENERAL_LOCK - This code is introduced commit 7f9cd76 and is enabled if MODSEC_USE_GENERAL_LOCK` is defined. - The define is commented out in the source code since the original commit and is not present in the build configuration either. - In commit ff9152e, in the SharedFiles constructor, the initialization of the local variable toBeCreated is removed. This means that in this version, if MODSEC_USE_GENERAL_LOCK is enabled, execution of the code that checks on toBeCreated is undefined. - Then, in commit 9b40a04, the variable toBeCreated is initialized again, but is now set to false, which means that if MODSEC_USE_GENERAL_LOCK is enabled, the shared memory and lock it uses will *not* be initialized and thus doesn't work (execution of the current version will result in trying to acquire a lock that will be null). - I conclude that the feature is not used and can be removed. - Additionally, if it were working, I think the lock should be used in SharedFiles::write as well, which is a reader of the underlying data structures protected by this lock when they're modified in SharedFiles::open & SharedFiles::close.

Libmodsecurity is one component of the ModSecurity v3 project. The library codebase serves as an interface to ModSecurity Connectors taking in web traffic and applying traditional ModSecurity processing. In general, it provides the capability to load/interpret rules written in the ModSecurity SecRules format and apply them to HTTP content provided by your application via Connectors.
If you are looking for ModSecurity for Apache (aka ModSecurity v2.x), it is still under maintenance and available: here.
What is the difference between this project and the old ModSecurity (v2.x.x)?
- All Apache dependencies have been removed
- Higher performance
- New features
- New architecture
Libmodsecurity is a complete rewrite of the ModSecurity platform. When it was first devised the ModSecurity project started as just an Apache module. Over time the project has been extended, due to popular demand, to support other platforms including (but not limited to) Nginx and IIS. In order to provide for the growing demand for additional platform support, it has became necessary to remove the Apache dependencies underlying this project, making it more platform independent.
As a result of this goal we have rearchitected Libmodsecurity such that it is no longer dependent on the Apache web server (both at compilation and during runtime). One side effect of this is that across all platforms users can expect increased performance. Additionally, we have taken this opportunity to lay the groundwork for some new features that users have been long seeking. For example we are looking to natively support auditlogs in the JSON format, along with a host of other functionality in future versions.
It is no longer just a module.
The 'ModSecurity' branch no longer contains the traditional module logic (for Nginx, Apache, and IIS) that has traditionally been packaged all together. Instead, this branch only contains the library portion (libmodsecurity) for this project. This library is consumed by what we have termed 'Connectors' these connectors will interface with your webserver and provide the library with a common format that it understands. Each of these connectors is maintained as a separate GitHub project. For instance, the Nginx connector is supplied by the ModSecurity-nginx project (https://github.com/owasp-modsecurity/ModSecurity-nginx).
Keeping these connectors separated allows each project to have different release cycles, issues and development trees. Additionally, it means that when you install ModSecurity v3 you only get exactly what you need, no extras you won't be using.
Compilation
Before starting the compilation process, make sure that you have all the dependencies in place. Read the subsection “Dependencies” for further information.
After the compilation make sure that there are no issues on your build/platform. We strongly recommend the utilization of the unit tests and regression tests. These test utilities are located under the subfolder ‘tests’.
As a dynamic library, don’t forget that libmodsecurity must be installed to a location (folder) where you OS will be looking for dynamic libraries.
Unix (Linux, MacOS, FreeBSD, …)
On unix the project uses autotools to help the compilation process.
$ ./build.sh
$ ./configure
$ make
$ sudo make install
Details on distribution specific builds can be found in our Wiki: Compilation Recipes
Windows
Windows build is not ready yet.
Dependencies
This library is written in C++ using the C++17 standards. It also uses Flex and Yacc to produce the “Sec Rules Language” parser. Other, mandatory dependencies include YAJL, as ModSecurity uses JSON for producing logs and its testing framework, libpcre (not yet mandatory) for processing regular expressions in SecRules, and libXML2 (not yet mandatory) which is used for parsing XML requests.
All others dependencies are related to operators specified within SecRules or configuration directives and may not be required for compilation. A short list of such dependencies is as follows:
- libinjection is needed for the operator @detectXSS and @detectSQL
- curl is needed for the directive SecRemoteRules.
If those libraries are missing ModSecurity will be compiled without the support for the operator @detectXSS and the configuration directive SecRemoteRules.
Library documentation
The library documentation is written within the code in Doxygen format. To generate this documentation, please use the doxygen utility with the provided configuration file, “doxygen.cfg”, located with the "doc/" subfolder. This will generate HTML formatted documentation including usage examples.
Library utilization
The library provides a C++ and C interface. Some resources are currently only available via the C++ interface, for instance, the capability to create custom logging mechanism (see the regression test to check for how those logging mechanism works). The objective is to have both APIs (C, C++) providing the same functionality, if you find an aspect of the API that is missing via a particular interface, please open an issue.
Inside the subfolder examples, there are simple examples on how to use the API. Below some are illustrated:
Simple example using C++
using ModSecurity::ModSecurity;
using ModSecurity::Rules;
using ModSecurity::Transaction;
ModSecurity *modsec;
ModSecurity::Rules *rules;
modsec = new ModSecurity();
rules = new Rules();
rules->loadFromUri(rules_file);
Transaction *modsecTransaction = new Transaction(modsec, rules);
modsecTransaction->processConnection("127.0.0.1");
if (modsecTransaction->intervention()) {
std::cout << "There is an intervention" << std::endl;
}
Simple example using C
#include "modsecurity/modsecurity.h"
#include "modsecurity/transaction.h"
char main_rule_uri[] = "basic_rules.conf";
int main (int argc, char **argv)
{
ModSecurity *modsec = NULL;
Transaction *transaction = NULL;
Rules *rules = NULL;
modsec = msc_init();
rules = msc_create_rules_set();
msc_rules_add_file(rules, main_rule_uri);
transaction = msc_new_transaction(modsec, rules);
msc_process_connection(transaction, "127.0.0.1");
msc_process_uri(transaction, "http://www.modsecurity.org/test?key1=value1&key2=value2&key3=value3&test=args&test=test");
msc_process_request_headers(transaction);
msc_process_request_body(transaction);
msc_process_response_headers(transaction);
msc_process_response_body(transaction);
return 0;
}
Contributing
You are more than welcome to contribute to this project and look forward to growing the community around this new version of ModSecurity. Areas of interest include: New functionalities, fixes, bug report, support for beginning users, or anything that you are willing to help with.
Providing patches
We prefer to have your patch within the GitHub infrastructure to facilitate our review work, and our Q.A. integration. GitHub provides excellent documentation on how to perform “Pull Requests”, more information available here: https://help.github.com/articles/using-pull-requests/
Please respect the coding style. Pull requests can include various commits, so provide one fix or one piece of functionality per commit. Please do not change anything outside the scope of your target work (e.g. coding style in a function that you have passed by). For further information about the coding style used in this project, please check: https://www.chromium.org/blink/coding-style
Provides explanative commit messages. Your first line should give the highlights of your patch, 3rd and on give a more detailed explanation/technical details about your patch. Patch explanation is valuable during the review process.
Don’t know where to start?
Within our code there are various items marked as TODO or FIXME that may need your attention. Check the list of items by performing a grep:
$ cd /path/to/modsecurity-nginx
$ egrep -Rin "TODO|FIXME" -R *
A TODO list is also available as part of the Doxygen documentation.
Testing your patch
Along with the manual testing, we strongly recommend you to use the our regression tests and unit tests. If you have implemented an operator, don’t forget to create unit tests for it. If you implement anything else, it is encouraged that you develop complimentary regression tests for it.
The regression test and unit test utilities are native and do not demand any external tool or script, although you need to fetch the test cases from other repositories, as they are shared with other versions of ModSecurity, those others repositories git submodules. To fetch the submodules repository and run the utilities, follow the commands listed below:
$ cd /path/to/your/ModSecurity
$ git submodule foreach git pull
$ cd test
$ ./regression-tests
$ ./unit-tests
Debugging
Before start the debugging process, make sure of where your bug is. The problem could be on your connector or in libmodsecurity. In order to identify where the bug is, it is recommended that you develop a regression test that mimics the scenario where the bug is happening. If the bug is reproducible with the regression-test utility, then it will be far simpler to debug and ensure that it never occurs again. On Linux it is recommended that anyone undertaking debugging utilize gdb and/or valgrind as needed.
During the configuration/compilation time, you may want to disable the compiler optimization making your “back traces” populated with readable data. Use the CFLAGS to disable the compilation optimization parameters:
$ export CFLAGS="-g -O0"
$ ./build.sh
$ ./configure
$ make
$ sudo make install
Reporting Issues
If you are facing a configuration issue or something is not working as you expected to be, please use the ModSecurity user’s mailing list. Issues on GitHub are also welcomed, but we prefer to have user ask questions on the mailing list first so that you can reach an entire community. Also don’t forget to look for existing issues before open a new one.
If you are going to open a new issue on GitHub, don’t forget to tell us the version of your libmodsecurity and the version of a specific connector if there is one.
Security issue
Please do not make public any security issue. Contact us at: modsecurity@owasp.org reporting the issue. Once the problem is fixed your credit will be given.
Feature request
We are open to discussing any new feature request with the community via the mailing lists. You can alternativly, feel free to open GitHub issues requesting new features. Before opening a new issue, please check if there is one already opened on the same topic.
Bindings
The libModSecurity design allows the integration with bindings. There is an effort to avoid breaking API [binary] compatibility to make an easy integration with possible bindings. Currently, there are two notable projects maintained by the community:
- Python - https://github.com/actions-security/pymodsecurity
- Varnish - https://github.com/xdecock/vmod-modsecurity
Packaging
Having our packages in distros on time is a desire that we have, so let us know if there is anything we can do to facilitate your work as a packager.
Sponsor Note
Development of ModSecurity is sponsored by Trustwave. Sponsorship will end July 1, 2024. Additional information can be found here https://www.trustwave.com/en-us/resources/security-resources/software-updates/end-of-sale-and-trustwave-support-for-modsecurity-web-application-firewall/