mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-15 23:55:03 +03:00
Adds support to the @rbl operator
This commit is contained in:
parent
4bdb4ed63a
commit
049e4eb69d
@ -49,6 +49,7 @@ class RulesProperties {
|
|||||||
RulesProperties()
|
RulesProperties()
|
||||||
: audit_log(NULL),
|
: audit_log(NULL),
|
||||||
m_debugLog(new DebugLog()),
|
m_debugLog(new DebugLog()),
|
||||||
|
m_httpbl_key(""),
|
||||||
remoteRulesActionOnFailed(AbortOnFailedRemoteRulesAction),
|
remoteRulesActionOnFailed(AbortOnFailedRemoteRulesAction),
|
||||||
requestBodyLimit(0),
|
requestBodyLimit(0),
|
||||||
requestBodyNoFilesLimit(0),
|
requestBodyNoFilesLimit(0),
|
||||||
@ -63,6 +64,7 @@ class RulesProperties {
|
|||||||
explicit RulesProperties(DebugLog *debugLog)
|
explicit RulesProperties(DebugLog *debugLog)
|
||||||
: audit_log(NULL),
|
: audit_log(NULL),
|
||||||
m_debugLog(debugLog),
|
m_debugLog(debugLog),
|
||||||
|
m_httpbl_key(""),
|
||||||
remoteRulesActionOnFailed(AbortOnFailedRemoteRulesAction),
|
remoteRulesActionOnFailed(AbortOnFailedRemoteRulesAction),
|
||||||
requestBodyLimit(0),
|
requestBodyLimit(0),
|
||||||
requestBodyNoFilesLimit(0),
|
requestBodyNoFilesLimit(0),
|
||||||
@ -207,6 +209,7 @@ class RulesProperties {
|
|||||||
|
|
||||||
DebugLog *m_debugLog;
|
DebugLog *m_debugLog;
|
||||||
|
|
||||||
|
std::string m_httpbl_key;
|
||||||
std::ostringstream parserError;
|
std::ostringstream parserError;
|
||||||
|
|
||||||
audit_log::AuditLog *audit_log;
|
audit_log::AuditLog *audit_log;
|
||||||
|
@ -15,6 +15,13 @@
|
|||||||
|
|
||||||
#include "operators/rbl.h"
|
#include "operators/rbl.h"
|
||||||
|
|
||||||
|
#include <modsecurity/rules.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "operators/operator.h"
|
#include "operators/operator.h"
|
||||||
@ -22,20 +29,198 @@
|
|||||||
namespace modsecurity {
|
namespace modsecurity {
|
||||||
namespace operators {
|
namespace operators {
|
||||||
|
|
||||||
bool Rbl::evaluate(Transaction *transaction, const std::string &str) {
|
|
||||||
/**
|
std::string Rbl::mapIpToAddress(std::string ipStr, Transaction *trans) {
|
||||||
* @todo Implement the operator Rbl.
|
std::string addr;
|
||||||
* Reference: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#rbl
|
unsigned int h0, h1, h2, h3;
|
||||||
*/
|
std::string key = trans->m_rules->m_httpbl_key;
|
||||||
|
|
||||||
|
if (sscanf(ipStr.c_str(), "%d.%d.%d.%d", &h0, &h1, &h2, &h3) != 4) {
|
||||||
|
debug(trans, 0, std::string("Failed to understand `" + ipStr +
|
||||||
|
"' as a valid IP address, assuming domain format input"));
|
||||||
|
|
||||||
|
addr = ipStr + "." + m_service;
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_demandsPassword && key.empty()) {
|
||||||
|
debug(trans, 0, std::string("Missing RBL key, cannot continue " \
|
||||||
|
"with the operator execution, please set the key using: " \
|
||||||
|
"SecHttpBlKey"));
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = std::to_string(h3) + "." +
|
||||||
|
std::to_string(h2) + "." +
|
||||||
|
std::to_string(h1) + "." +
|
||||||
|
std::to_string(h0) + "." +
|
||||||
|
m_service;
|
||||||
|
|
||||||
|
if (m_demandsPassword) {
|
||||||
|
addr = key + "." + addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Rbl::futherInfo_httpbl(struct sockaddr_in *sin, std::string ipStr,
|
||||||
|
Transaction *trans) {
|
||||||
|
char *respBl;
|
||||||
|
int first, days, score, type;
|
||||||
|
std::string ptype;
|
||||||
|
|
||||||
|
respBl = inet_ntoa(sin->sin_addr);
|
||||||
|
|
||||||
|
if (sscanf(respBl, "%d.%d.%d.%d", &first, &days, &score, &type) != 4) {
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " failed: bad response");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first != 127) {
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " failed: bad response");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
ptype = "Search Engine";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ptype = "Suspicious IP";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ptype = "Harvester IP";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ptype = "Suspicious harvester IP";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
ptype = "Comment spammer IP";
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
ptype = "Suspicious comment spammer IP";
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
ptype = "Harvester and comment spammer IP";
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
ptype = "Suspicious harvester comment spammer IP";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ptype = " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded. %s: " \
|
||||||
|
+ std::to_string(days) + " " \
|
||||||
|
"days since last activity, threat score " \
|
||||||
|
+ std::to_string(score));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Rbl::futherInfo_spamhaus(unsigned int high8bits, std::string ipStr,
|
||||||
|
Transaction *trans) {
|
||||||
|
switch (high8bits) {
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded " \
|
||||||
|
"(Static UBE sources).");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded " \
|
||||||
|
"(Illegal 3rd party exploits).");
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
case 11:
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded " \
|
||||||
|
"(Delivering unauthenticated SMTP email).");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Rbl::futherInfo_uribl(unsigned int high8bits, std::string ipStr,
|
||||||
|
Transaction *trans) {
|
||||||
|
switch (high8bits) {
|
||||||
|
case 2:
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded (BLACK).");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded (GREY).");
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded (RED).");
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded " \
|
||||||
|
"(BLACK,GREY,RED).");
|
||||||
|
break;
|
||||||
|
case 255:
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded " \
|
||||||
|
"(DNS IS BLOCKED).");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
debug(trans, 4, "RBL lookup of " + ipStr + " succeeded (WHITE).");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Rbl::furtherInfo(struct sockaddr_in *sin, std::string ipStr,
|
||||||
|
Transaction *trans) {
|
||||||
|
unsigned int high8bits = sin->sin_addr.s_addr >> 24;
|
||||||
|
|
||||||
|
switch (m_provider) {
|
||||||
|
case RblProvider::UnknownProvider:
|
||||||
|
debug(trans, 2, "RBL lookup of " + ipStr + " succeeded.");
|
||||||
|
break;
|
||||||
|
case RblProvider::httpbl:
|
||||||
|
futherInfo_httpbl(sin, ipStr, trans);
|
||||||
|
break;
|
||||||
|
case RblProvider::uribl:
|
||||||
|
futherInfo_uribl(high8bits, ipStr, trans);
|
||||||
|
break;
|
||||||
|
case RblProvider::spamhaus:
|
||||||
|
futherInfo_spamhaus(high8bits, ipStr, trans);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Rbl::evaluate(Transaction *transaction, const std::string &ipStr) {
|
||||||
|
struct addrinfo *info = NULL;
|
||||||
|
std::string host = mapIpToAddress(ipStr, transaction);
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (host.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = getaddrinfo(host.c_str(), NULL, NULL, &info);
|
||||||
|
|
||||||
|
if (rc != 0) {
|
||||||
|
if (info != NULL) {
|
||||||
|
freeaddrinfo(info);
|
||||||
|
}
|
||||||
|
debug(transaction, 5, "RBL lookup of " + ipStr + " failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr *addr = info->ai_addr;
|
||||||
|
struct sockaddr_in *sin = (struct sockaddr_in *) addr;
|
||||||
|
furtherInfo(sin, ipStr, transaction);
|
||||||
|
|
||||||
|
freeaddrinfo(info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rbl::Rbl(std::string op, std::string param, bool negation)
|
|
||||||
: Operator() {
|
|
||||||
this->op = op;
|
|
||||||
this->param = param;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace operators
|
} // namespace operators
|
||||||
} // namespace modsecurity
|
} // namespace modsecurity
|
||||||
|
@ -16,6 +16,12 @@
|
|||||||
#ifndef SRC_OPERATORS_RBL_H_
|
#ifndef SRC_OPERATORS_RBL_H_
|
||||||
#define SRC_OPERATORS_RBL_H_
|
#define SRC_OPERATORS_RBL_H_
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "operators/operator.h"
|
#include "operators/operator.h"
|
||||||
@ -27,9 +33,64 @@ namespace operators {
|
|||||||
|
|
||||||
class Rbl : public Operator {
|
class Rbl : public Operator {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum RblProvider {
|
||||||
|
/**
|
||||||
|
* UnknownProvider
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
UnknownProvider,
|
||||||
|
/**
|
||||||
|
* httpbl.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
httpbl,
|
||||||
|
/**
|
||||||
|
* uribl.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uribl,
|
||||||
|
/**
|
||||||
|
* spamhaus.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
spamhaus,
|
||||||
|
};
|
||||||
|
|
||||||
/** @ingroup ModSecurity_Operator */
|
/** @ingroup ModSecurity_Operator */
|
||||||
Rbl(std::string o, std::string p, bool i);
|
Rbl(std::string op, std::string param, bool negation)
|
||||||
|
: Operator(op, param, negation),
|
||||||
|
m_demandsPassword(false),
|
||||||
|
m_service(param) {
|
||||||
|
m_provider = RblProvider::UnknownProvider;
|
||||||
|
if (m_service == "httpbl.org") {
|
||||||
|
m_demandsPassword = true;
|
||||||
|
m_provider = RblProvider::httpbl;
|
||||||
|
} else if (m_service == "uribl.com") {
|
||||||
|
m_provider = RblProvider::httpbl;
|
||||||
|
} else if (m_service == "spamhaus.org") {
|
||||||
|
m_provider = RblProvider::httpbl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool evaluate(Transaction *transaction, const std::string &str) override;
|
bool evaluate(Transaction *transaction, const std::string &str) override;
|
||||||
|
|
||||||
|
std::string mapIpToAddress(std::string ipStr, Transaction *trans);
|
||||||
|
|
||||||
|
void futherInfo_httpbl(struct sockaddr_in *sin, std::string ipStr,
|
||||||
|
Transaction *trans);
|
||||||
|
void futherInfo_spamhaus(unsigned int high8bits, std::string ipStr,
|
||||||
|
Transaction *trans);
|
||||||
|
void futherInfo_uribl(unsigned int high8bits, std::string ipStr,
|
||||||
|
Transaction *trans);
|
||||||
|
void furtherInfo(struct sockaddr_in *sin, std::string ipStr,
|
||||||
|
Transaction *trans);
|
||||||
|
|
||||||
|
std::string m_service;
|
||||||
|
bool m_demandsPassword;
|
||||||
|
RblProvider m_provider;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace operators
|
} // namespace operators
|
||||||
|
Loading…
x
Reference in New Issue
Block a user