Feb 22nd 2023 update

This commit is contained in:
Ned Wright
2023-02-22 17:20:21 +00:00
parent fd6239f44a
commit 38e6e1bbcf
17 changed files with 234 additions and 76 deletions

View File

@@ -124,7 +124,10 @@ private:
map<string, HealthCheckStatus> field_types_status;
};
class setAgentUninstall : public ServerRest
class SetAgentUninstall
:
public ServerRest,
Singleton::Consume<I_AgentDetails>
{
public:
void
@@ -132,11 +135,13 @@ public:
{
dbgTrace(D_ORCHESTRATOR) << "Send 'agent uninstall process started' log to fog";
setConfiguration(false, "Logging", "Enable bulk of logs");
string profile_id = Singleton::Consume<I_AgentDetails>::by<SetAgentUninstall>()->getProfileId();
LogGen log (
"Agent started uninstall process",
Audience::INTERNAL,
Severity::INFO,
Priority::URGENT,
LogField("profileId", profile_id),
LogField("issuingEngine", "agentUninstallProvider"),
Tags::ORCHESTRATOR
);
@@ -167,7 +172,7 @@ public:
auto rest = Singleton::Consume<I_RestApi>::by<OrchestrationComp>();
rest->addRestCall<getStatusRest>(RestAction::SHOW, "orchestration-status");
rest->addRestCall<AddProxyRest>(RestAction::ADD, "proxy");
rest->addRestCall<setAgentUninstall>(RestAction::SET, "agent-uninstall");
rest->addRestCall<SetAgentUninstall>(RestAction::SET, "agent-uninstall");
// Main loop of the Orchestration.
Singleton::Consume<I_MainLoop>::by<OrchestrationComp>()->addOneTimeRoutine(
I_MainLoop::RoutineType::RealTime,

View File

@@ -312,7 +312,7 @@ TEST_F(OrchestrationTest, testAgentUninstallRest)
EXPECT_CALL(
rest,
mockRestCall(RestAction::ADD, "proxy", _)
).WillOnce(WithArg<2>(Invoke(this, &OrchestrationTest::restHandler)));
).WillOnce(WithArg<2>(Invoke(this, &OrchestrationTest::restHandler)));
init();

View File

@@ -726,7 +726,7 @@ checkBinaryData(const std::string &line, bool binaryDataFound)
for (size_t i=0; i<line.size(); ++i) {
unsigned char ch = (unsigned char)(line[i]);
if (!isprint(ch)) {
if (!isprint(ch) && (ch != '\r') && (ch != '\t') && (ch != '\n')) {
nonPrintableCharsCount++;
}
}
@@ -735,7 +735,7 @@ checkBinaryData(const std::string &line, bool binaryDataFound)
nonPrintableCharsCount << ", len=" << line.size();
// note: the threshold here is the same as used in base64 decoding (in function b64DecodeChunk)
if (nonPrintableCharsCount * 3 >= line.size()) {
if (nonPrintableCharsCount * 32 >= line.size()*10) {
dbgTrace(D_WAAP_SAMPLE_SCAN) << "checkBinaryData('" << line << "'): detected BINARY DATA";
binaryDataFound = true;
}

View File

@@ -51,6 +51,7 @@ public:
if (m_tag == "sourceip" || m_tag == "sourceidentifier") {
m_isCidr = Waap::Util::isCIDR(m_value, m_cidr);
}
m_isOverrideResponse = (m_tag == "responsebody" || m_tag == "responseBody");
if (!m_isCidr) {
// regex build may throw boost::regex_error
@@ -71,11 +72,13 @@ public:
ar(cereal::make_nvp("operand1", *m_operand1));
m_operand2 = std::make_shared<Match>();
ar(cereal::make_nvp("operand2", *m_operand2));
m_isOverrideResponse = m_operand1->m_isOverrideResponse || m_operand2->m_isOverrideResponse;
}
else if (m_op == "not") {
// If op is "NOT" get one operand
m_operand1 = std::make_shared<Match>();
ar(cereal::make_nvp("operand1", *m_operand1));
m_isOverrideResponse = m_operand1->m_isOverrideResponse;
}
}
}
@@ -113,6 +116,10 @@ public:
return false;
}
bool isOverrideResponse() const {
return m_isOverrideResponse;
}
private:
std::string m_op;
std::shared_ptr<Match> m_operand1;
@@ -122,6 +129,7 @@ private:
std::shared_ptr<boost::regex> m_valueRegex;
Waap::Util::CIDRData m_cidr;
bool m_isCidr;
bool m_isOverrideResponse;
};
class Behavior
@@ -233,6 +241,9 @@ public:
bool isChangingRequestData() const {
return m_isChangingRequestData;
}
bool isOverrideResponse() const {
return m_match.isOverrideResponse();
}
const std::string &getId() const {
return m_id;
@@ -251,6 +262,7 @@ public:
Policy(_A &ar) {
std::vector<Waap::Override::Rule> rules;
ar(cereal::make_nvp("overrides", rules));
m_isOverrideResponse = false;
for (std::vector<Waap::Override::Rule>::const_iterator it = rules.begin(); it != rules.end(); ++it) {
const Waap::Override::Rule& rule = *it;
@@ -262,6 +274,7 @@ public:
{
m_ResponseOverrides.push_back(rule);
}
m_isOverrideResponse |= rule.isOverrideResponse();
}
}
@@ -282,9 +295,14 @@ public:
dbgTrace(D_WAAP_OVERRIDE) << "Finished matching override rules.";
}
bool isOverrideResponse() const {
return m_isOverrideResponse;
}
private:
std::vector<Waap::Override::Rule> m_RequestOverrides; //overrides that change request data
std::vector<Waap::Override::Rule> m_ResponseOverrides; //overrides that change response/log data
bool m_isOverrideResponse;
};
struct State {

View File

@@ -99,6 +99,16 @@ bool WaapOverrideFunctor::operator()(const std::string& tag, const boost::regex&
else if (tag == "paramlocation" || tag == "paramLocation") {
return NGEN::Regex::regexMatch(__FILE__, __LINE__, waf2Transaction.getLocation().c_str(), what, rx);
}
else if (tag == "responsebody" || tag == "responseBody") {
waf2Transaction.getResponseInspectReasons().setApplyOverride(true);
if (!waf2Transaction.getResponseBody().empty()) {
boost::smatch matcher;
return NGEN::Regex::regexSearch(__FILE__, __LINE__,
waf2Transaction.getResponseBody().c_str(), matcher, rx);
} else {
return false;
}
}
}
catch (std::runtime_error & e) {
dbgDebug(D_WAAP_OVERRIDE) << "RegEx match for tag " << tag << " failed due to: " << e.what();

View File

@@ -24,7 +24,8 @@ openRedirect(false),
errorDisclosure(false),
errorLimiter(false),
rateLimiting(false),
collectResponseForLog(false)
collectResponseForLog(false),
applyOverride(false)
{
}
@@ -36,8 +37,9 @@ ResponseInspectReasons::shouldInspect() const
" ErrorDisclosure=" << errorDisclosure <<
" RateLimiting=" << rateLimiting <<
" ErrorLimiter=" << errorLimiter <<
" collectResponseForLog=" << collectResponseForLog;
return openRedirect || errorDisclosure || rateLimiting || errorLimiter || collectResponseForLog;
" collectResponseForLog=" << collectResponseForLog <<
" applyOverride=" << applyOverride;
return openRedirect || errorDisclosure || rateLimiting || errorLimiter || collectResponseForLog || applyOverride;
}
void
@@ -76,4 +78,18 @@ ResponseInspectReasons::setCollectResponseForLog(bool flag)
collectResponseForLog = flag;
}
void
ResponseInspectReasons::setApplyOverride(bool flag)
{
dbgTrace(D_WAAP) << "Change ResponseInspectReasons(setApplyOverride) " << applyOverride << " to " <<
flag;
applyOverride = flag;
}
bool
ResponseInspectReasons::getApplyOverride(void)
{
return applyOverride;
}
}

View File

@@ -24,12 +24,15 @@ public:
void setRateLimiting(bool flag);
void setErrorLimiter(bool flag);
void setCollectResponseForLog(bool flag);
void setApplyOverride(bool flag);
bool getApplyOverride(void);
private:
bool openRedirect;
bool errorDisclosure;
bool errorLimiter;
bool rateLimiting;
bool collectResponseForLog;
bool applyOverride;
};
}

View File

@@ -2097,6 +2097,29 @@ bool Waf2Transaction::decideResponse()
return false; // block
}
if (m_responseInspectReasons.getApplyOverride()) {
WaapConfigApplication ngenSiteConfig;
dbgTrace(D_WAAP_OVERRIDE) << "Checking exceptions for response";
if (WaapConfigApplication::getWaapSiteConfig(ngenSiteConfig)) {
dbgTrace(D_WAAP)
<< "Waf2Transaction::decideResponse(): got relevant Application configuration from the I/S";
m_overrideState = getOverrideState(&ngenSiteConfig);
// Apply overrides
if (m_overrideState.bForceBlock) {
dbgTrace(D_WAAP)
<< "Waf2Transaction::decideResponse(): setting shouldBlock to true due to override";
return false; // BLOCK
}
else if (m_overrideState.bForceException) {
dbgTrace(D_WAAP)
<< "Waf2Transaction::decideResponse(): setting shouldBlock to false due to override";
return true; // PASS
}
}
}
if (m_siteConfig) {
const std::shared_ptr<Waap::Trigger::Policy> triggerPolicy = m_siteConfig->get_TriggerPolicy();
if (!triggerPolicy) {

View File

@@ -219,6 +219,8 @@ public:
Waap::OpenRedirect::State &getOpenRedirectState() { return m_openRedirectState; }
IWaapConfig* getSiteConfig() { return m_siteConfig; }
void addNote(const std::string &note) { m_notes.push_back(note); }
const std::string &getResponseBody(void) const { return m_response_body; }
Waap::ResponseInspectReasons &getResponseInspectReasons(void) { return m_responseInspectReasons; }
private:
int finalizeDecision(IWaapConfig *sitePolicy, bool shouldBlock);

View File

@@ -556,6 +556,7 @@ Waap::Override::State Waf2Transaction::getOverrideState(IWaapConfig* sitePolicy)
Waap::Override::State overrideState;
std::shared_ptr<Waap::Override::Policy> overridePolicy = sitePolicy->get_OverridePolicy();
if (overridePolicy) { // at first we will run request overrides (in order to set the source)
m_responseInspectReasons.setApplyOverride(overridePolicy->isOverrideResponse());
overrideState.applyOverride(*overridePolicy, WaapOverrideFunctor(*this), m_matchedOverrideIds, true);
}

View File

@@ -971,6 +971,7 @@ bool decodeBase64Chunk(
int acc_bits = 0; // how many bits are filled in acc
int terminatorCharsSeen = 0; // whether '=' character was seen, and how many of them.
uint32_t nonPrintableCharsCount = 0;
uint32_t spacer_count = 0;
dbgTrace(D_WAAP) << "decodeBase64Chunk: value='" << value << "' match='" << string(it, end) << "'";
@@ -1047,9 +1048,12 @@ bool decodeBase64Chunk(
acc_bits -= 8;
// Count non-printable characters seen
if (!isprint(code)) {
if (!isprint(code) && (code != '\n') && (code != '\t')) {
nonPrintableCharsCount++;
}
if (code == '\r') {
spacer_count++;
}
decoded += (char)code;
}
@@ -1059,12 +1063,24 @@ bool decodeBase64Chunk(
// end of encoded sequence decoded.
dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: decoded.size=" << decoded.size() <<
", nonPrintableCharsCount=" << nonPrintableCharsCount << "; decoded='" << decoded << "'";
dbgTrace(D_WAAP_BASE64)
<< "decodeBase64Chunk: decoded.size="
<< decoded.size()
<< ", nonPrintableCharsCount="
<< nonPrintableCharsCount
<< ", spacer_count = "
<< spacer_count
<< ", decoded size = "
<< decoded.size()
<< "; decoded='"
<< decoded << "'";
// Return success only if decoded.size>=5 and there are less than 10% of non-printable
// characters in output.
if (decoded.size() >= 5) {
if (spacer_count > 1) {
nonPrintableCharsCount = nonPrintableCharsCount - spacer_count + 1;
}
if (nonPrintableCharsCount * 10 < decoded.size()) {
dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (decode/replace) decoded.size=" << decoded.size() <<
", nonPrintableCharsCount=" << nonPrintableCharsCount << ": replacing with decoded data";
@@ -1074,6 +1090,8 @@ bool decodeBase64Chunk(
", nonPrintableCharsCount=" << nonPrintableCharsCount;
decoded.clear();
}
dbgTrace(D_WAAP_BASE64) << "returning true: successfully decoded."
<< " Returns decoded data in \"decoded\" parameter";
return true; // successfully decoded. Returns decoded data in "decoded" parameter
}