Skip to content
Browse files

Implement all handlers

New handlers:
* logging passthru handler
* redirection
* rejection
* honeypot backend
* define your own handler
* synthetic html

Cleanup:
* put module config in config.vcl
* put handlers in handlers.vcl
* put breach into breach.vcl
* redefine default handler from sec_sev1 to sec_handler
* added X-SEC-Client client info
* added X-SEC-Response synthetic response
  • Loading branch information...
1 parent 515d41e commit f539bbd7fe7776f3685e4e6d4e76464e45b02636 @comotion committed Dec 4, 2010
View
37 README
@@ -1,7 +1,7 @@
Security.VCL
-This is work in progress. This was (as is too common) developed internally
-and thrown into a public repository. Use at your own discretion.
+This is work in progress just like any security app should be.
+Use at your own discretion.
=================================
1. About Security.VCL
@@ -33,16 +33,16 @@ To use Security.VCL, you currently have to:
$ cd vcl/
$ make
$ cd ..
-$ cp -a vcl/ /etc/varnish/security.vcl/
- (alternatively you could symlink it, of course).
+$ ln -s $PWD/vcl/ /etc/varnish/security.vcl/
-Then you edit your normal VCL and add this line near the top:
+then you edit your default.vcl and add this line near the top:
include "/etc/varnish/security.vcl/main.vcl";
At this point, you should only need to reload your varnish configuration.
-You may have to or want to modify main.vcl to fit your needs. At the
-moment, paths are hardcoded.
+
+You may have to or want to modify config.vcl to fit your needs.
+Remember that paths must be hardcoded and absolute.
3. The Architecture
===================
@@ -51,20 +51,31 @@ Security.VCL currently have two categories of rules: rules generated from
mod_security, located in vcl/breach/ and our own rules, vcl/modules/.
Security.VCL works by including all modules, then defining a number of
-standard functions. Each module will call sec_sevN, where N is the
-severity, which in turn typically calls error or some other handler.
+standard functions. Each module will set X-SEC-Severity = "N", where N is the
+severity, and call sec_handler which in turn typically calls error or some other handler.
4. Handlers
===========
-Handlers are still not well developed, but the general concept is that
-Security.VCL either throws an error (vcl_error) of some kind, which can
-potentially redirect the client or do any other synthetic response, or
-Security.VCL can rewrite the original request and send it to a backend
+The general concept is that security.VCL either throws an error
+(vcl_error) of some kind, which can return a redirect the client,
+or do any other synthetic response, or Security.VCL can log,
+rewrite the original request and send it to a backend
designed to do more clever things, like:
- Block the client in a firewall
- Log the event
- Test-run the code.
- Paint you a pretty picture....
- ....
+
+There are several handlers defined and you can set the default handler in handlers.vcl.
+The default handler rejects detected malicious traffic.
+
+Also you may write your own handler, see handlers.vcl
+
+5. Known Issues
+===============
+
+Let us know! http://github.com/comotion/security.vcl/issues
+
View
4 vcl/VARIABLES
@@ -25,3 +25,7 @@ X-SEC-RuleId
X-SEC-Rule
X-SEC-RuleName
X-SEC-RuleInfo
+# the evil.. gather info about him here
+X-SEC-Client
+# custom client response, in html
+X-SEC-Response
View
14 vcl/breach.vcl
@@ -0,0 +1,14 @@
+/* Security.vcl breach2vcl config VCL
+ * Copyright (C) 2009 Kacper Wysocki
+ *
+ * the rules enabled here are auto-generated by ../tools/all2vcl.pl
+ */
+
+include "/etc/varnish/security/breach/20_protocol_violations.vcl";
+include "/etc/varnish/security/breach/21_protocol_anomalies.vcl";
+include "/etc/varnish/security/breach/23_request_limits.vcl";
+include "/etc/varnish/security/breach/30_http_policy.vcl";
+include "/etc/varnish/security/breach/35_bad_robots.vcl";
+include "/etc/varnish/security/breach/40_generic_attacks.vcl";
+include "/etc/varnish/security/breach/45_trojans.vcl";
+include "/etc/varnish/security/breach/50_outbound.vcl";
View
30 vcl/config.vcl
@@ -0,0 +1,30 @@
+/* Security.vcl config VCL file
+ * Copyright (C) 2009 Redpill Linpro AS
+ * Copyright (C) 2009 Kristian Lyngstøl
+ * Copyright (C) 2009 Kacper Wysocki
+ * Copyright (C) 2009 Edward Bjarte Fjellskål
+ *
+ * In this file you specify which rulesets to configure,
+ * what to log and which handlers to employ.
+ *
+ */
+
+# Comment out any include line to disable the security module.
+include "/etc/varnish/security/modules/demo.vcl";
+include "/etc/varnish/security/modules/php.vcl";
+include "/etc/varnish/security/modules/sql.vcl";
+include "/etc/varnish/security/modules/xss.vcl";
+include "/etc/varnish/security/modules/cmd.vcl";
+include "/etc/varnish/security/modules/restricted-file-extensions.vcl";
+include "/etc/varnish/security/modules/content-encoding.vcl";
+include "/etc/varnish/security/modules/content-type.vcl";
+include "/etc/varnish/security/modules/localfiles.vcl";
+include "/etc/varnish/security/modules/request.vcl";
+
+## User agent checks may be a little too restrictive for your tastes.
+#include "/etc/varnish/security/modules/user-agent.vcl";
+
+## The breach2vcl tool is not perfect...
+# include "/etc/varnish/security/breach.vcl";
+
+
View
98 vcl/handlers.vcl
@@ -0,0 +1,98 @@
+/* Security.vcl hanlders VCL file
+ * Copyright (C) 2009 Kacper Wysocki
+ *
+ * **************** handlers **************** *
+ * The rest of the code assumes this file defines the
+ * following:
+ * sec_honey - the honeyput backend
+ * sec_log - logging function
+ * sec_handler - this function handles all triggered rules
+ *
+ * If you do not intend on changing these there is no need to read on.
+ */
+
+sub sec_default_handler {
+ # swap this one with your handler (see below)
+ call sec_reject;
+}
+
+/* the honeypot backend...
+ * presently defined to give no service
+ * possible uses:
+ * send to less critical server
+ * log evil traffic
+ * sandbox request
+ * execute CGI scripts based on traffic
+ * ... ie to firewall client
+ * ... other active responses?
+ */
+backend sec_honey {
+ .host = "127.0.1.2";
+ .port = "3";
+}
+
+# Here you can specify what gets logged when a rule triggers.
+sub sec_log {
+ log "security.vcl "
+ "Rule:" req.http.X-SEC-Module "-" req.http.X-SEC-RuleId
+ " xid:" req.xid " " req.http.X-SEC-Client ;
+}
+
+
+/* You can define how to handle the different severity levels. */
+sub sec_handler {
+ ## magichandler handles restarts should always be called!
+ call sec_magichandler;
+
+ if(req.http.X-SEC-Severity == "1"){
+ /* we have only one severity for now: this is the default rule */
+ call sec_default_handler;
+ }else{
+ # fallback attack response when severity is off the charts
+ call sec_default_handler;
+ }
+
+ if(!req.http.X-SEC-Client){ # this variable always present, so rule always false
+ # all functions must be used in vcl, fool compiler by putting them here
+
+ log "security.vcl WONTREACH: available sec handlers";
+ # the handlers are defined in main.vcl along with the error codes
+ # handler name # code # purpose
+ call sec_general; # 800 # debug handler - delivers X-SEC-Rule to client
+ call sec_reject; # 801 # 403 reject with message
+ call sec_redirect; # 802 # 302 redirect
+ call sec_honeypot; # 803 # restart request with honeypot backend
+ call sec_synthtml; # 804 # synthesize a response
+ call sec_drop; # 805 # drop the request (not implemented)
+ call sec_myhandler; # any # do your own thing
+
+ ## note! the passthru handler really does pass thru
+ # - you must make sure it is the last thing called
+ call sec_passthru; # n/a # log client and pass thru to default error logic
+ }
+}
+
+/* You can define your own handlers here if you know a little vcl.
+ * The default handlers are defined in main.vcl
+ * remember that it must be referenced in the code above */
+
+/* sample handler, contains sample code for all handler types */
+sub sec_myhandler {
+ # perform an action based on the error code as above.
+
+ error 800 "Blahblah";
+
+ set req.http.X-SEC-Response = "we don't like your kind around here";
+ error 801 "Rejected";
+
+ set req.http.X-SEC-Response = "http://u.rdir.it/hit/me/please";
+ error 802 "Redirect";
+
+ # send to sec_honey backend
+ error 803 "Honeypot me";
+
+ set req.http.X-SEC-Response = "<h1>Whatever</h1> so you think you can dance?";
+ error 804 "Synthesize";
+
+ error 805 "Drop";
+}
View
157 vcl/main.vcl
@@ -25,60 +25,139 @@
* hardcoded. Blah.
*/
+
+# clear all internal variables
+include "/etc/varnish/security/build/variables.vcl";
+
+sub vcl_recv {
+ # gather info about client
+ # this is one of the vars guaranteed to be present
+ # if and only if your request is inside security.vcl
+ set req.http.X-SEC-Client = client.ip " "
+ req.http.host req.url
+ " agent:" req.http.user-agent;
+}
+
+# which modules to use, what to log, how to handle events and honeypot backend definition
+include "/etc/varnish/security/config.vcl";
+
+# fallthrough: clear all internal variables on security.vcl_recv exit
include "/etc/varnish/security/build/variables.vcl";
-include "/etc/varnish/security/modules/demo.vcl";
-include "/etc/varnish/security/modules/php.vcl";
-include "/etc/varnish/security/modules/sql.vcl";
-include "/etc/varnish/security/modules/xss.vcl";
-include "/etc/varnish/security/modules/cmd.vcl";
-include "/etc/varnish/security/modules/restricted-file-extensions.vcl";
-include "/etc/varnish/security/modules/content-encoding.vcl";
-include "/etc/varnish/security/modules/content-type.vcl";
-include "/etc/varnish/security/modules/localfiles.vcl";
-include "/etc/varnish/security/modules/request.vcl";
-
-#include "/etc/varnish/security/modules/user-agent.vcl";
-
-#include "/etc/varnish/security/breach/20_protocol_violations.vcl";
-#include "/etc/varnish/security/breach/21_protocol_anomalies.vcl";
-#include "/etc/varnish/security/breach/23_request_limits.vcl";
-#include "/etc/varnish/security/breach/30_http_policy.vcl";
-#include "/etc/varnish/security/breach/35_bad_robots.vcl";
-#include "/etc/varnish/security/breach/40_generic_attacks.vcl";
-#include "/etc/varnish/security/breach/45_trojans.vcl";
-#include "/etc/varnish/security/breach/50_outbound.vcl";
+
+# define all the event handlers
+include "/etc/varnish/security/handlers.vcl";
/* The value of '800' and up is used because it is not actual HTTP error
* codes. They should not be exposed.
*
* The list thus far:
* 800 - Debug
- * 801 - Plain error (401-unauthorized might be a bad rewrite here)
+ * 801 - Plain error (403-forbidden might be a bad rewrite here)
* 802 - Redirect
+ * 803 - Restart, forward to backend honey
+ * 804 - Synthetic response
+ * 805 - Attempt to drop or reset the request (not implemented yet)
*/
sub vcl_error {
- if (obj.status == 800) {
- set obj.http.X-SEC-Rule = req.http.X-SEC-Module "-" req.http.X-SEC-RuleId;
-
- set obj.status = 200;
- } elsif (obj.status == 801) {
- set obj.status = 401;
- set obj.response = "Here be dragons! YARR! Wait, that's pirates.";
- } elsif (obj.status == 802) {
- set obj.status = 302;
- set obj.response = "Redirected for fun and profit";
- set obj.http.Location = "http://images.google.com/images?q=llama";
- return (deliver);
- }
+ # are we insecure?
+ if(req.restarts == 0 && req.http.X-SEC-Client){
+ # XXX: for some reason one log prints twice... bug?
+ call sec_log;
+ if (obj.status == 800) {
+ set obj.http.X-SEC-Rule = req.http.X-SEC-Module "-" req.http.X-SEC-RuleId;
+ set obj.status = 200;
+ } elsif (obj.status == 801) {
+ set obj.status = 403;
+ if(req.http.X-SEC-Response){
+ set obj.response = req.http.X-SEC-Response;
+ }else{
+ set obj.response = "Forbidden";
+ }
+ } elsif (obj.status == 802) {
+ set obj.status = 302;
+ #set obj.response = "Redirected for fun and profit";
+ if(obj.http.X-SEC-Response){
+ set obj.http.Location = obj.http.X-SEC-Response;
+ }else{
+ set obj.http.Location = "http://images.google.com/images?q=llama";
+ }
+ return (deliver);
+ } elsif (obj.status == 803) {
+ # restart on 2nd backend
+ set req.http.X-SEC-Response = "honeypot me";
+ set req.backend = sec_honey;
+ restart;
+ } elsif (obj.status == 804){
+ set obj.status = 200;
+ set obj.response = "OK";
+ set obj.http.content-type = "text/html";
+ if(! obj.http.X-SEC-Response ){
+ set obj.http.X-SEC-Response = "Synthetic";
+ }
+ synthetic {"<html><body>
+"} obj.http.X-SEC-Response {"
+</body></html>
+"};
+ return (deliver);
+ } elsif (obj.status == 805){
+ set obj.status = 501;
+ set obj.response = "Get outta here";
+ }
+ # fallthrough to other vcl_error's
+ }
+}
+
+/* Call this one to just log rule hits and pass to backend
+ * without calling error.
+ * This effectively *DISABLES* security.vcl protectionism */
+sub sec_passthru {
+ call sec_log;
}
-/* Catch-all handler */
+
+/* Call this one for a catch-all */
sub sec_general {
- error 800 "BOOOYA!";
+ error 800 "Naugty, not nice!";
+}
+
+/* 403 rejected */
+sub sec_reject {
+ error 801 "Rejected";
+}
+
+/* call this one for a redirect */
+sub sec_redirect {
+ error 802 "Redirect";
+}
+
+sub sec_honeypot {
+ error 803 "Sexy Honey";
+}
+
+/* call this one for synthetic html */
+sub sec_synthtml {
+ error 804 "Synthetic";
+}
+
+/* TODO: drop the request..
+ * the plan is to implement VMOD that either
+ * - sends an RST and kills the client connection OR
+ * - kills the client connection silently
+ */
+sub sec_drop {
+ error 805 "quit it";
}
-sub sec_sev1 {
- call sec_general;
+sub sec_magichandler {
+ if(!req.http.X-SEC-Response) {
+ ## The default attack response message, can be overridden by rules.
+ set req.http.X-SEC-Response = "Naughty, not nice!";
+ }
+ if(req.http.X-SEC-Response ~ "^honeypot me$"){
+ # we have restarted and our request is on the honeypot backend
+ # pass the request;
+ return (pass);
+ }
}
/* vim: set syntax=c tw=76: */
View
4 vcl/modules/cmd.vcl
@@ -2,7 +2,7 @@
# For now
sub sec_cmd_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
@@ -63,7 +63,7 @@ sub vcl_recv {
# Checks if someone tries to inject a common command name in URL
if (req.url ~ "(=|;|&&|%7C%7C)(whoami|who|uptime|last|df).*") {
- set req.http.X-SEC-RuleName = "Common command in URL: cmd.exe";
+ set req.http.X-SEC-RuleName = "Common command in URL: unixish";
set req.http.X-SEC-RuleId = "7";
set req.http.X-SEC-RuleInfo = "Checks if someone tries to inject a common command name in URL: cmd.exe";
call sec_cmd_sev1;
View
2 vcl/modules/content-encoding.vcl
@@ -2,7 +2,7 @@
# For now
sub sec_contentencoding_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
sub vcl_recv {
View
2 vcl/modules/content-type.vcl
@@ -2,7 +2,7 @@
# For now
sub sec_contenttype_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
sub vcl_recv {
View
2 vcl/modules/demo.vcl
@@ -24,7 +24,7 @@
sub sec_demo_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
sub vcl_recv {
View
2 vcl/modules/localfiles.vcl
@@ -2,7 +2,7 @@
# For now
sub sec_localfiles_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
View
2 vcl/modules/php.vcl
@@ -2,7 +2,7 @@
# For now
sub sec_php_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
View
2 vcl/modules/request.vcl
@@ -2,7 +2,7 @@
# For now
sub sec_request_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
sub vcl_recv {
View
2 vcl/modules/restricted-file-extensions.vcl
@@ -2,7 +2,7 @@
# For now
sub sec_restrictedfileextentions_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
sub vcl_recv {
View
2 vcl/modules/sql.vcl
@@ -2,7 +2,7 @@
# For now
sub sec_sql_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
View
2 vcl/modules/user-agent.vcl
@@ -2,7 +2,7 @@
# For now
sub sec_useragent_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
View
2 vcl/modules/xss.vcl
@@ -2,7 +2,7 @@
# For now
sub sec_xss_sev1 {
set req.http.X-SEC-Severity = "1";
- call sec_sev1;
+ call sec_handler;
}
sub vcl_recv {

0 comments on commit f539bbd

Please sign in to comment.
Something went wrong with that request. Please try again.