| /* |
| * NAXSI, a web application firewall for NGINX |
| * Copyright (C) 2011, Thibault 'bui' Koechlin |
| * |
| * This program is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation, either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * In addition, as a special exception, the copyright holders give |
| * permission to link the code of portions of this program with the |
| * OpenSSL library under certain conditions as described in each |
| * individual source file, and distribute linked combinations |
| * including the two. |
| * You must obey the GNU General Public License in all respects |
| * for all of the code used other than OpenSSL. If you modify |
| * file(s) with this exception, you may extend this exception to your |
| * version of the file(s), but you are not obligated to do so. If you |
| * do not wish to do so, delete this exception statement from your |
| * version. If you delete this exception statement from all source |
| * files in the program, then also delete it here. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #ifndef __FOO_H__ |
| #define __FOO_H__ |
| |
| #define NAXSI_VERSION "0.50" |
| |
| #include <nginx.h> |
| #include <ngx_config.h> |
| #include <ngx_core.h> |
| #include <ngx_http.h> |
| #include <ngx_event.h> |
| #include <ngx_md5.h> |
| #include <ngx_http_core_module.h> |
| #include <pcre.h> |
| #include <ctype.h> |
| |
| |
| extern ngx_module_t ngx_http_naxsi_module; |
| |
| /* |
| ** Here is globally how the structures are organized : |
| ** |
| ** [[ngx_http_dummy_main_conf_t]] is the main structure for the module. |
| ** it contains the core rules and a set of ngx_http_dummy_loc_conf_t, |
| ** for each NGINX location. |
| ** --- |
| ** [[ngx_http_dummy_loc_conf_t]] is the main structure for any NGINX |
| ** locations, that is - a web site. It contains both pointers to the core |
| ** rules, as well as whitelists, scores, denied_url and all flags. all |
| ** the data of a nginx location is held into the loc_conf_t struct. |
| ** The sets of rules are actually containted into [[ngx_http_rule_t]] structs. |
| ** --- |
| ** [[ngx_http_rule_t]] structs are used to hold any info about a rule, as well |
| ** as whitelists. (whitelists is just a 'kind' of rule). |
| ** |
| */ |
| |
| enum MATCH_TYPE { |
| URI_ONLY=0, |
| NAME_ONLY, |
| MIXED |
| }; |
| |
| enum DUMMY_MATCH_ZONE { |
| HEADERS=0, |
| URL, |
| ARGS, |
| BODY, |
| FILE_EXT, |
| UNKNOWN |
| }; |
| |
| |
| /* |
| ** struct used to store a specific match zone |
| ** in conf : MATCH_ZONE:[GET_VAR|HEADER|POST_VAR]:VAR_NAME: |
| */ |
| typedef struct |
| { |
| /* match in [name] var of body */ |
| ngx_flag_t body_var:1; |
| /* match in [name] var of headers */ |
| ngx_flag_t headers_var:1; |
| /* match in [name] var of args */ |
| ngx_flag_t args_var:1; |
| /* match on URL [name] */ |
| ngx_flag_t specific_url:1; |
| ngx_str_t target; |
| ngx_uint_t hash; |
| } ngx_http_custom_rule_location_t; |
| |
| |
| /* |
| ** WhiteList Rules Definition : |
| ** A whitelist contains : |
| ** - an URI |
| ** |
| ** - one or several sets containing : |
| ** - an variable name ('foo') associated with a zone ($GET_VAR:foo) |
| ** - one or several rules id to whitelist |
| */ |
| |
| #define WEIRD_REQUEST_INTERNAL_RULE_ID 1 |
| #define BIG_BODY_INTERNAL_RULE_ID 2 |
| typedef struct |
| { |
| /* match in full body (POST DATA) */ |
| ngx_flag_t body:1; |
| /* match in [name] var of body */ |
| ngx_flag_t body_var:1; |
| /* match in all headers */ |
| ngx_flag_t headers:1; |
| /* match in [name] var of headers */ |
| ngx_flag_t headers_var:1; |
| /* match in URI */ |
| ngx_flag_t url:1; |
| /* match in args (bla.php?<ARGS>) */ |
| ngx_flag_t args:1; |
| /* match in [name] var of args */ |
| ngx_flag_t args_var:1; |
| /* match on a global flag : weird_request, big_body etc. */ |
| ngx_flag_t flags:1; |
| /* match on file upload extension */ |
| ngx_flag_t file_ext:1; |
| /* set if defined "custom" match zone (GET_VAR/POST_VAR/...) */ |
| ngx_array_t *ids; |
| ngx_str_t *name; |
| } ngx_http_whitelist_location_t; |
| |
| |
| /* |
| ** this struct is used to aggregate all whitelist |
| ** that point to the same URI or the same VARNAME |
| ** all the "subrules" will then be stored in the "whitelist_locations" |
| */ |
| typedef struct |
| { |
| //ngx_http_whitelist_location_t |
| ngx_array_t *whitelist_locations; |
| // zone to wich the WL applies |
| enum DUMMY_MATCH_ZONE zone; |
| // if the "name" is only an url, specify it |
| int uri_only:1; |
| /* does the rule targets the name |
| instead of the content ?*/ |
| int target_name; |
| |
| ngx_str_t *name; |
| ngx_int_t hash; |
| ngx_array_t *ids; |
| } ngx_http_whitelist_rule_t; |
| |
| |
| |
| |
| |
| |
| /* basic rule */ |
| typedef struct |
| { |
| ngx_str_t *str; // string |
| ngx_regex_compile_t *rx; // or regex |
| ngx_int_t transform; //transform rule to apply, as flags. |
| /* ~~~~~ match zones ~~~~~~ */ |
| /* match in full body (POST DATA) */ |
| ngx_flag_t body:1; |
| ngx_flag_t body_var:1; |
| /* match in all headers */ |
| ngx_flag_t headers:1; |
| ngx_flag_t headers_var:1; |
| /* match in URI */ |
| ngx_flag_t url:1; |
| /* match in args (bla.php?<ARGS>) */ |
| ngx_flag_t args:1; |
| ngx_flag_t args_var:1; |
| /* match on flags (weird_uri, big_body etc. */ |
| ngx_flag_t flags:1; |
| /* match on file upload extension */ |
| ngx_flag_t file_ext:1; |
| /* set if defined "custom" match zone (GET_VAR/POST_VAR/...) */ |
| ngx_flag_t custom_location:1; |
| ngx_int_t custom_location_only; |
| /* does the rule targets variable name instead ? */ |
| ngx_int_t target_name; |
| |
| /* custom location match zones list (GET_VAR/POST_VAR ...) */ |
| ngx_array_t *custom_locations; |
| /* ~~~~~~~ specific flags ~~~~~~~~~ */ |
| ngx_flag_t negative:1; |
| } ngx_http_basic_rule_t; |
| |
| |
| |
| /* define for RULE TYPE in rule_t */ |
| #define BR 1 |
| //#define FR 2 UNUSED |
| //#define WR 3 UNUSED |
| |
| /* flags used for 'custom match rules', like $XSS > 7 */ |
| #define SUP 1 |
| #define SUP_OR_EQUAL 2 |
| #define INF 3 |
| #define INF_OR_EQUAL 4 |
| |
| /* |
| ** This struct is used to store custom scores at runtime. |
| ** ie : $XSS = 7 |
| ** tag is the $XSS and sc_score is 7 |
| */ |
| typedef struct |
| { |
| ngx_str_t *sc_tag; |
| ngx_int_t sc_score; |
| ngx_flag_t block:1; |
| ngx_flag_t allow:1; |
| ngx_flag_t log:1; |
| } ngx_http_special_score_t; |
| |
| /* |
| ** This one is very related to the previous one, |
| ** it's used to store a score rule comparison. |
| ** ie : $XSS > 7 |
| */ |
| typedef struct |
| { |
| ngx_str_t sc_tag; |
| ngx_int_t sc_score; |
| ngx_int_t cmp; |
| ngx_flag_t block:1; |
| ngx_flag_t allow:1; |
| ngx_flag_t log:1; |
| } ngx_http_check_rule_t; |
| |
| /* TOP level rule structure */ |
| typedef struct |
| { |
| /* type of the rule */ |
| ngx_int_t type; |
| // simply put a flag if it's a wlr, wl_id array will be used to store the whitelisted IDs |
| ngx_flag_t whitelist:1; |
| ngx_int_t *wl_id; |
| /* "common" data for all rules */ |
| ngx_int_t rule_id; |
| ngx_str_t *log_msg; // a specific log message |
| ngx_int_t score; //also handles DENY and ALLOW |
| |
| /* List of scores increased on rule match. */ |
| ngx_array_t *sscores; |
| /*ngx_str_t *sc_tag; //specific score tag |
| ngx_int_t sc_score; //specific score value*/ |
| ngx_flag_t sc_block:1; // |
| ngx_flag_t sc_allow:1; // |
| // end of specific score tag stuff |
| ngx_flag_t block:1; |
| ngx_flag_t allow:1; |
| ngx_flag_t log:1; |
| /* flag set if we're linked FROM or TO another rule */ |
| ngx_flag_t lnk_to:1; |
| ngx_flag_t lnk_from:1; |
| /* pointers on specific rule stuff */ |
| ngx_http_basic_rule_t *br; |
| } ngx_http_rule_t; |
| |
| typedef struct |
| { |
| ngx_array_t *get_rules; /*ngx_http_rule_t*/ |
| ngx_array_t *body_rules; |
| ngx_array_t *header_rules; |
| ngx_array_t *generic_rules; |
| ngx_array_t *locations; /*ngx_http_dummy_loc_conf_t*/ |
| ngx_log_t *log; |
| |
| } ngx_http_dummy_main_conf_t; |
| |
| |
| /* TOP level configuration structure */ |
| typedef struct |
| { |
| ngx_array_t *get_rules; |
| ngx_array_t *body_rules; |
| ngx_array_t *header_rules; |
| ngx_array_t *generic_rules; |
| ngx_array_t *check_rules; |
| /* raw array of whitelisted rules */ |
| ngx_array_t *whitelist_rules; |
| /* raw array of transformed whitelists */ |
| ngx_array_t *tmp_wlr; |
| /* hash table of whitelisted URL rules */ |
| ngx_hash_t *wlr_url_hash; |
| /* hash table of whitelisted ARGS rules */ |
| ngx_hash_t *wlr_args_hash; |
| /* hash table of whitelisted BODY rules */ |
| ngx_hash_t *wlr_body_hash; |
| /* hash table of whitelisted HEADERS rules */ |
| ngx_hash_t *wlr_headers_hash; |
| /* rules that are globally disabled in one location */ |
| ngx_array_t *disabled_rules; |
| /* counters for both processed requests and |
| blocked requests, used in naxsi_fmt */ |
| size_t request_processed; |
| size_t request_blocked; |
| ngx_int_t error; |
| ngx_array_t *persistant_data; |
| ngx_flag_t extensive:1; |
| ngx_flag_t learning:1; |
| ngx_flag_t enabled:1; |
| ngx_flag_t force_disabled:1; |
| ngx_flag_t pushed:1; |
| ngx_str_t *denied_url; |
| /* precomputed hash for dynamic variable lookup, |
| variable themselves are boolean */ |
| ngx_uint_t flag_enable_h; |
| ngx_uint_t flag_learning_h; |
| ngx_uint_t flag_post_action_h; |
| ngx_uint_t flag_extensive_log_h; |
| |
| } ngx_http_dummy_loc_conf_t; |
| |
| |
| /* |
| ** used to store sets of matched rules during runtime |
| */ |
| typedef struct |
| { |
| /* matched in [name] var of body */ |
| ngx_flag_t body_var:1; |
| /* matched in [name] var of headers */ |
| ngx_flag_t headers_var:1; |
| /* matched in [name] var of args */ |
| ngx_flag_t args_var:1; |
| /* matched on URL */ |
| ngx_flag_t url:1; |
| /* matched in filename [name] of args*/ |
| ngx_flag_t file_ext:1; |
| /* matched within the 'NAME' */ |
| ngx_flag_t target_name:1; |
| |
| ngx_str_t *name; |
| ngx_http_rule_t *rule; |
| } ngx_http_matched_rule_t; |
| |
| /* |
| ** Context structure |
| */ |
| typedef struct |
| { |
| ngx_array_t *special_scores; |
| ngx_int_t score; |
| /* blocking flags */ |
| ngx_flag_t log:1; |
| ngx_flag_t block:1; |
| ngx_flag_t allow:1; |
| /* state */ |
| ngx_flag_t wait_for_body:1; |
| ngx_flag_t ready:1; |
| ngx_flag_t over:1; |
| /* flag request */ |
| ngx_flag_t weird_request:1; |
| ngx_flag_t big_request:1; |
| /* matched rules */ |
| ngx_array_t *matched; |
| /* runtime flags (modifiers) */ |
| ngx_flag_t learning:1; |
| ngx_flag_t enabled:1; |
| ngx_flag_t post_action:1; |
| ngx_flag_t extensive_log:1; |
| |
| } ngx_http_request_ctx_t; |
| |
| #define TOP_DENIED_URL_T "DeniedUrl" |
| #define TOP_LEARNING_FLAG_T "LearningMode" |
| #define TOP_ENABLED_FLAG_T "SecRulesEnabled" |
| #define TOP_DISABLED_FLAG_T "SecRulesDisabled" |
| #define TOP_CHECK_RULE_T "CheckRule" |
| #define TOP_BASIC_RULE_T "BasicRule" |
| #define TOP_MAIN_BASIC_RULE_T "MainRule" |
| |
| /* nginx-style names */ |
| #define TOP_DENIED_URL_N "denied_url" |
| #define TOP_LEARNING_FLAG_N "learning_mode" |
| #define TOP_ENABLED_FLAG_N "rules_enabled" |
| #define TOP_DISABLED_FLAG_N "rules_disabled" |
| #define TOP_CHECK_RULE_N "check_rule" |
| #define TOP_BASIC_RULE_N "basic_rule" |
| #define TOP_MAIN_BASIC_RULE_N "main_rule" |
| |
| /*possible 'tokens' in rule */ |
| #define ID_T "id:" |
| #define TRANSFORM_T "t:" |
| #define SCORE_T "s:" |
| //#define PERSISTANT_SCORE_T "ps:" |
| #define MSG_T "msg:" |
| #define RX_T "rx:" |
| #define STR_T "str:" |
| #define MATCH_ZONE_T "mz:" |
| #define WHITELIST_T "wl:" |
| #define NEGATIVE_T "negative" |
| |
| /* name of hardcoded variables to |
| change behavior of naxsi at runtime */ |
| #define RT_EXTENSIVE_LOG "naxsi_extensive_log" |
| #define RT_ENABLE "naxsi_flag_enable" |
| #define RT_LEARNING "naxsi_flag_learning" |
| #define RT_POST_ACTION "naxsi_flag_post_action" |
| |
| |
| |
| |
| extern ngx_http_dummy_loc_conf_t *dummy_lc; |
| |
| |
| |
| void *ngx_http_dummy_cfg_parse_one_rule(ngx_conf_t *cf, |
| ngx_str_t *value, |
| ngx_http_rule_t *rule, |
| ngx_int_t nb_elem); |
| char *strfaststr(unsigned char *haystack, unsigned int hl, |
| unsigned char *needle, unsigned int nl); |
| char *strnchr(const char *s, int c, int len); |
| char *strncasechr(const char *s, int c, int len); |
| ngx_int_t ngx_http_dummy_create_hashtables(ngx_http_dummy_loc_conf_t *dlc, |
| ngx_conf_t *cf); |
| ngx_int_t ngx_http_dummy_create_hashtables_n(ngx_http_dummy_loc_conf_t *dlc, |
| ngx_conf_t *cf); |
| void ngx_http_dummy_data_parse(ngx_http_request_ctx_t *ctx, |
| ngx_http_request_t *r); |
| ngx_int_t ngx_http_output_forbidden_page(ngx_http_request_ctx_t *ctx, |
| ngx_http_request_t *r); |
| void |
| naxsi_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type); |
| |
| |
| int naxsi_unescape(ngx_str_t *str); |
| |
| |
| /* static ngx_int_t ngx_http_dummy_subrequest(ngx_http_request_t *r, */ |
| /* ngx_chain_t *in); */ |
| //ngx_int_t ngx_http_dummy_subrequest(ngx_http_request_t *r); |
| #endif |
| |