Files
SecGen/lib/helpers/rules.rb

142 lines
5.0 KiB
Ruby

require_relative './print.rb'
require_relative './scenario.rb'
class Rules
# Generate audit and alerting rules
def self.generate_auditbeat_rules(goals)
rules = []
goals.each do |goal|
# Generate auditbeat rules based on rule type
rule_type = RuleTypes.get_rule_type(goal['goal_type'])
case rule_type
when RuleTypes::READ_FILE
rules << greedy_auditbeat_rule(goal['file_path'], 'r')
when RuleTypes::MODIFY_FILE
when RuleTypes::ACCESS_ACCOUNT
when RuleTypes::SERVICE_DOWN
when RuleTypes::SYSTEM_DOWN
else
Print.err('Unknown goal type')
raise
end
end
rules
end
# Generates a greedy read or write rule for auditbeat (e.g. /home/user/file_name resolves to /home)
def self.greedy_auditbeat_rule(path, r_w)
if path.count('/') == 1 # is root dir
Print.err("ERROR: auditd cannot monitor the root directory - revise your scenario goals!")
Print.err(" path: #{path}")
Print.err(" r_w: #{r_w}")
exit(1)
else
base_path = path.split('/')[0..1].join('/') + '/'
key = base_path.gsub(/[^A-Za-z0-9\-\_]/, '')
"-w #{base_path} -p #{r_w} -k #{key}"
end
end
def self.generate_elastalert_rule(hostname, module_name, goal, counter)
rule = ''
# switch case to determine which type of rule we're returning (read file, etc.)
rule_type = RuleTypes.get_rule_type(goal['goal_type'])
case rule_type
when RuleTypes::READ_FILE
rule = generate_elastalert_rule_rf(hostname, module_name, goal, counter)
when RuleTypes::MODIFY_FILE
# rule = generate_elastalert_rule_mf(hostname, module_name, goal, sub_goal)
when RuleTypes::ACCESS_ACCOUNT
rule = generate_elastalert_rule_acc(hostname, module_name, goal, counter)
when RuleTypes::SERVICE_DOWN
# rule = generate_elastalert_rule_svcd(hostname, module_name, goal, sub_goal)
when RuleTypes::SYSTEM_DOWN
# rule = generate_elastalert_rule_sysd(hostname, module_name, goal, sub_goal)
else
raise 'unknown_goal_type'
end
rule
end
# source_name: either system name or module name,
def self.generate_elastalert_rule_rf(hostname, source_name, goal, counter)
"name: #{get_ea_rulename(hostname, source_name, goal, counter)}\n" +
"type: any\n" +
"index: auditbeat-*\n" +
"filter:\n" +
" - query:\n" +
" query_string:\n" +
' query: "combined_path: \"' + goal['file_path'] + '\""' + "\n" +
" - query:\n" +
" query_string:\n" +
' query: "auditd.result: success"' + "\n" +
" - query:\n" +
" query_string:\n" +
' query: "event.action: opened-file"' + "\n" +
" - query:\n" +
" query_string:\n" +
" query: \"process.executable: \\\"/bin/cat\\\" OR \\\"/usr/bin/vim.basic\\\" OR \\\"/usr/bin/less\\\" OR \\\"/bin/more\\\" OR \\\"/bin/nano\\\" OR \\\"/usr/bin/kate\\\"\"" + "\n" +
"alert:\n" +
" - \"elastalert.modules.alerter.exec.ExecAlerter\"\n" +
"command: [\"/usr/bin/ruby\", \"/opt/alert_actioner/alert_router.rb\", \"raise\", \"--alert-name\", \"" + get_ea_rulename(hostname, source_name, goal, counter) +"\"]\n" +
"pipe_match_json: true\n" +
"realert:\n" +
" minutes: 0\n"
end
def self.generate_elastalert_rule_acc(hostname, source_name, goal, counter)
"name: #{get_ea_rulename(hostname, source_name, goal, counter)}\n" +
"type: any\n" +
"index: auditbeat-*\n" +
"filter:\n" +
" - query:\n" +
" query_string:\n" +
' query: "related.user: \"' + goal['account_name'] + '\" OR user.name: \"' + goal['account_name'] + '\""' + "\n" +
" - query:\n" +
" query_string:\n" +
' query: "event.action: \"user_login\" OR \"started-session\" OR \"acquired-credentials\" OR \"opened-file\""' + "\n" +
" - query:\n" +
" query_string:\n" +
' query: "auditd.result: success"' + "\n" +
"alert:\n" +
" - \"elastalert.modules.alerter.exec.ExecAlerter\"\n" +
"command: [\"/usr/bin/ruby\", \"/opt/alert_actioner/alert_router.rb\", \"raise\", \"--alert-name\", \"" + get_ea_rulename(hostname, source_name, goal, counter) +"\"]\n" +
"pipe_match_json: true\n" +
"realert:\n" +
" minutes: 0\n"
end
def self.get_ea_rulename(hostname, module_name, goal, counter)
rule_type = RuleTypes.get_rule_type(goal['goal_type'])
return "#{hostname}-#{module_name}-#{rule_type}-#{counter}"
end
class RuleTypes
READ_FILE = 'rf'
MODIFY_FILE = 'mf'
ACCESS_ACCOUNT = 'acc'
SERVICE_DOWN = 'svcd'
SYSTEM_DOWN = 'sysd'
def self.get_rule_type(rule_type)
case rule_type
when 'read_file'
READ_FILE
when 'modify_file'
MODIFY_FILE
when 'access_account'
ACCESS_ACCOUNT
when 'service_down'
SERVICE_DOWN
when 'system_down'
SYSTEM_DOWN
else
raise 'unknown_rule_type'
end
end
end
end