mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-09-29 11:16:33 +03:00
Lua: Added support for scripting to @inspectFile.
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
*
|
||||
*/
|
||||
#include <limits.h>
|
||||
#include <apr_lib.h>
|
||||
|
||||
#include "modsecurity.h"
|
||||
#include "msc_logging.h"
|
||||
@@ -18,15 +17,6 @@
|
||||
|
||||
#include "msc_lua.h"
|
||||
|
||||
static const char *configuration_relative_path(apr_pool_t *pool, const char *parent_filename, const char *filename) {
|
||||
if (filename == NULL) return NULL;
|
||||
// TODO Support paths on operating systems other than Unix.
|
||||
if (filename[0] == '/') return filename;
|
||||
|
||||
return apr_pstrcat(pool, apr_pstrndup(pool, parent_filename,
|
||||
strlen(parent_filename) - strlen(apr_filepath_name_get(parent_filename))),
|
||||
filename, NULL);
|
||||
}
|
||||
|
||||
/* -- Directory context creation and initialisation -- */
|
||||
|
||||
@@ -1297,7 +1287,7 @@ static const char *cmd_rule_inheritance(cmd_parms *cmd, void *_dcfg, int flag) {
|
||||
static const char *cmd_rule_script(cmd_parms *cmd, void *_dcfg, const char *p1,
|
||||
const char *p2)
|
||||
{
|
||||
const char *filename = configuration_relative_path(cmd->pool, cmd->directive->filename, p1);
|
||||
const char *filename = resolve_relative_path(cmd->pool, cmd->directive->filename, p1);
|
||||
return add_rule(cmd, (directory_config *)_dcfg, RULE_TYPE_LUA, filename, p2, NULL);
|
||||
}
|
||||
#endif
|
||||
|
@@ -244,7 +244,7 @@ static const struct luaL_Reg mylib[] = {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
int lua_execute(msc_script *script, modsec_rec *msr, msre_rule *rule, char **error_msg) {
|
||||
int lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rule, char **error_msg) {
|
||||
apr_time_t time_before;
|
||||
lua_State *L = NULL;
|
||||
int rc;
|
||||
@@ -288,7 +288,12 @@ int lua_execute(msc_script *script, modsec_rec *msr, msre_rule *rule, char **err
|
||||
/* Execute main() */
|
||||
lua_getglobal(L, "main");
|
||||
|
||||
if (lua_pcall(L, 0, 1, 0)) {
|
||||
/* Put the parameter on the stack. */
|
||||
if (param != NULL) {
|
||||
lua_pushlstring(L, param, strlen(param));
|
||||
}
|
||||
|
||||
if (lua_pcall(L, ((param != NULL) ? 1 : 0), 1, 0)) {
|
||||
*error_msg = apr_psprintf(msr->mp, "Lua: Script execution failed: %s", lua_tostring(L, -1));
|
||||
return -1;
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ struct msc_script_part {
|
||||
|
||||
char DSOLOCAL *lua_compile(msc_script **script, const char *filename, apr_pool_t *pool);
|
||||
|
||||
int DSOLOCAL lua_execute(msc_script *script, modsec_rec *msr, msre_rule *rule, char **error_msg);
|
||||
int DSOLOCAL lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rule, char **error_msg);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <apr_lib.h>
|
||||
|
||||
/* NOTE: Be careful as these can ONLY be used on static values for X.
|
||||
* (i.e. VALID_HEX(c++) will NOT work)
|
||||
*/
|
||||
@@ -1176,3 +1178,28 @@ char *modsec_build(apr_pool_t *mp) {
|
||||
build_type,
|
||||
atoi(MODSEC_VERSION_RELEASE));
|
||||
}
|
||||
|
||||
int is_empty_string(const char *string) {
|
||||
unsigned int i;
|
||||
|
||||
if (string == NULL) return 1;
|
||||
if (strlen(string) == 0) return 1;
|
||||
|
||||
for(i = 0; i < strlen(string); i++) {
|
||||
if (!isspace(string[i])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *resolve_relative_path(apr_pool_t *pool, const char *parent_filename, const char *filename) {
|
||||
if (filename == NULL) return NULL;
|
||||
// TODO Support paths on operating systems other than Unix.
|
||||
if (filename[0] == '/') return (char *)filename;
|
||||
|
||||
return apr_pstrcat(pool, apr_pstrndup(pool, parent_filename,
|
||||
strlen(parent_filename) - strlen(apr_filepath_name_get(parent_filename))),
|
||||
filename, NULL);
|
||||
}
|
||||
|
@@ -78,4 +78,8 @@ int DSOLOCAL ansi_c_sequences_decode_inplace(unsigned char *input, int len);
|
||||
|
||||
char DSOLOCAL *modsec_build(apr_pool_t *mp);
|
||||
|
||||
int DSOLOCAL is_empty_string(const char *string);
|
||||
|
||||
char DSOLOCAL *resolve_relative_path(apr_pool_t *pool, const char *parent_filename, const char *filename);
|
||||
|
||||
#endif
|
||||
|
@@ -1966,7 +1966,7 @@ static apr_status_t msre_rule_process_lua(msre_rule *rule, modsec_rec *msr) {
|
||||
acting_actionset = rule->chain_starter->actionset;
|
||||
}
|
||||
|
||||
rc = lua_execute(rule->script, msr, rule, &my_error_msg);
|
||||
rc = lua_execute(rule->script, NULL, msr, rule, &my_error_msg);
|
||||
if (rc < 0) {
|
||||
msr_log(msr, 1, "%s", my_error_msg);
|
||||
return -1;
|
||||
|
@@ -1484,7 +1484,7 @@ static apr_status_t msre_action_exec_execute(modsec_rec *msr, apr_pool_t *mptmp,
|
||||
msc_script *script = (msc_script *)action->param_data;
|
||||
char *my_error_msg = NULL;
|
||||
|
||||
if (lua_execute(script, msr, rule, &my_error_msg) < 0) {
|
||||
if (lua_execute(script, NULL, msr, rule, &my_error_msg) < 0) {
|
||||
msr_log(msr, 1, "%s", my_error_msg);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1237,44 +1237,99 @@ static int msre_op_rbl_execute(modsec_rec *msr, msre_rule *rule, msre_var *var,
|
||||
}
|
||||
|
||||
/* inspectFile */
|
||||
static int msre_op_inspectFile_execute(modsec_rec *msr, msre_rule *rule, msre_var *var,
|
||||
char **error_msg)
|
||||
{
|
||||
char *script_output = NULL;
|
||||
char const *argv[5];
|
||||
const char *approver_script = rule->op_param;
|
||||
const char *target_file = apr_pstrmemdup(msr->mp, var->value, var->value_len);
|
||||
|
||||
static int msre_op_inspectFile_init(msre_rule *rule, char **error_msg) {
|
||||
char *filename = (char *)rule->op_param;
|
||||
|
||||
if (error_msg == NULL) return -1;
|
||||
*error_msg = NULL;
|
||||
|
||||
msr_log(msr, 4, "Executing %s to inspect %s.", approver_script, target_file);
|
||||
|
||||
argv[0] = approver_script;
|
||||
argv[1] = target_file;
|
||||
argv[2] = NULL;
|
||||
|
||||
if (apache2_exec(msr, approver_script, (const char **)argv, &script_output) <= 0) {
|
||||
*error_msg = apr_psprintf(msr->mp, "Execution of the approver script \"%s\" failed (invocation failed).",
|
||||
log_escape(msr->mp, approver_script));
|
||||
if ((filename == NULL)||(is_empty_string(filename))) {
|
||||
*error_msg = apr_psprintf(rule->ruleset->mp, "Operator @inspectFile requires parameter.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (script_output == NULL) {
|
||||
*error_msg = apr_psprintf(msr->mp, "Execution of the approver script \"%s\" failed (no output).",
|
||||
log_escape(msr->mp, approver_script));
|
||||
return -1;
|
||||
filename = resolve_relative_path(rule->ruleset->mp, rule->filename, filename);
|
||||
|
||||
#ifdef WITH_LUA
|
||||
// TODO Write & use string_ends(s, e).
|
||||
if (strlen(rule->op_param) > 4) {
|
||||
char *p = filename + strlen(filename) - 4;
|
||||
if ((p[0] == '.')&&(p[1] == 'l')&&(p[2] == 'u')&&(p[3] == 'a'))
|
||||
{
|
||||
msc_script *script = NULL;
|
||||
|
||||
/* Compile script. */
|
||||
*error_msg = lua_compile(&script, filename, rule->ruleset->mp);
|
||||
if (*error_msg != NULL) return -1;
|
||||
|
||||
rule->op_param_data = script;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rule->op_param_data == NULL) {
|
||||
// TODO Verify the script exists and that we have
|
||||
// the rights to execute it.
|
||||
}
|
||||
|
||||
if (script_output[0] != '1') {
|
||||
*error_msg = apr_psprintf(msr->mp, "File \"%s\" rejected by the approver script \"%s\": %s",
|
||||
log_escape(msr->mp, target_file), log_escape(msr->mp, approver_script),
|
||||
log_escape_nq(msr->mp, script_output));
|
||||
return 1; /* Match. */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* No match. */
|
||||
return 0;
|
||||
static int msre_op_inspectFile_execute(modsec_rec *msr, msre_rule *rule, msre_var *var,
|
||||
char **error_msg)
|
||||
{
|
||||
if (error_msg == NULL) return -1;
|
||||
*error_msg = NULL;
|
||||
|
||||
if (rule->op_param_data == NULL) {
|
||||
/* Execute externally, as native binary/shell script. */
|
||||
char *script_output = NULL;
|
||||
char const *argv[5];
|
||||
const char *approver_script = rule->op_param;
|
||||
const char *target_file = apr_pstrmemdup(msr->mp, var->value, var->value_len);
|
||||
|
||||
msr_log(msr, 4, "Executing %s to inspect %s.", approver_script, target_file);
|
||||
|
||||
argv[0] = approver_script;
|
||||
argv[1] = target_file;
|
||||
argv[2] = NULL;
|
||||
|
||||
if (apache2_exec(msr, approver_script, (const char **)argv, &script_output) <= 0) {
|
||||
*error_msg = apr_psprintf(msr->mp, "Execution of the approver script \"%s\" failed (invocation failed).",
|
||||
log_escape(msr->mp, approver_script));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (script_output == NULL) {
|
||||
*error_msg = apr_psprintf(msr->mp, "Execution of the approver script \"%s\" failed (no output).",
|
||||
log_escape(msr->mp, approver_script));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (script_output[0] != '1') {
|
||||
*error_msg = apr_psprintf(msr->mp, "File \"%s\" rejected by the approver script \"%s\": %s",
|
||||
log_escape(msr->mp, target_file), log_escape(msr->mp, approver_script),
|
||||
log_escape_nq(msr->mp, script_output));
|
||||
return 1; /* Match. */
|
||||
}
|
||||
|
||||
/* No match. */
|
||||
return 0;
|
||||
} else {
|
||||
/* Execute internally, as Lua script. */
|
||||
char *target = apr_pstrmemdup(msr->mp, var->value, var->value_len);
|
||||
msc_script *script = (msc_script *)rule->op_param_data;
|
||||
int rc;
|
||||
|
||||
rc = lua_execute(script, target, msr, rule, error_msg);
|
||||
if (rc < 0) {
|
||||
/* Error. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* validateByteRange */
|
||||
@@ -1867,7 +1922,7 @@ void msre_engine_register_default_operators(msre_engine *engine) {
|
||||
/* inspectFile */
|
||||
msre_engine_op_register(engine,
|
||||
"inspectFile",
|
||||
NULL,
|
||||
msre_op_inspectFile_init,
|
||||
msre_op_inspectFile_execute
|
||||
);
|
||||
|
||||
|
Reference in New Issue
Block a user