2024-11-28 10:41:59 +00:00

194 lines
6.4 KiB
C++
Executable File

// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __PARSER_PARAMETER_DEEP_H__549cc3ee
#define __PARSER_PARAMETER_DEEP_H__549cc3ee
#include "ParserBase.h"
#include "KeyStack.h"
#include "WaapAssetState.h"
#include "Waf2Regex.h"
#include "Waf2Util.h"
#include "maybe_res.h"
#include <deque>
// Deep (recursively) parses/dissects parameters based on input stream
class DeepParser : public IParserReceiver
{
public:
DeepParser(std::shared_ptr<WaapAssetState> pWaapAssetState, IParserReceiver &receiver,
IWaf2Transaction* pTransaction);
virtual ~DeepParser();
void setWaapAssetState(std::shared_ptr<WaapAssetState> pWaapAssetState);
// This callback receives input key/value pairs, dissects, decodes and deep-scans these, recursively
// finally, it calls onDetected() on each detected parameter.
virtual int onKv(const char *k, size_t k_len, const char *v, size_t v_len, int flags, size_t parser_depth);
void clear();
void showStats(std::string& buff, const ValueStatsAnalyzer& valueStats);
void apiProcessKey(const char *v, size_t v_len);
size_t depth() const;
void setGlobalMaxObjectDepth(size_t depth) { m_globalMaxObjectDepth = depth; }
size_t getGlobalMaxObjectDepth() const { return m_globalMaxObjectDepth; }
bool isGlobalMaxObjectDepthReached() const;
size_t getLocalMaxObjectDepth() const { return m_localMaxObjectDepth; }
void setMultipartBoundary(const std::string &boundary);
const std::string &getMultipartBoundary() const;
bool isBinaryData() const;
const std::string getActualParser(size_t parser_depth) const;
bool isWBXmlData() const;
Maybe<std::string> getSplitType() const;
std::vector<std::pair<std::string, std::string> > kv_pairs;
// Represents information stored per-keyword
struct KeywordInfo
{
std::string type;
std::string name;
std::string val;
KeywordInfo() {}
KeywordInfo(
const std::string &type,
const std::string &name,
const char *v,
size_t v_len) :
type(type),
name(name),
val(std::string(v, v_len))
{
}
size_t getLength() const
{
return val.size();
}
const std::string &getName() const
{
return name;
}
const std::string &getType() const
{
return type;
}
// Return the value itself
const std::string &getValue() const
{
return val;
}
};
// KeywordInfo maintained for each keyword name
std::vector<KeywordInfo> m_keywordInfo;
KeyStack m_key;
int getShiftInUrlEncodedBuffer(const ValueStatsAnalyzer &valueStats, std::string &cur_val);
private:
class Ref
{
public:
Ref(int &ref):m_ref(ref) { m_ref++; }
~Ref() { m_ref--; }
private:
int &m_ref;
};
std::shared_ptr<WaapAssetState> m_pWaapAssetState;
IWaf2Transaction* m_pTransaction;
IParserReceiver &m_receiver;
size_t m_depth;
int m_splitRefs; // incremented when entering recursion due to "split" action,
// decremented afterwards. If >0, apiProcessKey should not be called.
// Split a value by given regexp. Return true if split, false otherwise.
// note: This function calls onKv(), and the call can be recursive!
// TODO:: maybe convert this splitter to Parser-derived class?!
bool splitByRegex(const std::string &val, const Regex &r, const char *keyPrefix, size_t parser_depth);
int createInternalParser(
const char *k,
size_t k_len,
std::string &cur_val,
const ValueStatsAnalyzer &valueStats,
bool isBodyPayload,
bool isRefererPayload,
bool isRefererParamPayload,
bool isUrlPayload,
bool isUrlParamPayload,
bool isCookiePayload,
int flags,
size_t parser_depth,
Waap::Util::BinaryFileType b64FileType
);
int createUrlParserForJson(
const char *k,
size_t k_len,
std::string &cur_val,
const ValueStatsAnalyzer &valueStats,
bool isBodyPayload,
bool isRefererPayload,
bool isRefererParamPayload,
bool isUrlPayload,
bool isUrlParamPayload,
bool isCookiePayload,
int flags,
size_t parser_depth
);
void printParserDeque();
int parseAfterMisleadingMultipartBoundaryCleaned(
const char *k,
size_t k_len,
std::string &cur_val,
const ValueStatsAnalyzer &valueStats,
bool isBodyPayload,
bool isRefererPayload,
bool isRefererParamPayload,
bool isUrlPayload,
bool isUrlParamPayload,
bool isCookiePayload,
int flags,
size_t parser_depth,
bool base64ParamFound,
Waap::Util::BinaryFileType b64FileType
);
int pushValueToTopParser(std::string &cur_val, int flags, bool base64ParamFound, int offset, size_t parser_depth);
int parseBuffer(
ValueStatsAnalyzer &valueStats,
const std::string &cur_val,
bool base64ParamFound,
bool shouldUpdateKeyStack,
size_t parser_depth
);
bool shouldEnforceDepthLimit(const std::shared_ptr<ParserBase>& parser) const;
void setLocalMaxObjectDepth(size_t depth) { m_localMaxObjectDepth = depth; }
void setGlobalMaxObjectDepthReached() { m_globalMaxObjectDepthReached = true; }
bool isPDFDetected(const std::string &cur_val) const;
bool m_deepParserFlag;
std::stack<std::tuple<size_t, size_t, std::string>> m_splitTypesStack; // depth, splitIndex, splitType
std::deque<std::shared_ptr<ParserBase>> m_parsersDeque;
std::string m_multipart_boundary;
size_t m_globalMaxObjectDepth;
size_t m_localMaxObjectDepth;
bool m_globalMaxObjectDepthReached;
bool m_is_wbxml;
};
#endif // __PARSER_PARAMETER_DEEP_H__549cc3ee