mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
Adds fuzzyHash operator
The fuzzyHash operator can be used to match files. In conjuntcion with FILES_TMP_CONTENT collection it can scan uploaded files and try to match it with a pre caculated list of know malicious content, more details on how it works can be found on ssdeep website: http://ssdeep.sourceforge.net/
This commit is contained in:
parent
873c628b1a
commit
96865a92d3
@ -2453,6 +2453,32 @@ not_enough_memory:
|
|||||||
return headers_length;
|
return headers_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int read_line(char *buf, int len, FILE *fp)
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
if (buf == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buf, '\0', len*sizeof(char));
|
||||||
|
|
||||||
|
if (fgets(buf, len, fp) == NULL)
|
||||||
|
{
|
||||||
|
*buf = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((tmp = strrchr(buf, '\n')) != NULL)
|
||||||
|
{
|
||||||
|
*tmp = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int create_radix_tree(apr_pool_t *mp, TreeRoot **rtree, char **error_msg)
|
int create_radix_tree(apr_pool_t *mp, TreeRoot **rtree, char **error_msg)
|
||||||
{
|
{
|
||||||
|
@ -159,4 +159,6 @@ int DSOLOCAL tree_contains_ip(apr_pool_t *mp, TreeRoot *rtree,
|
|||||||
int DSOLOCAL ip_tree_from_param(apr_pool_t *pool,
|
int DSOLOCAL ip_tree_from_param(apr_pool_t *pool,
|
||||||
char *param, TreeRoot **rtree, char **error_msg);
|
char *param, TreeRoot **rtree, char **error_msg);
|
||||||
|
|
||||||
|
int read_line(char *buff, int size, FILE *fp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -409,4 +409,9 @@ struct msre_cache_rec {
|
|||||||
apr_size_t val_len;
|
apr_size_t val_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fuzzy_hash_param_data {
|
||||||
|
const char *file;
|
||||||
|
int threshold;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_SSDEEP
|
||||||
|
#include "fuzzy.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "libinjection/libinjection.h"
|
#include "libinjection/libinjection.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3718,6 +3722,142 @@ static int msre_op_rbl_execute(modsec_rec *msr, msre_rule *rule, msre_var *var,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fuzzyHash */
|
||||||
|
static int msre_op_fuzzy_hash_init(msre_rule *rule, char **error_msg)
|
||||||
|
{
|
||||||
|
#ifdef WITH_SSDEEP
|
||||||
|
struct fuzzy_hash_param_data *param_data;
|
||||||
|
char *file;
|
||||||
|
int param_len,threshold;
|
||||||
|
|
||||||
|
char *data = NULL;
|
||||||
|
char *threshold_str = NULL;
|
||||||
|
|
||||||
|
param_data = apr_palloc(rule->ruleset->mp,
|
||||||
|
sizeof(struct fuzzy_hash_param_data));
|
||||||
|
|
||||||
|
data = apr_pstrdup(rule->ruleset->mp, rule->op_param);
|
||||||
|
threshold_str = data;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (error_msg == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*error_msg = NULL;
|
||||||
|
|
||||||
|
#ifdef WITH_SSDEEP
|
||||||
|
/* Sanity check */
|
||||||
|
param_len = strlen(threshold_str);
|
||||||
|
threshold_str = threshold_str + param_len;
|
||||||
|
|
||||||
|
if (param_len < 3)
|
||||||
|
{
|
||||||
|
goto invalid_parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (param_len - 1 > 0 && *threshold_str != ' ')
|
||||||
|
{
|
||||||
|
param_len--;
|
||||||
|
threshold_str--;
|
||||||
|
}
|
||||||
|
|
||||||
|
*threshold_str = '\0';
|
||||||
|
threshold_str++;
|
||||||
|
file = data;
|
||||||
|
threshold = atoi(threshold_str);
|
||||||
|
|
||||||
|
if ((file == NULL) || (is_empty_string(file)) || (threshold > 100) ||
|
||||||
|
(threshold < 1))
|
||||||
|
{
|
||||||
|
goto invalid_parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = resolve_relative_path(rule->ruleset->mp, rule->filename, file);
|
||||||
|
|
||||||
|
if (!fopen(file, "r"))
|
||||||
|
{
|
||||||
|
*error_msg = apr_psprintf(rule->ruleset->mp, "Not able to open file:" \
|
||||||
|
" %s.", file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
param_data->file = file;
|
||||||
|
param_data->threshold = threshold;
|
||||||
|
|
||||||
|
rule->op_param_data = param_data;
|
||||||
|
#else
|
||||||
|
*error_msg = apr_psprintf(rule->ruleset->mp, "ModSecurity was not " \
|
||||||
|
"compiled with ssdeep support.");
|
||||||
|
|
||||||
|
rule->op_param_data = NULL;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
invalid_parameters:
|
||||||
|
*error_msg = apr_psprintf(rule->ruleset->mp, "Operator @fuzzyHash " \
|
||||||
|
"requires valid parameters. File and threshold.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msre_op_fuzzy_hash_execute(modsec_rec *msr, msre_rule *rule,
|
||||||
|
msre_var *var, char **error_msg)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef WITH_SSDEEP
|
||||||
|
char result[FUZZY_MAX_RESULT];
|
||||||
|
struct fuzzy_hash_param_data *param = rule->op_param_data;
|
||||||
|
char line[1024];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (error_msg == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*error_msg = NULL;
|
||||||
|
|
||||||
|
#ifdef WITH_SSDEEP
|
||||||
|
if (fuzzy_hash_buf(var->value, var->value_len, result))
|
||||||
|
{
|
||||||
|
*error_msg = apr_psprintf(rule->ruleset->mp, "Problems generating " \
|
||||||
|
"fuzzy hash.");
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fp = fopen(param->file, "r");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
*error_msg = apr_psprintf(rule->ruleset->mp, "Not able to open " \
|
||||||
|
"fuzzy hash file: %s", param->file);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (read_line(line, sizeof(line), fp))
|
||||||
|
{
|
||||||
|
int i = fuzzy_compare(line, result);
|
||||||
|
if (i >= param->threshold)
|
||||||
|
{
|
||||||
|
*error_msg = apr_psprintf(msr->mp, "Fuzzy hash of %s matched " \
|
||||||
|
"with %s (from: %s). Socore: %d.", var->name, line,
|
||||||
|
param->file, i);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* No match. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* inspectFile */
|
/* inspectFile */
|
||||||
|
|
||||||
static int msre_op_inspectFile_init(msre_rule *rule, char **error_msg) {
|
static int msre_op_inspectFile_init(msre_rule *rule, char **error_msg) {
|
||||||
@ -4552,6 +4692,13 @@ void msre_engine_register_default_operators(msre_engine *engine) {
|
|||||||
msre_op_inspectFile_execute
|
msre_op_inspectFile_execute
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* fuzzy_hash */
|
||||||
|
msre_engine_op_register(engine,
|
||||||
|
"fuzzyHash",
|
||||||
|
msre_op_fuzzy_hash_init,
|
||||||
|
msre_op_fuzzy_hash_execute
|
||||||
|
);
|
||||||
|
|
||||||
/* validateByteRange */
|
/* validateByteRange */
|
||||||
msre_engine_op_register(engine,
|
msre_engine_op_register(engine,
|
||||||
"validateByteRange",
|
"validateByteRange",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user