Project

General

Profile

[Solved] ModSecurity

Added by zeault about 2 months ago

I've been using lighttpd for a few months now. It's been working great as both a reverse-proxy server and a traditional webserver of static and dynamically-generated files.

On the reverse-proxy side, I am using lighttpd to protect some web services that I don't really trust to protect themselves. One of these threats I am dealing with are "injection" attacks: SQL Injection, LDAP Injection, and more attacks that haven't happened yet but are still possible in-theory.

I HATE that the internet has been around for how many decades now? and there is still no standard way to pass an "unsanitary" web request to a backend service. However that is the reality. Even for services that have been updated (e.g. SQL servers with compiled queries) sometimes we still need to keep the old software running for compatibility reasons.

None of this is lighttpd's problem, but as a reverse-proxy, I think it is in a good position to help. I was thinking: what if there was a simple "mod_sanitize" that could just comb through the http headers and/or query strings to detect a set of "illegal" characters, strings, or bytes.

I imagine it would have a configuration syntax similar to mod_auth:

$HTTP["url"] =~ "^/my/insecure/form" {

     sanitize.query_string = ( "searchTerm" => (  "IllegalCharacters" => "{}()/\",
                                                  "action" => "audit",),
                          "otherSearchTerm" => (  "IllegalString" => "DROP TABLE",
                                                  "action" => "drop",) )

     sanitize.header = ( "dontTrustMe" => (  "IllegalBytes" => "1F,1E,11",
                                                   "action" => "audit",),
                   "dontTrustMeEither" => (  "IllegalSequence" => "FF90ADC1",
                                                   "action" => "audit,drop",) )
}

You could specify primitive input sanitation for a particular query string or header. Each "sanitize" config entry could have a list of tuples. Each tuple could contain a rule that determines when an input is illegal and an action to take when an illegal input is found. The "drop" action would just drop the whole request. The "audit" action would allow the request but write a message to the log. Audit and drop could be used together to drop the request AND write a message to the log.

Even for services that are not really vulnerable to injection-type attacks I think this could be useful if used with the "audit" action, because a separate daemon like fail2ban could monitor the logs and block potential abusers who are probing your system.

I haven't developed in a long time, but I took a peek at the lighttpd source code today and thought I could probably implement this module myself. It'll take a while though; I don't do this for a living. That's why I wanted to bring this idea up here first, so I can gather some comments and suggestions to see if other people are interested in it too.

Please share your thoughts and thank you.


Replies (4)

RE: ModSecurity - Added by gstrauss about 2 months ago

and there is still no standard way to pass an "unsanitary" web request to a backend service.

Incorrect. Among other mechanisms, there are SQL placeholders (?).

mod_sanitize

Please share your thoughts and thank you.

You are by far not the first person to "invent" a web application firewall (WAF). Please ask questions instead of making suggestions since you do not seem not well-versed in this area.

WAFs can be useful, and WAFs take effort to configure them to be able to best protect your application. There are commercial products for this. There are some open source attempts, too, such as ModSecurity. Effort should also be placed on improving your application, such as by writing SQL queries using placeholders (?)in the queries to pass untrusted data to the database.

You are posting to the lighttpd development forum, so you ought to have at least read some documentation on this website before posting.

lighttpd mod_magnet allows you to write lua scripts to perform arbitrary web request manipulation.

There are plenty of other examples on AbsoLUAtion including lua Fight DDoS sample and lua mod_evasive

There is a documented example for using the open source "mod_security" at lua mod_security
ModSecurity is available as a library package called "libmodsecurity" in some Linux distributions.

A couple years ago, I took a look at ModSecurity code and have a development branch in git for lighttpd mod_security3 to use ModSecurity.
https://github.com/gstrauss/lighttpd1.4/tree/mod_security3
I posted briefly about it here: https://serverfault.com/questions/919387/how-to-use-modsecurity-with-lighttpd
I occasionally rebase this branch onto lighttpd git master. The tip of the mod_security3 development branch says:

[mod_security3] new module using libmodsecurity

(experimental)

Note: libmodsecurity has a humongous list of dependencies

libmodsecurity is not near the performance level of lighttpd,
but that is also not the goal of libmodsecurity.  Using mod_security3
will result in higher memory use, higher CPU use, and slower responses
compared to using lighttpd without mod_security3.

mod_sanitize

I am going to rename this post title from mod_sanitize to ModSecurity.

RE: ModSecurity - Added by zeault about 2 months ago

You are by far not the first person to "invent" a web application firewall (WAF).

I'm not trying to invent the web application firewall. In fact if you look at the example I offered, I tried to keep it as simple as possible. No regex's, no parsing, just "does this string contain this byte?". I am not interested in the whole bag of a web application firewall. Like you said ModSecurity is a large and heavyweight solution unlike lighttpd. All I want to do is make sure the '{' character doesn't get accidentally passed through to my 20 year old DBMS.

Effort should also be placed on improving your application, such as by writing SQL queries using placeholders (?)in the queries to pass untrusted data to the database.

Yes that is a great suggestion. I would absolutely improve it if it were my application. Like I said in my original post "this is not lighttpd's problem". It is the application's problem. Unfortunately in the real world we do not always write every piece of code that we use, and like I said in my original post sometimes we have to keep legacy systems online for compatibility reasons.

Please ask questions instead of making suggestions since you do not seem not well-versed in this area. Outside of FAANG, the world is running on garbage legacy software. I hate it, but that is the situation we are in (at least in the USA). Banks, governments, factories, power plants.... lots of crusty old databases.

lighttpd mod_magnet allows you to write lua scripts to perform arbitrary web request manipulation.

Yes I am aware of mod_magnet. Of course I could use scripting to accomplish this. If mod_magnet exists, then why does lighttpd have modules at all? That was a rhetorical question.

Like I said in my original post, I am aware that SQL placeholders exist. I called them SQL compiled queries. I believe that is the Microsoft parlance. Same thing.

Like I said in my original post, SQL compiled queries/placeholders do not do any good for LDAP or other legacy/proprietary/crusty/crappy types of databases and protocols. i.e. there is no standard protocol. I can forgive the first person who naively wrote the code back in 1978 that originally contained the SQL injection bug, but it should have been completely eliminated by the 2000's. Unfortunately it still exists in software written today. I would get rid of it if I could, but like I said I am not the one writing that software.

I still might clone the repo and implement this in C if I have time, but don't worry, I won't upload it since you think it is such a bad idea.

Good day.

RE: ModSecurity - Added by gstrauss about 2 months ago

I still might clone the repo and implement this in C if I have time, but don't worry, I won't upload it since you think it is such a bad idea.

I did not say it was a bad idea. I said that you do not seem well-versed in this area.

The evidence for that is that you seemed unaware of ModSecurity or the effort that goes into maintaining the OWASP CRS (core rule set) https://github.com/coreruleset/coreruleset

Further evidence of your inflated ego is that you have ignored the links I provided with multiple solutions and think that you can write something better, even though it is not your day job.

Yes I am aware of mod_magnet. Of course I could use scripting to accomplish this. If mod_magnet exists, then why does lighttpd have modules at all? That was a rhetorical question.

Yeah, the answer to your rhetorical question is also well-documented.
ModMagnetExamples states: "mod_magnet with lua scripts can allow for customized alternatives to many lighttpd modules."

lighttpd mod_magnet running lua scripts is fast and performant, and is where you should write your custom script to check for '{' since you want your false sense of security that you did something to "protect" your backends. Well, doing that is better than nothing, but as a security professional, I can tell you it is not much. If your company has something worthwhile to protect, then a determined attacker is going to do better than '{'. So pat yourself on the back that you have filtered '{' and stopped some script kiddies.

I still might clone the repo and implement this in C if I have time, but don't worry, I won't upload it since you think it is such a bad idea.

Your inflated ego about your complete vaporware should be embarrasing to you. I do not write everything from scratch. My ModSecurity connector lighttpd mod_security3 did not reinvent everything from scratch. I leveraged the existing ModSecurity library and ruleset.

lighttpd mod_magnet running lua scripts is fast and performant. Some benchmarks of mod_magnet compared to mod_access are in #3199. In those benchmarks, yes, mod_access is faster when compared to mod_magnet and a custom lua script, but both are much faster (multiple times over) than typical backend scripts.

If you have NIH syndrome (not invented here) and have not tried the simple, already available mod_magnet working solution with examples provided, and benchmarked it, then I am not interested in any code that you might write. The behaviors you have exhibited are highly correlated with inferior design and code.

RE: ModSecurity - Added by gstrauss about 2 months ago

lighttpd mod_magnet allows you to write lua scripts to perform arbitrary web request manipulation.

Yes I am aware of mod_magnet.

You made no mention of that in your original post.

Of course I could use scripting to accomplish this.

And why didn't you do that?

The "conversation" as it were has reached the point of: mod_magnet is very likely the best available solution for, in your words: 'just "does this string contain this byte?"', unless you can demonstrate -- using concrete, observational data -- the actual, real-world limitations of a mod_magnet solution in your environment. lighttpd.conf regexes would be fine for a very small/short set of strings for which to deny access, but implementing tables and audit logging policies is better done in a lua script run with mod_magnet

    (1-4/4)