mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
Initial support for Lua script engine
This commit is contained in:
parent
1866a3a9eb
commit
a676f313c3
2
CHANGES
2
CHANGES
@ -2,6 +2,8 @@
|
|||||||
v3.0.????? - ?
|
v3.0.????? - ?
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
- Adds initial support for Lua engine.
|
||||||
|
[Issue #994 - @zimmerle]
|
||||||
- Adds support for @inspectFile operator.
|
- Adds support for @inspectFile operator.
|
||||||
[Issue #999 - @zimmerle, @victorhora]
|
[Issue #999 - @zimmerle, @victorhora]
|
||||||
- Adds support for RESOURCE variable collection.
|
- Adds support for RESOURCE variable collection.
|
||||||
|
@ -79,7 +79,7 @@ noinst_HEADERS = \
|
|||||||
|
|
||||||
|
|
||||||
ENGINES = \
|
ENGINES = \
|
||||||
engines/lua.cc
|
engine/lua.cc
|
||||||
|
|
||||||
|
|
||||||
VARIABLES = \
|
VARIABLES = \
|
||||||
|
377
src/engine/lua.cc
Normal file
377
src/engine/lua.cc
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
/*
|
||||||
|
* ModSecurity, http://www.modsecurity.org/
|
||||||
|
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||||
|
*
|
||||||
|
* You may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* If any of the files related to licensing are missing or if you have any
|
||||||
|
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||||
|
* directly using the email address security@modsecurity.org.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "modsecurity/modsecurity.h"
|
||||||
|
#include "src/engine/lua.h"
|
||||||
|
#include "src/utils/string.h"
|
||||||
|
#include "src/macro_expansion.h"
|
||||||
|
#include "modsecurity/transaction.h"
|
||||||
|
#include "modsecurity/collection/variable.h"
|
||||||
|
#include "src/variables/variable.h"
|
||||||
|
#include "src/variables/highest_severity.h"
|
||||||
|
#include "src/utils/string.h"
|
||||||
|
#include "src/actions/transformations/transformation.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace modsecurity {
|
||||||
|
namespace engine {
|
||||||
|
|
||||||
|
|
||||||
|
bool Lua::isCompatible(std::string script, Lua *l, std::string *error) {
|
||||||
|
std::string lua(".lua");
|
||||||
|
std::string err;
|
||||||
|
|
||||||
|
if (!(script.size() >= lua.size() &&
|
||||||
|
script.compare(script.size() - lua.size(), lua.size(), lua) == 0))
|
||||||
|
{
|
||||||
|
error->assign("Expecting a Lua script: " + script);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->load(script, &err) == false) {
|
||||||
|
error->assign("Problems load script: " + err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Lua::load(std::string script, std::string *err) {
|
||||||
|
lua_State *L = NULL;
|
||||||
|
L = luaL_newstate();
|
||||||
|
luaL_openlibs(L);
|
||||||
|
|
||||||
|
m_scriptName = script;
|
||||||
|
if (luaL_loadfile(L, script.c_str())) {
|
||||||
|
const char *luaerr = lua_tostring(L, -1);
|
||||||
|
err->assign("Failed to compile script '" + script + "");
|
||||||
|
if (luaerr) {
|
||||||
|
err->append(": " + *luaerr);
|
||||||
|
}
|
||||||
|
err->append(".");
|
||||||
|
lua_close(L);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_dump(L, Lua::blob_keeper, (void *)&m_blob, 0)) {
|
||||||
|
const char *luaerr = lua_tostring(L, -1);
|
||||||
|
err->assign("Failed to compile script '" + script + "");
|
||||||
|
if (luaerr) {
|
||||||
|
err->append(": " + *luaerr);
|
||||||
|
}
|
||||||
|
err->append(".");
|
||||||
|
lua_close(L);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lua_close(L);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Lua::blob_keeper(lua_State *L, const void *p, size_t sz, void *ud) {
|
||||||
|
LuaScriptBlob *lsb = static_cast<LuaScriptBlob *>(ud);
|
||||||
|
lsb->write(p, sz);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *Lua::blob_reader(lua_State *L, void *ud, size_t *size) {
|
||||||
|
LuaScriptBlob *lsb = static_cast<LuaScriptBlob *>(ud);
|
||||||
|
const char *data = lsb->read(size);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Lua::run(Transaction *t) {
|
||||||
|
std::string luaRet;
|
||||||
|
lua_State *L = luaL_newstate();
|
||||||
|
luaL_openlibs(L);
|
||||||
|
|
||||||
|
luaL_newmetatable(L, "luaL_msc");
|
||||||
|
lua_newtable(L);
|
||||||
|
|
||||||
|
lua_pushlightuserdata(L, (void *)t);
|
||||||
|
lua_setglobal(L, "__transaction");
|
||||||
|
|
||||||
|
luaL_setfuncs(L, mscLuaLib, 0);
|
||||||
|
lua_setglobal(L, "m");
|
||||||
|
|
||||||
|
int rc = lua_load(L, Lua::blob_reader, &m_blob, m_scriptName.c_str(),
|
||||||
|
NULL);
|
||||||
|
if (rc != LUA_OK) {
|
||||||
|
std::string e;
|
||||||
|
e.assign("Failed to execute lua script: " + m_scriptName + ". ");
|
||||||
|
switch (rc) {
|
||||||
|
case LUA_ERRSYNTAX:
|
||||||
|
e.assign("Syntax error. ");
|
||||||
|
break;
|
||||||
|
case LUA_ERRMEM:
|
||||||
|
e.assign("Memory error. ");
|
||||||
|
break;
|
||||||
|
case LUA_ERRGCMM:
|
||||||
|
e.assign("Garbage Collector error. ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e.append(lua_tostring(L, -1));
|
||||||
|
t->debug(2, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_pcall(L, 0, 0, 0)) {
|
||||||
|
std::string e;
|
||||||
|
const char *luaerr = lua_tostring(L, -1);
|
||||||
|
e.assign("Failed to execute lua script: " + m_scriptName \
|
||||||
|
+ " (before main)");
|
||||||
|
if (luaerr != NULL) {
|
||||||
|
e.append(" - ");
|
||||||
|
e.append(luaerr);
|
||||||
|
}
|
||||||
|
t->debug(2, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_setglobal(L, "modsec");
|
||||||
|
|
||||||
|
lua_getglobal(L, "main");
|
||||||
|
if (lua_pcall(L, 0, 1, 0)) {
|
||||||
|
std::string e;
|
||||||
|
const char *luaerr = lua_tostring(L, -1);
|
||||||
|
e.assign("Failed to execute lua script: " + m_scriptName + " (main)");
|
||||||
|
if (luaerr != NULL) {
|
||||||
|
e.append(" - ");
|
||||||
|
e.append(luaerr);
|
||||||
|
}
|
||||||
|
t->debug(2, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *a = (char *)lua_tostring(L, -1);
|
||||||
|
if (a != NULL) {
|
||||||
|
luaRet.assign(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
t->debug(9, "Returning from lua script: " + luaRet);
|
||||||
|
|
||||||
|
lua_pop(L, 1);
|
||||||
|
lua_close(L);
|
||||||
|
|
||||||
|
if (luaRet.size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Lua::log(lua_State *L) {
|
||||||
|
Transaction *t = NULL;
|
||||||
|
const char *text;
|
||||||
|
int level;
|
||||||
|
|
||||||
|
/* Retrieve parameters. */
|
||||||
|
level = luaL_checknumber(L, 1);
|
||||||
|
text = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
|
/* Retrieve msr. */
|
||||||
|
lua_getglobal(L, "__transaction");
|
||||||
|
t = (Transaction *)lua_topointer(L, -1);
|
||||||
|
|
||||||
|
/* Log message. */
|
||||||
|
if (t != NULL) {
|
||||||
|
t->debug(level, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Lua::getvar(lua_State *L) {
|
||||||
|
char *varname = NULL;
|
||||||
|
Transaction *t = NULL;
|
||||||
|
|
||||||
|
/* Retrieve parameters. */
|
||||||
|
varname = (char *)luaL_checkstring(L, 1);
|
||||||
|
|
||||||
|
lua_getglobal(L, "__transaction");
|
||||||
|
t = (Transaction *)lua_topointer(L, -1);
|
||||||
|
|
||||||
|
std::string var = Variables::Variable::stringMatchResolve(t, varname);
|
||||||
|
var = applyTransformations(L, t, 2, var);
|
||||||
|
|
||||||
|
if (var.size() == 0) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushlstring(L, var.c_str(), var.size());
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Lua::getvars(lua_State *L) {
|
||||||
|
char *varname = NULL;
|
||||||
|
Transaction *t = NULL;
|
||||||
|
std::vector<const collection::Variable *> l;
|
||||||
|
int idx = 1;
|
||||||
|
|
||||||
|
/* Retrieve parameters. */
|
||||||
|
varname = (char *)luaL_checkstring(L, 1);
|
||||||
|
|
||||||
|
lua_getglobal(L, "__transaction");
|
||||||
|
t = (Transaction *)lua_topointer(L, -1);
|
||||||
|
|
||||||
|
Variables::Variable::stringMatchResolveMulti(t, varname, &l);
|
||||||
|
|
||||||
|
lua_newtable(L);
|
||||||
|
for (auto i : l) {
|
||||||
|
lua_pushnumber(L, idx);
|
||||||
|
lua_newtable(L);
|
||||||
|
|
||||||
|
lua_pushstring(L, "name");
|
||||||
|
lua_pushlstring(L, i->m_key.c_str(), i->m_key.size());
|
||||||
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
lua_pushstring(L, "value");
|
||||||
|
lua_pushlstring(L, i->m_value.c_str(), i->m_value.size());
|
||||||
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
lua_settable(L, -3);
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Lua::setvar(lua_State *L) {
|
||||||
|
Transaction *t = NULL;
|
||||||
|
const char *var_value = NULL;
|
||||||
|
const char *var_name = NULL;
|
||||||
|
std::string vname;
|
||||||
|
std::string collection;
|
||||||
|
std::string variableName;
|
||||||
|
int nargs = lua_gettop(L);
|
||||||
|
char *chr = NULL;
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
|
lua_getglobal(L, "__transaction");
|
||||||
|
t = (Transaction *)lua_topointer(L, -1);
|
||||||
|
|
||||||
|
if (nargs != 2) {
|
||||||
|
t->debug(8, "m.setvar: Failed m.setvar funtion must has 2 arguments");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
var_value = luaL_checkstring(L, 2);
|
||||||
|
var_name = luaL_checkstring(L, 1);
|
||||||
|
|
||||||
|
lua_pop(L, 2);
|
||||||
|
|
||||||
|
if (var_value == NULL || var_name == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vname.assign(var_name);
|
||||||
|
pos = vname.find(".");
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
collection = std::string(vname, 0, pos);
|
||||||
|
collection = utils::string::toupper(collection);
|
||||||
|
variableName = std::string(vname, pos + 1,
|
||||||
|
std::string::npos);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
t->debug(8, "m.setvar: Must specify a collection using dot character" \
|
||||||
|
" - ie m.setvar(tx.myvar,mydata)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->m_collections.storeOrUpdateFirst(collection,
|
||||||
|
variableName, var_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string Lua::applyTransformations(lua_State *L, Transaction *t, int idx, std::string var) {
|
||||||
|
std::string newVar = var;
|
||||||
|
|
||||||
|
if (lua_isuserdata(L, idx) || lua_isnoneornil(L, idx)) {
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_istable(L, idx)) {
|
||||||
|
char *name = NULL;
|
||||||
|
int i, n = lua_rawlen(L, idx);
|
||||||
|
|
||||||
|
for (i = 1; i <= n; i++) {
|
||||||
|
lua_rawgeti(L, idx, i);
|
||||||
|
name = (char *)luaL_checkstring(L, -1);
|
||||||
|
|
||||||
|
/* A "none" means start over */
|
||||||
|
if (strcmp("none", name) == 0) {
|
||||||
|
newVar = var;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions::transformations::Transformation *tfn = actions::transformations::Transformation::instantiate("t:" + std::string(name));
|
||||||
|
// FIXME: transformation is not yet returning null.
|
||||||
|
if (tfn) {
|
||||||
|
newVar = tfn->evaluate(newVar, t);
|
||||||
|
} else {
|
||||||
|
t->debug(1, "SecRuleScript: Invalid transformation function: " + std::string(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_isstring(L, idx)) {
|
||||||
|
char *name = (char *)luaL_checkstring(L, idx);
|
||||||
|
|
||||||
|
actions::transformations::Transformation *tfn = actions::transformations::Transformation::instantiate("t:" + std::string(name));
|
||||||
|
// FIXME: transformation is not yet returning null.
|
||||||
|
if (tfn) {
|
||||||
|
newVar = tfn->evaluate(newVar, t);
|
||||||
|
} else {
|
||||||
|
t->debug(1, "SecRuleScript: Invalid transformation function: " + std::string(name));
|
||||||
|
}
|
||||||
|
return newVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->debug(8, "SecRuleScript: Transformation parameter must be a " \
|
||||||
|
"transformation name or array of transformation names, but found " \
|
||||||
|
"" + std::string(lua_typename(L, idx)) + " (type " \
|
||||||
|
+ std::to_string(lua_type(L, idx)) + ")");
|
||||||
|
|
||||||
|
return newVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace engines
|
||||||
|
} // namespace modsecurity
|
101
src/engine/lua.h
Normal file
101
src/engine/lua.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* ModSecurity, http://www.modsecurity.org/
|
||||||
|
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||||
|
*
|
||||||
|
* You may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* If any of the files related to licensing are missing or if you have any
|
||||||
|
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||||
|
* directly using the email address security@modsecurity.org.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WITH_LUA
|
||||||
|
#endif
|
||||||
|
#include <lua.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SRC_ENGINES_LUA_H_
|
||||||
|
#define SRC_ENGINES_LUA_H_
|
||||||
|
|
||||||
|
namespace modsecurity {
|
||||||
|
class Transaction;
|
||||||
|
namespace engine {
|
||||||
|
|
||||||
|
class LuaScriptBlob {
|
||||||
|
public:
|
||||||
|
LuaScriptBlob() :
|
||||||
|
m_data(NULL),
|
||||||
|
m_len(0) { };
|
||||||
|
|
||||||
|
~LuaScriptBlob() {
|
||||||
|
if (m_data) {
|
||||||
|
free(m_data);
|
||||||
|
m_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void write(const void *data, size_t len) {
|
||||||
|
unsigned char *d = NULL;
|
||||||
|
d = (unsigned char *)realloc((unsigned char *)m_data, len + m_len);
|
||||||
|
std::memcpy(d + m_len, data, len);
|
||||||
|
m_len = m_len + len;
|
||||||
|
m_data = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *read(size_t *len) {
|
||||||
|
*len = m_len;
|
||||||
|
return (const char *)m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char *m_data;
|
||||||
|
size_t m_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Lua {
|
||||||
|
public:
|
||||||
|
Lua() { };
|
||||||
|
|
||||||
|
bool load(std::string script, std::string *err);
|
||||||
|
int run(Transaction *t);
|
||||||
|
static bool isCompatible(std::string script, Lua *l, std::string *error);
|
||||||
|
|
||||||
|
static int blob_keeper(lua_State *L, const void *p, size_t sz, void *ud);
|
||||||
|
static const char *blob_reader(lua_State *L, void *us, size_t *size);
|
||||||
|
|
||||||
|
static int log(lua_State *L);
|
||||||
|
static int getvar(lua_State *L);
|
||||||
|
static int getvars(lua_State *L);
|
||||||
|
static int setvar(lua_State *L);
|
||||||
|
static std::string applyTransformations(lua_State *L, Transaction *t, int idx,
|
||||||
|
std::string var);
|
||||||
|
|
||||||
|
LuaScriptBlob m_blob;
|
||||||
|
std::string m_scriptName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const struct luaL_Reg mscLuaLib[] = {
|
||||||
|
{ "log", Lua::log },
|
||||||
|
{ "getvar", Lua::getvar },
|
||||||
|
{ "getvars", Lua::getvars },
|
||||||
|
{ "setvar", Lua::setvar },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace engines
|
||||||
|
} // namespace modsecurity
|
||||||
|
|
||||||
|
#endif // SRC_ENGINES_LUA_H_
|
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* ModSecurity, http://www.modsecurity.org/
|
|
||||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
|
||||||
*
|
|
||||||
* You may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* If any of the files related to licensing are missing or if you have any
|
|
||||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
|
||||||
* directly using the email address security@modsecurity.org.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "modsecurity/modsecurity.h"
|
|
||||||
#include "src/engines/lua.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_LUA
|
|
||||||
#include <lua.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SRC_ENGINES_LUA_H_
|
|
||||||
#define SRC_ENGINES_LUA_H_
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // SRC_ENGINES_LUA_H_
|
|
@ -28,6 +28,7 @@ namespace operators {
|
|||||||
bool InspectFile::init(const std::string ¶m2, std::string *error) {
|
bool InspectFile::init(const std::string ¶m2, std::string *error) {
|
||||||
std::istream *iss;
|
std::istream *iss;
|
||||||
std::string err;
|
std::string err;
|
||||||
|
std::string err_lua;
|
||||||
|
|
||||||
m_file = utils::find_resource(m_param, param2, &err);
|
m_file = utils::find_resource(m_param, param2, &err);
|
||||||
iss = new std::ifstream(m_file, std::ios::in);
|
iss = new std::ifstream(m_file, std::ios::in);
|
||||||
@ -38,37 +39,45 @@ bool InspectFile::init(const std::string ¶m2, std::string *error) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (engine::Lua::isCompatible(m_file, &m_lua, &err_lua) == true) {
|
||||||
|
m_isScript = true;
|
||||||
|
}
|
||||||
|
|
||||||
delete iss;
|
delete iss;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool InspectFile::evaluate(Transaction *transaction, const std::string &str) {
|
bool InspectFile::evaluate(Transaction *transaction, const std::string &str) {
|
||||||
FILE *in;
|
if (m_isScript) {
|
||||||
char buff[512];
|
return m_lua.run(transaction);
|
||||||
std::stringstream s;
|
} else {
|
||||||
std::string res;
|
FILE *in;
|
||||||
std::string openstr;
|
char buff[512];
|
||||||
|
std::stringstream s;
|
||||||
|
std::string res;
|
||||||
|
std::string openstr;
|
||||||
|
|
||||||
openstr.append(m_param);
|
openstr.append(m_param);
|
||||||
openstr.append(" ");
|
openstr.append(" ");
|
||||||
openstr.append(str);
|
openstr.append(str);
|
||||||
|
if (!(in = popen(openstr.c_str(), "r"))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(buff, sizeof(buff), in) != NULL) {
|
||||||
|
s << buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
pclose(in);
|
||||||
|
|
||||||
|
res.append(s.str());
|
||||||
|
if (res.size() > 1 && res.at(0) == '1') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(in = popen(openstr.c_str(), "r"))){
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (fgets(buff, sizeof(buff), in) != NULL) {
|
|
||||||
s << buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
pclose(in);
|
|
||||||
|
|
||||||
res.append(s.str());
|
|
||||||
if (res.size() > 1 && res.at(0) == '1') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "src/operators/operator.h"
|
#include "src/operators/operator.h"
|
||||||
|
#include "src/engine/lua.h"
|
||||||
|
|
||||||
|
|
||||||
namespace modsecurity {
|
namespace modsecurity {
|
||||||
@ -29,15 +30,19 @@ class InspectFile : public Operator {
|
|||||||
/** @ingroup ModSecurity_Operator */
|
/** @ingroup ModSecurity_Operator */
|
||||||
InspectFile(std::string o, std::string p, bool n)
|
InspectFile(std::string o, std::string p, bool n)
|
||||||
: Operator(o, p, n),
|
: Operator(o, p, n),
|
||||||
m_file("") { }
|
m_file(""),
|
||||||
|
m_isScript(false) { }
|
||||||
explicit InspectFile(std::string param)
|
explicit InspectFile(std::string param)
|
||||||
: Operator("InspectFile", param),
|
: Operator("InspectFile", param),
|
||||||
m_file("") { }
|
m_file(""),
|
||||||
|
m_isScript(false) { }
|
||||||
|
|
||||||
bool init(const std::string ¶m, std::string *error) override;
|
bool init(const std::string ¶m, std::string *error) override;
|
||||||
bool evaluate(Transaction *transaction, const std::string &str) override;
|
bool evaluate(Transaction *transaction, const std::string &str) override;
|
||||||
private:
|
private:
|
||||||
std::string m_file;
|
std::string m_file;
|
||||||
|
bool m_isScript;
|
||||||
|
engine::Lua m_lua;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace operators
|
} // namespace operators
|
||||||
|
@ -3937,7 +3937,7 @@ namespace yy {
|
|||||||
case 310:
|
case 310:
|
||||||
#line 2298 "seclang-parser.yy" // lalr1.cc:859
|
#line 2298 "seclang-parser.yy" // lalr1.cc:859
|
||||||
{
|
{
|
||||||
ACTION_NOT_SUPPORTED("Exec", yystack_[1].location);
|
//ACTION_CONTAINER($$, new actions::Exec($1));
|
||||||
}
|
}
|
||||||
#line 3943 "seclang-parser.cc" // lalr1.cc:859
|
#line 3943 "seclang-parser.cc" // lalr1.cc:859
|
||||||
break;
|
break;
|
||||||
|
@ -2296,7 +2296,7 @@ act:
|
|||||||
}
|
}
|
||||||
| ACTION_EXEC
|
| ACTION_EXEC
|
||||||
{
|
{
|
||||||
ACTION_NOT_SUPPORTED("Exec", @0);
|
//ACTION_CONTAINER($$, new actions::Exec($1));
|
||||||
}
|
}
|
||||||
| ACTION_EXPIRE_VAR
|
| ACTION_EXPIRE_VAR
|
||||||
{
|
{
|
||||||
|
@ -86,6 +86,487 @@ class Variable {
|
|||||||
|
|
||||||
static std::string to_s(std::vector<Variable *> *variables);
|
static std::string to_s(std::vector<Variable *> *variables);
|
||||||
|
|
||||||
|
static inline bool compareStrNoCase(const std::string &a, const std::string &b) {
|
||||||
|
return a.size() == b.size()
|
||||||
|
&& std::equal(a.begin(), a.end(), b.begin(),
|
||||||
|
[](char aa, char bb) {
|
||||||
|
return toupper(aa) == bb;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
static void stringMatchResolveMulti(Transaction *transaction, const std::string &variable,
|
||||||
|
std::vector<const collection::Variable *> *l) {
|
||||||
|
size_t collection = variable.find(".");
|
||||||
|
if (collection == std::string::npos) {
|
||||||
|
collection = variable.find(":");
|
||||||
|
}
|
||||||
|
if (collection == std::string::npos) {
|
||||||
|
if (compareStrNoCase(variable, "RESPONSE_CONTENT_TYPE")) {
|
||||||
|
transaction->m_variableResponseContentType.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "ARGS_COMBINED_SIZE")) {
|
||||||
|
transaction->m_variableARGScombinedSize.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "AUTH_TYPE")) {
|
||||||
|
transaction->m_variableAuthType.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "FILES_COMBINED_SIZE")) {
|
||||||
|
transaction->m_variableFilesCombinedSize.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "FULL_REQUEST")) {
|
||||||
|
transaction->m_variableFullRequest.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "FULL_REQUEST_LENGTH")) {
|
||||||
|
transaction->m_variableFullRequestLength.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "INBOUND_DATA_ERROR")) {
|
||||||
|
transaction->m_variableInboundDataError.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MATCHED_VAR")) {
|
||||||
|
transaction->m_variableMatchedVar.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MATCHED_VAR_NAME")) {
|
||||||
|
transaction->m_variableMatchedVarName.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_CRLF_LF_LINES")) {
|
||||||
|
transaction->m_variableMultipartCrlfLFLines.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_DATA_AFTER")) {
|
||||||
|
transaction->m_variableMultipartDataAfter.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_FILE_LIMIT_EXCEEDED")) {
|
||||||
|
transaction->m_variableMultipartFileLimitExceeded.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_STRICT_ERROR")) {
|
||||||
|
transaction->m_variableMultipartStrictError.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_HEADER_FOLDING")) {
|
||||||
|
transaction->m_variableMultipartHeaderFolding.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_INVALID_QUOTING")) {
|
||||||
|
transaction->m_variableMultipartInvalidQuoting.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_INVALID_HEADER_FOLDING")) {
|
||||||
|
transaction->m_variableMultipartInvalidHeaderFolding.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_UNMATCHED_BOUNDARY")) {
|
||||||
|
transaction->m_variableMultipartUnmatchedBoundary.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "OUTBOUND_DATA_ERROR")) {
|
||||||
|
transaction->m_variableOutboundDataError.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "PATH_INFO")) {
|
||||||
|
transaction->m_variablePathInfo.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "QUERY_STRING")) {
|
||||||
|
transaction->m_variableQueryString.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REMOTE_ADDR")) {
|
||||||
|
transaction->m_variableRemoteAddr.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REMOTE_HOST")) {
|
||||||
|
transaction->m_variableRemoteHost.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REMOTE_PORT")) {
|
||||||
|
transaction->m_variableRemotePort.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQBODY_ERROR")) {
|
||||||
|
transaction->m_variableReqbodyError.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQBODY_ERROR_MSG")) {
|
||||||
|
transaction->m_variableReqbodyErrorMsg.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQBODY_PROCESSOR_ERROR_MSG")) {
|
||||||
|
transaction->m_variableReqbodyProcessorErrorMsg.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQBODY_PROCESSOR_ERROR")) {
|
||||||
|
transaction->m_variableReqbodyProcessorError.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQBODY_PROCESSOR")) {
|
||||||
|
transaction->m_variableReqbodyProcessor.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_BASENAME")) {
|
||||||
|
transaction->m_variableRequestBasename.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_BODY")) {
|
||||||
|
transaction->m_variableRequestBody.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_BODY_LENGTH")) {
|
||||||
|
transaction->m_variableRequestBodyLength.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_FILENAME")) {
|
||||||
|
transaction->m_variableRequestFilename.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_LINE")) {
|
||||||
|
transaction->m_variableRequestLine.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_METHOD")) {
|
||||||
|
transaction->m_variableRequestMethod.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_PROTOCOL")) {
|
||||||
|
transaction->m_variableRequestProtocol.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_URI")) {
|
||||||
|
transaction->m_variableRequestURI.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_URI_RAW")) {
|
||||||
|
transaction->m_variableRequestURIRaw.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESOURCE")) {
|
||||||
|
transaction->m_variableResource.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESPONSE_BODY")) {
|
||||||
|
transaction->m_variableResponseBody.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESPONSE_CONTENT_LENGTH")) {
|
||||||
|
transaction->m_variableResponseContentLength.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESPONSE_PROTOCOL")) {
|
||||||
|
transaction->m_variableResponseProtocol.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESPONSE_STATUS")) {
|
||||||
|
transaction->m_variableResponseStatus.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "SERVER_ADDR")) {
|
||||||
|
transaction->m_variableServerAddr.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "SERVER_NAME")) {
|
||||||
|
transaction->m_variableServerName.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "SERVER_PORT")) {
|
||||||
|
transaction->m_variableServerPort.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "SESSIONID")) {
|
||||||
|
transaction->m_variableSessionID.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "UNIQUE_ID")) {
|
||||||
|
transaction->m_variableUniqueID.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "URLENCODED_ERROR")) {
|
||||||
|
transaction->m_variableUrlEncodedError.evaluate(l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "USERID")) {
|
||||||
|
transaction->m_variableUserID.evaluate(l);
|
||||||
|
} else {
|
||||||
|
transaction->m_collections.resolveMultiMatches(
|
||||||
|
variable, l);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::string col = std::string(variable, 0, collection);
|
||||||
|
std::string var = std::string(variable, collection + 1,
|
||||||
|
variable.length() - (collection + 1));
|
||||||
|
if (compareStrNoCase(col, "ARGS")) {
|
||||||
|
transaction->m_variableArgs.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "ARGS_NAMES")) {
|
||||||
|
transaction->m_variableArgsNames.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "ARGS_GET_NAMES")) {
|
||||||
|
transaction->m_variableArgsGetNames.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "ARGS_POST_NAMES")) {
|
||||||
|
transaction->m_variableArgsPostNames.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "RULE")) {
|
||||||
|
transaction->m_variableRule.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "ARGS_GET")) {
|
||||||
|
transaction->m_variableArgsGet.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "ARGS_POST")) {
|
||||||
|
transaction->m_variableArgsPost.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "FILES_SIZES")) {
|
||||||
|
transaction->m_variableFilesSizes.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "FILES_NAMES")) {
|
||||||
|
transaction->m_variableFilesNames.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "FILES_TMP_CONTENT")) {
|
||||||
|
transaction->m_variableFilesTmpContent.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "MULTIPART_FILENAME")) {
|
||||||
|
transaction->m_variableMultiPartFileName.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "MULTIPART_NAME")) {
|
||||||
|
transaction->m_variableMultiPartName.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "MATCHED_VARS_NAMES")) {
|
||||||
|
transaction->m_variableMatchedVarsNames.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "MATCHED_VARS")) {
|
||||||
|
transaction->m_variableMatchedVars.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "FILES")) {
|
||||||
|
transaction->m_variableFiles.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "REQUEST_COOKIES")) {
|
||||||
|
transaction->m_variableRequestCookies.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "REQUEST_HEADERS")) {
|
||||||
|
transaction->m_variableRequestHeaders.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_HEADERS_NAMES")) {
|
||||||
|
transaction->m_variableRequestHeadersNames.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "RESPONSE_HEADERS")) {
|
||||||
|
transaction->m_variableResponseHeaders.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESPONSE_HEADERS_NAMES")) {
|
||||||
|
transaction->m_variableResponseHeadersNames.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "GEO")) {
|
||||||
|
transaction->m_variableGeo.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "REQUEST_COOKIES_NAMES")) {
|
||||||
|
transaction->m_variableRequestCookiesNames.resolve(var, l);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "FILES_TMPNAMES")) {
|
||||||
|
transaction->m_variableFilesTmpNames.resolve(var, l);
|
||||||
|
} else {
|
||||||
|
transaction->m_collections.resolveMultiMatches(col,
|
||||||
|
var, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string stringMatchResolve(Transaction *transaction, const std::string &variable) {
|
||||||
|
std::unique_ptr<std::string> variableValue = nullptr;
|
||||||
|
size_t collection = variable.find(".");
|
||||||
|
if (collection == std::string::npos) {
|
||||||
|
collection = variable.find(":");
|
||||||
|
}
|
||||||
|
if (collection == std::string::npos) {
|
||||||
|
if (compareStrNoCase(variable, "RESPONSE_CONTENT_TYPE")) {
|
||||||
|
variableValue = transaction->m_variableResponseContentType.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "ARGS_COMBINED_SIZE")) {
|
||||||
|
variableValue = transaction->m_variableARGScombinedSize.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "AUTH_TYPE")) {
|
||||||
|
variableValue = transaction->m_variableAuthType.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "FILES_COMBINED_SIZE")) {
|
||||||
|
variableValue = transaction->m_variableFilesCombinedSize.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "FULL_REQUEST")) {
|
||||||
|
variableValue = transaction->m_variableFullRequest.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "FULL_REQUEST_LENGTH")) {
|
||||||
|
variableValue = transaction->m_variableFullRequestLength.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "INBOUND_DATA_ERROR")) {
|
||||||
|
variableValue = transaction->m_variableInboundDataError.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MATCHED_VAR")) {
|
||||||
|
variableValue = transaction->m_variableMatchedVar.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MATCHED_VAR_NAME")) {
|
||||||
|
variableValue = transaction->m_variableMatchedVarName.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_CRLF_LF_LINES")) {
|
||||||
|
variableValue = transaction->m_variableMultipartCrlfLFLines.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_DATA_AFTER")) {
|
||||||
|
variableValue = transaction->m_variableMultipartDataAfter.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_FILE_LIMIT_EXCEEDED")) {
|
||||||
|
variableValue = transaction->m_variableMultipartFileLimitExceeded.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_STRICT_ERROR")) {
|
||||||
|
variableValue = transaction->m_variableMultipartStrictError.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_HEADER_FOLDING")) {
|
||||||
|
variableValue = transaction->m_variableMultipartHeaderFolding.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_INVALID_QUOTING")) {
|
||||||
|
variableValue = transaction->m_variableMultipartInvalidQuoting.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_INVALID_HEADER_FOLDING")) {
|
||||||
|
variableValue = transaction->m_variableMultipartInvalidHeaderFolding.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "MULTIPART_UNMATCHED_BOUNDARY")) {
|
||||||
|
variableValue = transaction->m_variableMultipartUnmatchedBoundary.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "OUTBOUND_DATA_ERROR")) {
|
||||||
|
variableValue = transaction->m_variableOutboundDataError.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "PATH_INFO")) {
|
||||||
|
variableValue = transaction->m_variablePathInfo.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "QUERY_STRING")) {
|
||||||
|
variableValue = transaction->m_variableQueryString.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REMOTE_ADDR")) {
|
||||||
|
variableValue = transaction->m_variableRemoteAddr.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REMOTE_HOST")) {
|
||||||
|
variableValue = transaction->m_variableRemoteHost.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REMOTE_PORT")) {
|
||||||
|
variableValue = transaction->m_variableRemotePort.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQBODY_ERROR")) {
|
||||||
|
variableValue = transaction->m_variableReqbodyError.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQBODY_ERROR_MSG")) {
|
||||||
|
variableValue = transaction->m_variableReqbodyErrorMsg.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQBODY_PROCESSOR_ERROR_MSG")) {
|
||||||
|
variableValue = transaction->m_variableReqbodyProcessorErrorMsg.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQBODY_PROCESSOR_ERROR")) {
|
||||||
|
variableValue = transaction->m_variableReqbodyProcessorError.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQBODY_PROCESSOR")) {
|
||||||
|
variableValue = transaction->m_variableReqbodyProcessor.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_BASENAME")) {
|
||||||
|
variableValue = transaction->m_variableRequestBasename.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_BODY")) {
|
||||||
|
variableValue = transaction->m_variableRequestBody.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_BODY_LENGTH")) {
|
||||||
|
variableValue = transaction->m_variableRequestBodyLength.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_FILENAME")) {
|
||||||
|
variableValue = transaction->m_variableRequestFilename.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_LINE")) {
|
||||||
|
variableValue = transaction->m_variableRequestLine.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_METHOD")) {
|
||||||
|
variableValue = transaction->m_variableRequestMethod.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_PROTOCOL")) {
|
||||||
|
variableValue = transaction->m_variableRequestProtocol.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_URI")) {
|
||||||
|
variableValue = transaction->m_variableRequestURI.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_URI_RAW")) {
|
||||||
|
variableValue = transaction->m_variableRequestURIRaw.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESOURCE")) {
|
||||||
|
variableValue = transaction->m_variableResource.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESPONSE_BODY")) {
|
||||||
|
variableValue = transaction->m_variableResponseBody.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESPONSE_CONTENT_LENGTH")) {
|
||||||
|
variableValue = transaction->m_variableResponseContentLength.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESPONSE_PROTOCOL")) {
|
||||||
|
variableValue = transaction->m_variableResponseProtocol.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESPONSE_STATUS")) {
|
||||||
|
variableValue = transaction->m_variableResponseStatus.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "SERVER_ADDR")) {
|
||||||
|
variableValue = transaction->m_variableServerAddr.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "SERVER_NAME")) {
|
||||||
|
variableValue = transaction->m_variableServerName.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "SERVER_PORT")) {
|
||||||
|
variableValue = transaction->m_variableServerPort.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "SESSIONID")) {
|
||||||
|
variableValue = transaction->m_variableSessionID.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "UNIQUE_ID")) {
|
||||||
|
variableValue = transaction->m_variableUniqueID.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "URLENCODED_ERROR")) {
|
||||||
|
variableValue = transaction->m_variableUrlEncodedError.resolveFirst();
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "USERID")) {
|
||||||
|
variableValue = transaction->m_variableUserID.resolveFirst();
|
||||||
|
} else {
|
||||||
|
variableValue = transaction->m_collections.resolveFirst(
|
||||||
|
variable);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::string col = std::string(variable, 0, collection);
|
||||||
|
std::string var = std::string(variable, collection + 1,
|
||||||
|
variable.length() - (collection + 1));
|
||||||
|
if (compareStrNoCase(col, "ARGS")) {
|
||||||
|
variableValue = transaction->m_variableArgs.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "ARGS_NAMES")) {
|
||||||
|
variableValue = transaction->m_variableArgsNames.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "ARGS_GET_NAMES")) {
|
||||||
|
variableValue = transaction->m_variableArgsGetNames.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "ARGS_POST_NAMES")) {
|
||||||
|
variableValue = transaction->m_variableArgsPostNames.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "RULE")) {
|
||||||
|
variableValue = transaction->m_variableRule.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "ARGS_GET")) {
|
||||||
|
variableValue = transaction->m_variableArgsGet.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "ARGS_POST")) {
|
||||||
|
variableValue = transaction->m_variableArgsPost.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "FILES_SIZES")) {
|
||||||
|
variableValue = transaction->m_variableFilesSizes.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "FILES_NAMES")) {
|
||||||
|
variableValue = transaction->m_variableFilesNames.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "FILES_TMP_CONTENT")) {
|
||||||
|
variableValue = transaction->m_variableFilesTmpContent.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "MULTIPART_FILENAME")) {
|
||||||
|
variableValue = transaction->m_variableMultiPartFileName.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "MULTIPART_NAME")) {
|
||||||
|
variableValue = transaction->m_variableMultiPartName.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "MATCHED_VARS_NAMES")) {
|
||||||
|
variableValue = transaction->m_variableMatchedVarsNames.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "MATCHED_VARS")) {
|
||||||
|
variableValue = transaction->m_variableMatchedVars.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "FILES")) {
|
||||||
|
variableValue = transaction->m_variableFiles.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "REQUEST_COOKIES")) {
|
||||||
|
variableValue = transaction->m_variableRequestCookies.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "REQUEST_HEADERS")) {
|
||||||
|
variableValue = transaction->m_variableRequestHeaders.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "REQUEST_HEADERS_NAMES")) {
|
||||||
|
variableValue = transaction->m_variableRequestHeadersNames.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "RESPONSE_HEADERS")) {
|
||||||
|
variableValue = transaction->m_variableResponseHeaders.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(variable, "RESPONSE_HEADERS_NAMES")) {
|
||||||
|
variableValue = transaction->m_variableResponseHeadersNames.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "GEO")) {
|
||||||
|
variableValue = transaction->m_variableGeo.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "REQUEST_COOKIES_NAMES")) {
|
||||||
|
variableValue = transaction->m_variableRequestCookiesNames.resolveFirst(var);
|
||||||
|
}
|
||||||
|
else if (compareStrNoCase(col, "FILES_TMPNAMES")) {
|
||||||
|
variableValue = transaction->m_variableFilesTmpNames.resolveFirst(var);
|
||||||
|
} else {
|
||||||
|
variableValue = transaction->m_collections.resolveFirst(col,
|
||||||
|
var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::string(*variableValue.get());
|
||||||
|
}
|
||||||
|
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
std::string m_collectionName;
|
std::string m_collectionName;
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ unit_tests_LDADD = \
|
|||||||
$(YAJL_LDFLAGS) $(YAJL_LDADD) \
|
$(YAJL_LDFLAGS) $(YAJL_LDADD) \
|
||||||
$(LMDB_LDFLAGS) $(LMDB_LDADD) \
|
$(LMDB_LDFLAGS) $(LMDB_LDADD) \
|
||||||
$(SSDEEP_LDFLAGS) $(SSDEEP_LDADD) \
|
$(SSDEEP_LDFLAGS) $(SSDEEP_LDADD) \
|
||||||
|
$(LUA_LDFLAGS) $(LUA_LDADD) \
|
||||||
$(LIBXML2_LDADD) \
|
$(LIBXML2_LDADD) \
|
||||||
$(GLOBAL_LDADD)
|
$(GLOBAL_LDADD)
|
||||||
|
|
||||||
@ -82,6 +83,7 @@ regression_tests_LDADD = \
|
|||||||
$(YAJL_LDFLAGS) $(YAJL_LDADD) \
|
$(YAJL_LDFLAGS) $(YAJL_LDADD) \
|
||||||
$(LMDB_LDFLAGS) $(LMDB_LDADD) \
|
$(LMDB_LDFLAGS) $(LMDB_LDADD) \
|
||||||
$(SSDEEP_LDFLAGS) $(SSDEEP_LDADD) \
|
$(SSDEEP_LDFLAGS) $(SSDEEP_LDADD) \
|
||||||
|
$(LUA_LDFLAGS) $(LUA_LDADD) \
|
||||||
$(LIBXML2_LDADD) \
|
$(LIBXML2_LDADD) \
|
||||||
$(GLOBAL_LDADD)
|
$(GLOBAL_LDADD)
|
||||||
|
|
||||||
@ -118,6 +120,7 @@ rules_optimization_LDADD = \
|
|||||||
$(YAJL_LDFLAGS) $(YAJL_LDADD) \
|
$(YAJL_LDFLAGS) $(YAJL_LDADD) \
|
||||||
$(LMDB_LDFLAGS) $(LMDB_LDADD) \
|
$(LMDB_LDFLAGS) $(LMDB_LDADD) \
|
||||||
$(SSDEEP_LDFLAGS) $(SSDEEP_LDADD) \
|
$(SSDEEP_LDFLAGS) $(SSDEEP_LDADD) \
|
||||||
|
$(LUA_LDFLAGS) $(LUA_LDADD) \
|
||||||
$(LIBXML2_LDADD) \
|
$(LIBXML2_LDADD) \
|
||||||
$(GLOBAL_LDADD)
|
$(GLOBAL_LDADD)
|
||||||
|
|
||||||
|
20
test/test-cases/data/match-getvar-transformation.lua
Normal file
20
test/test-cases/data/match-getvar-transformation.lua
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
function main()
|
||||||
|
ret = nil
|
||||||
|
|
||||||
|
var = m.getvar("tx.test");
|
||||||
|
if var == nil then
|
||||||
|
m.log(9, "Don't know what to say...");
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
if var == "FELIPE"
|
||||||
|
m.log(9, "Ops.");
|
||||||
|
elseif var == "felipe"
|
||||||
|
m.log(9, "Just fine.");
|
||||||
|
ret ="ok";
|
||||||
|
else
|
||||||
|
m.log(9, "Really?");
|
||||||
|
end
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
19
test/test-cases/data/match-getvar.lua
Normal file
19
test/test-cases/data/match-getvar.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
function main()
|
||||||
|
ret = nil
|
||||||
|
|
||||||
|
num = m.getvar("tx.test");
|
||||||
|
if num == nil then
|
||||||
|
m.log(9, "Don't know what to say about this so called number.");
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
num = tonumber(num)
|
||||||
|
|
||||||
|
if num > 1 then
|
||||||
|
m.log(9, "Number is bigger than one.");
|
||||||
|
ret = "Whee :)"
|
||||||
|
else
|
||||||
|
m.log(9, "Really?");
|
||||||
|
end
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
21
test/test-cases/data/match-getvars.lua
Normal file
21
test/test-cases/data/match-getvars.lua
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
function dump(o)
|
||||||
|
if type(o) == 'table' then
|
||||||
|
local s = '{ '
|
||||||
|
for k,v in pairs(o) do
|
||||||
|
if type(k) ~= 'number' then k = '"'..k..'"' end
|
||||||
|
s = s .. '['..k..'] = ' .. dump(v) .. ','
|
||||||
|
end
|
||||||
|
return s .. '} '
|
||||||
|
else
|
||||||
|
return tostring(o)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function main()
|
||||||
|
ret = nil
|
||||||
|
m.log(9, "Here I am");
|
||||||
|
z = m.getvars("QUERY_STRING");
|
||||||
|
m.log(9, "Z: " .. dump(z))
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
4
test/test-cases/data/match-log.lua
Normal file
4
test/test-cases/data/match-log.lua
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
function main()
|
||||||
|
m.log(9, "echo 123");
|
||||||
|
return "Lua script matched.";
|
||||||
|
end
|
5
test/test-cases/data/match-set.lua
Normal file
5
test/test-cases/data/match-set.lua
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
function main()
|
||||||
|
m.log(9, "echo 123");
|
||||||
|
m.setvar("tx.test", "whee");
|
||||||
|
return "Lua script matched.";
|
||||||
|
end
|
3
test/test-cases/data/match.lua
Normal file
3
test/test-cases/data/match.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
function main()
|
||||||
|
return "Lua script matched.";
|
||||||
|
end
|
@ -112,5 +112,198 @@
|
|||||||
"SecRuleEngine On",
|
"SecRuleEngine On",
|
||||||
"SecRule ARGS:res \"@inspectFile /bin/echo\" \"id:1,phase:2,pass,t:trim\""
|
"SecRule ARGS:res \"@inspectFile /bin/echo\" \"id:1,phase:2,pass,t:trim\""
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"Testing Operator :: @inspectFile - lua (1/1)",
|
||||||
|
"client":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":123
|
||||||
|
},
|
||||||
|
"server":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":80
|
||||||
|
},
|
||||||
|
"request":{
|
||||||
|
"headers":{
|
||||||
|
"Host":"localhost",
|
||||||
|
"User-Agent":"curl/7.38.0",
|
||||||
|
"Accept":"*/*",
|
||||||
|
"Content-Length": "27",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
},
|
||||||
|
"uri":"/whee?res=whee",
|
||||||
|
"method":"GET",
|
||||||
|
"body": [ ]
|
||||||
|
},
|
||||||
|
"response":{
|
||||||
|
"headers":{},
|
||||||
|
"body":[
|
||||||
|
"no need."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expected":{
|
||||||
|
"debug_log":"Rule returned 1."
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecRule ARGS:res \"@inspectFile test-cases/data/match.lua\" \"id:1,phase:2,pass,t:trim\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"Testing Operator :: @inspectFile - lua (2/2)",
|
||||||
|
"client":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":123
|
||||||
|
},
|
||||||
|
"server":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":80
|
||||||
|
},
|
||||||
|
"request":{
|
||||||
|
"headers":{
|
||||||
|
"Host":"localhost",
|
||||||
|
"User-Agent":"curl/7.38.0",
|
||||||
|
"Accept":"*/*",
|
||||||
|
"Content-Length": "27",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
},
|
||||||
|
"uri":"/whee?res=whee",
|
||||||
|
"method":"GET",
|
||||||
|
"body": [ ]
|
||||||
|
},
|
||||||
|
"response":{
|
||||||
|
"headers":{},
|
||||||
|
"body":[
|
||||||
|
"no need."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expected":{
|
||||||
|
"debug_log":"echo 123"
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecRule ARGS:res \"@inspectFile test-cases/data/match-log.lua\" \"id:1,phase:2,pass,t:trim\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"Testing Operator :: @inspectFile - lua (3/3)",
|
||||||
|
"client":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":123
|
||||||
|
},
|
||||||
|
"server":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":80
|
||||||
|
},
|
||||||
|
"request":{
|
||||||
|
"headers":{
|
||||||
|
"Host":"localhost",
|
||||||
|
"User-Agent":"curl/7.38.0",
|
||||||
|
"Accept":"*/*",
|
||||||
|
"Content-Length": "27",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
},
|
||||||
|
"uri":"/whee?res=whee",
|
||||||
|
"method":"GET",
|
||||||
|
"body": [ ]
|
||||||
|
},
|
||||||
|
"response":{
|
||||||
|
"headers":{},
|
||||||
|
"body":[
|
||||||
|
"no need."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expected":{
|
||||||
|
"debug_log":"Target value: \"whee\" "
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecRule ARGS:res \"@inspectFile test-cases/data/match-set.lua\" \"id:1,phase:2,pass,t:trim\"",
|
||||||
|
"SecRule TX:test \"whee\" \"id:2,phase:2,pass,t:trim\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"Testing Operator :: @inspectFile - lua (4/4)",
|
||||||
|
"client":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":123
|
||||||
|
},
|
||||||
|
"server":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":80
|
||||||
|
},
|
||||||
|
"request":{
|
||||||
|
"headers":{
|
||||||
|
"Host":"localhost",
|
||||||
|
"User-Agent":"curl/7.38.0",
|
||||||
|
"Accept":"*/*",
|
||||||
|
"Content-Length": "27",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
},
|
||||||
|
"uri":"/whee?res=whee",
|
||||||
|
"method":"GET",
|
||||||
|
"body": [ ]
|
||||||
|
},
|
||||||
|
"response":{
|
||||||
|
"headers":{},
|
||||||
|
"body":[
|
||||||
|
"no need."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expected":{
|
||||||
|
"debug_log":"Number is bigger than one."
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecRule ARGS \".\" \"id:2,phase:2,setvar:tx.test=2\"",
|
||||||
|
"SecRule ARGS:res \"@inspectFile test-cases/data/match-getvar.lua\" \"id:1,phase:2,pass,t:trim\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"Testing Operator :: @inspectFile - lua (5/5)",
|
||||||
|
"client":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":123
|
||||||
|
},
|
||||||
|
"server":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":80
|
||||||
|
},
|
||||||
|
"request":{
|
||||||
|
"headers":{
|
||||||
|
"Host":"localhost",
|
||||||
|
"User-Agent":"curl/7.38.0",
|
||||||
|
"Accept":"*/*",
|
||||||
|
"Content-Length": "27",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
},
|
||||||
|
"uri":"/whee?res=whee&z=z&d=e",
|
||||||
|
"method":"GET",
|
||||||
|
"body": [ ]
|
||||||
|
},
|
||||||
|
"response":{
|
||||||
|
"headers":{},
|
||||||
|
"body":[
|
||||||
|
"no need."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expected":{
|
||||||
|
"debug_log":"Z: \\{ \\[1\\] = \\{ \\[\"value\"\\] = res=whee&z=z&d=e,\\[\"name\"\\] = QUERY_STRING,\\} ,\\}"
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecRule QUERY_STRING \".\" \"id:2,phase:2,setvar:tx.test=2\"",
|
||||||
|
"SecRule ARGS:res \"@inspectFile test-cases/data/match-getvars.lua\" \"id:1,phase:2,pass,t:trim\""
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user