#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "argument_retriever.hpp"
#include "clock.hpp"
#include "condition/base.hpp"
#include "condition/shi_common.hpp"
#include "condition/shi_detector.hpp"
#include "condition/structured_condition.hpp"
#include "exclusion/common.hpp"
#include "log.hpp"
#include "object.hpp"
#include "tokenizer/shell.hpp"
#include "utils.hpp"
using namespace std::literals;
namespace ddwaf {
bool shi_detector::eval_string(const unary_argument<object_view> &resource,
const variadic_argument<object_view> ¶ms, condition_cache &cache,
const object_set_ref &objects_excluded, ddwaf::timer &deadline)
{
if (resource.value.empty()) {
return {};
}
auto resource_sv = resource.value.as<std::string_view>();
std::vector<shell_token> resource_tokens;
for (const auto ¶m : params) {
auto res = find_shi_from_params(resource_sv, resource_tokens, param.value,
param.transformers, objects_excluded, deadline);
if (res.has_value()) {
auto &[highlight, param_kp] = res.value();
DDWAF_TRACE("Target {} matched parameter value {}", param.address, highlight);
cache.match =
condition_match{.args = {{.name = "resource"sv,
.resolved = std::string{resource_sv},
.address = resource.address,
.key_path = convert_key_path(resource.key_path)},
{.name = "params"sv,
.resolved = highlight,
.address = param.address,
.key_path = param_kp}},
.highlights = {std::move(highlight)},
.operator_name = "shi_detector",
.operator_value = {}};
return true;
}
}
return {};
}
bool shi_detector::eval_array(const unary_argument<object_view> &resource,
const variadic_argument<object_view> ¶ms, condition_cache &cache,
const object_set_ref &objects_excluded, ddwaf::timer &deadline)
{
shell_argument_array arguments{resource.value};
if (arguments.empty()) {
return {};
}
std::vector<shell_token> resource_tokens;
for (const auto ¶m : params) {
auto res = find_shi_from_params(arguments, resource_tokens, param.value, param.transformers,
objects_excluded, deadline);
if (res.has_value()) {
auto &[highlight, param_kp] = res.value();
DDWAF_TRACE("Target {} matched parameter value {}", param.address, highlight);
cache.match =
condition_match{.args = {{.name = "resource"sv,
.resolved = std::move(arguments.resource),
.address = resource.address,
.key_path = convert_key_path(resource.key_path)},
{.name = "params"sv,
.resolved = highlight,
.address = param.address,
.key_path = param_kp}},
.highlights = {std::move(highlight)},
.operator_name = "shi_detector",
.operator_value = {}};
return true;
}
}
return {};
}
shi_detector::shi_detector(std::vector<condition_parameter> args)
: base_impl<shi_detector>(std::move(args))
{
shell_tokenizer::initialise_regexes();
}
bool shi_detector::eval_impl(const unary_argument<object_view> &resource,
const variadic_argument<object_view> ¶ms, condition_cache &cache,
const object_set_ref &objects_excluded, ddwaf::timer &deadline) const
{
if (resource.value.is_string()) {
return eval_string(resource, params, cache, objects_excluded, deadline);
}
if (resource.value.is_array()) {
return eval_array(resource, params, cache, objects_excluded, deadline);
}
return {};
}
}