19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
# File 'lib/newrelic_security/agent/control/collector.rb', line 19
def collect(case_type, args, event_category = nil, **keyword_args)
return unless NewRelic::Security::Agent.config[:enabled]
return if NewRelic::Security::Agent::Control::HTTPContext.get_context.nil? && NewRelic::Security::Agent::Control::GRPCContext.get_context.nil?
return if check_and_exclude_from_iast_scan_for_api
return if check_and_exclude_from_iast_scan_for_detection_category(case_type)
args.map! { |file| Pathname.new(file).relative? ? File.join(Dir.pwd, file) : file } if [FILE_OPERATION, FILE_INTEGRITY].include?(case_type)
event = NewRelic::Security::Agent::Control::Event.new(case_type, args, event_category)
stk = caller_locations[1..COVERAGE]
event.sourceMethod = stk[0].label
event.copy_http_info(NewRelic::Security::Agent::Control::HTTPContext.get_context) if NewRelic::Security::Agent::Control::HTTPContext.get_context
event.copy_grpc_info(NewRelic::Security::Agent::Control::GRPCContext.get_context) if NewRelic::Security::Agent::Control::GRPCContext.get_context
event.isIASTEnable = true if NewRelic::Security::Agent::Utils.is_IAST?
event.isIASTRequest = true if NewRelic::Security::Agent::Utils.is_IAST_request?(event.httpRequest[:headers])
event.parentId = event.httpRequest[:headers][NR_CSEC_PARENT_ID] if event.httpRequest[:headers].key?(NR_CSEC_PARENT_ID)
find_deserialisation(event, stk) if case_type != REFLECTED_XSS && NewRelic::Security::Agent.config[:'security.detection.deserialization.enabled']
find_rci(event, stk) if case_type != REFLECTED_XSS && NewRelic::Security::Agent.config[:'security.detection.rci.enabled']
route = nil
if case_type == REFLECTED_XSS
event.httpResponse[:contentType] = keyword_args[:response_header]
route = NewRelic::Security::Agent::Control::HTTPContext.get_context.route
if route && NewRelic::Security::Agent.agent.route_map.include?(route)
event.stacktrace << route
end
end
user_frame_index = get_user_frame_index(stk)
route = route&.gsub(/\d+/, EMPTY_STRING) if NewRelic::Security::Agent.config[:framework] == :rack || NewRelic::Security::Agent.config[:framework] == :roda
event.apiId = "#{case_type}-#{calculate_api_id(stk[0..user_frame_index].map { |frame| "#{frame.absolute_path}:#{frame.lineno}" }, event.httpRequest[:method], route)}"
stk.delete_if { |frame| frame.path.match?(/newrelic_security/) || frame.path.match?(/new_relic/) }
user_frame_index = get_user_frame_index(stk)
return if case_type != REFLECTED_XSS && user_frame_index == -1 if user_frame_index != -1
event.userMethodName = stk[user_frame_index].label.to_s
event.userFileName = stk[user_frame_index].path
event.lineNumber = stk[user_frame_index].lineno
else
event.sourceMethod = stk[0].label.to_s
event.userMethodName = stk[0].label.to_s
event.userFileName = stk[0].path
event.lineNumber = stk[0].lineno
end
event.stacktrace = stk[0..user_frame_index].map(&:to_s)
NewRelic::Security::Agent.agent.event_processor&.send_event(event)
if event.httpRequest[:headers].key?(NR_CSEC_FUZZ_REQUEST_ID) && event.apiId == event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID].split(COLON_IAST_COLON)[0] && NewRelic::Security::Agent.agent.iast_client.completed_requests[event.parentId]
NewRelic::Security::Agent.agent.iast_client.completed_requests[event.parentId] << event.id
end
event
rescue Exception => exception
NewRelic::Security::Agent.logger.error "Exception in event collector: #{exception.inspect} #{exception.backtrace}"
NewRelic::Security::Agent.agent.event_processor.send_critical_message(exception.message, "SEVERE", caller_locations[0].to_s, Thread.current.name, exception)
if NewRelic::Security::Agent::Utils.is_IAST_request?(event.httpRequest[:headers])
NewRelic::Security::Agent.agent.iast_event_stats.error_count.increment
else
NewRelic::Security::Agent.agent.rasp_event_stats.error_count.increment
end
ensure
event = nil
stk = nil
route = nil
end
|