use crate::labels::{
Cap, DataLabel, GateActivation, Kind, LabelRule, ParamConfig, RuntimeLabelRule, SinkGate,
};
use crate::utils::project::{DetectedFramework, FrameworkContext};
use phf::{Map, phf_map};
pub static RULES: &[LabelRule] = &[
LabelRule {
matchers: &[
"$_GET",
"_GET",
"$_POST",
"_POST",
"$_REQUEST",
"_REQUEST",
"$_COOKIE",
"_COOKIE",
"$_FILES",
"_FILES",
"$_SERVER",
"_SERVER",
"$_ENV",
"_ENV",
],
label: DataLabel::Source(Cap::all()),
case_sensitive: false,
},
LabelRule {
matchers: &["file_get_contents", "fread"],
label: DataLabel::Source(Cap::all()),
case_sensitive: false,
},
LabelRule {
matchers: &["htmlspecialchars", "htmlentities"],
label: DataLabel::Sanitizer(Cap::HTML_ESCAPE),
case_sensitive: false,
},
LabelRule {
matchers: &["escapeshellarg", "escapeshellcmd"],
label: DataLabel::Sanitizer(Cap::SHELL_ESCAPE),
case_sensitive: false,
},
LabelRule {
matchers: &["basename", "realpath"],
label: DataLabel::Sanitizer(Cap::FILE_IO),
case_sensitive: false,
},
LabelRule {
matchers: &["prepare", "bindParam", "bindValue"],
label: DataLabel::Sanitizer(Cap::SQL_QUERY),
case_sensitive: false,
},
LabelRule {
matchers: &["intval", "floatval", "ctype_digit", "ctype_alpha"],
label: DataLabel::Sanitizer(Cap::all()),
case_sensitive: false,
},
LabelRule {
matchers: &["filter_input", "filter_var"],
label: DataLabel::Sanitizer(Cap::all()),
case_sensitive: false,
},
LabelRule {
matchers: &["urlencode", "rawurlencode"],
label: DataLabel::Sanitizer(Cap::URL_ENCODE),
case_sensitive: false,
},
LabelRule {
matchers: &[
"system",
"exec",
"passthru",
"shell_exec",
"proc_open",
"popen",
],
label: DataLabel::Sink(Cap::SHELL_ESCAPE),
case_sensitive: false,
},
LabelRule {
matchers: &["eval", "assert"],
label: DataLabel::Sink(Cap::CODE_EXEC),
case_sensitive: false,
},
LabelRule {
matchers: &["include", "include_once", "require", "require_once"],
label: DataLabel::Sink(Cap::FILE_IO),
case_sensitive: false,
},
LabelRule {
matchers: &["unserialize"],
label: DataLabel::Sink(Cap::DESERIALIZE),
case_sensitive: false,
},
LabelRule {
matchers: &["move_uploaded_file", "copy", "file_put_contents", "fwrite"],
label: DataLabel::Sink(Cap::FILE_IO),
case_sensitive: false,
},
LabelRule {
matchers: &["echo", "print"],
label: DataLabel::Sink(Cap::HTML_ESCAPE),
case_sensitive: false,
},
LabelRule {
matchers: &["mysqli_query", "pg_query", "pg_execute", "query"],
label: DataLabel::Sink(Cap::SQL_QUERY),
case_sensitive: false,
},
LabelRule {
matchers: &[
"pdo.exec",
"pdo.query",
"mysqli.real_query",
"mysqli_real_query",
],
label: DataLabel::Sink(Cap::SQL_QUERY),
case_sensitive: false,
},
LabelRule {
matchers: &["DB.raw", "whereRaw", "selectRaw", "orderByRaw", "havingRaw"],
label: DataLabel::Sink(Cap::SQL_QUERY),
case_sensitive: false,
},
LabelRule {
matchers: &["file_get_contents", "curl_exec"],
label: DataLabel::Sink(Cap::SSRF),
case_sensitive: false,
},
LabelRule {
matchers: &[
"Client.post",
"Client.put",
"Client.patch",
"Client.request",
"HttpClient.post",
"HttpClient.put",
"HttpClient.patch",
"HttpClient.request",
"Http.post",
"Http.put",
"Http.patch",
],
label: DataLabel::Sink(Cap::DATA_EXFIL),
case_sensitive: true,
},
];
pub static GATED_SINKS: &[SinkGate] = &[SinkGate {
callee_matcher: "curl_setopt",
arg_index: 1,
dangerous_values: &["CURLOPT_POSTFIELDS", "CURLOPT_COPYPOSTFIELDS"],
dangerous_prefixes: &[],
label: DataLabel::Sink(Cap::DATA_EXFIL),
case_sensitive: true,
payload_args: &[2],
keyword_name: None,
dangerous_kwargs: &[],
activation: GateActivation::ValueMatch,
}];
pub static KINDS: Map<&'static str, Kind> = phf_map! {
"if_statement" => Kind::If,
"while_statement" => Kind::While,
"for_statement" => Kind::For,
"foreach_statement" => Kind::For,
"do_statement" => Kind::While,
"return_statement" => Kind::Return,
"throw_expression" => Kind::Throw,
"break_statement" => Kind::Break,
"continue_statement" => Kind::Continue,
"program" => Kind::SourceFile,
"compound_statement" => Kind::Block,
"else_clause" => Kind::Block,
"else_if_clause" => Kind::Block,
"function_definition" => Kind::Function,
"method_declaration" => Kind::Function,
"switch_statement" => Kind::Switch,
"switch_block" => Kind::Block,
"case_statement" => Kind::Block,
"default_statement" => Kind::Block,
"try_statement" => Kind::Try,
"catch_clause" => Kind::Block,
"finally_clause" => Kind::Block,
"colon_block" => Kind::Block,
"anonymous_function_creation_expression" => Kind::Function,
"arrow_function" => Kind::Function,
"class_declaration" => Kind::Block,
"function_call_expression" => Kind::CallFn,
"object_creation_expression" => Kind::CallFn,
"member_call_expression" => Kind::CallMethod,
"scoped_call_expression" => Kind::CallMethod,
"assignment_expression" => Kind::Assignment,
"expression_statement" => Kind::CallWrapper,
"echo_statement" => Kind::CallWrapper,
"comment" => Kind::Trivia,
";" => Kind::Trivia, "," => Kind::Trivia,
"(" => Kind::Trivia, ")" => Kind::Trivia,
"{" => Kind::Trivia, "}" => Kind::Trivia,
"\n" => Kind::Trivia,
"php_tag" => Kind::Trivia,
"namespace_definition" => Kind::Trivia,
"namespace_use_declaration" => Kind::Trivia,
};
pub static PARAM_CONFIG: ParamConfig = ParamConfig {
params_field: "parameters",
param_node_kinds: &["simple_parameter", "variadic_parameter"],
self_param_kinds: &[],
ident_fields: &["name"],
};
pub fn framework_rules(ctx: &FrameworkContext) -> Vec<RuntimeLabelRule> {
let mut rules = Vec::new();
if ctx.has(DetectedFramework::Laravel) {
rules.push(RuntimeLabelRule {
matchers: vec![
"Request::input".into(),
"Request::get".into(),
"Request::query".into(),
"Request::post".into(),
"Request::all".into(),
],
label: DataLabel::Source(Cap::all()),
case_sensitive: false,
});
}
rules
}