Email-Abuse-Investigator
view release on metacpan or search on metacpan
lib/Email/Abuse/Investigator.pm view on Meta::CPAN
push @out, sprintf(' %-14s : %s', $label,
_sanitise_output($decoded ne $v ? "$decoded [encoded: $v]" : $v));
}
push @out, '';
# Risk assessment section
my $risk = $self->risk_assessment();
push @out, "[ RISK ASSESSMENT: $risk->{level} (score: $risk->{score}) ]";
if (@{ $risk->{flags} }) {
for my $f (@{ $risk->{flags} }) {
push @out, " [$f->{severity}] " . _sanitise_output($f->{detail});
}
} else {
push @out, ' (no specific red flags detected)';
}
push @out, '';
# Originating host section
push @out, '[ ORIGINATING HOST ]';
my $orig = $self->originating_ip();
if ($orig) {
push @out, ' IP : ' . _sanitise_output($orig->{ip});
push @out, ' Reverse DNS : ' . _sanitise_output($orig->{rdns}) if $orig->{rdns};
push @out, ' Country : ' . _sanitise_output($orig->{country}) if $orig->{country};
push @out, ' Organisation : ' . _sanitise_output($orig->{org}) if $orig->{org};
push @out, ' Abuse addr : ' . _sanitise_output($orig->{abuse}) if $orig->{abuse};
push @out, " Confidence : $orig->{confidence}";
push @out, ' Note : ' . _sanitise_output($orig->{note}) if $orig->{note};
} else {
push @out, ' (could not determine originating IP)';
}
push @out, '';
# Sending software section (omitted if none found)
my @sw = $self->sending_software();
if (@sw) {
push @out, '[ SENDING SOFTWARE / INFRASTRUCTURE CLUES ]';
for my $s (@sw) {
push @out, sprintf(' %-14s : %s', $s->{header}, _sanitise_output($s->{value}));
push @out, " Note : $s->{note}";
push @out, '';
}
}
# Received chain tracking IDs (only hops with id or for are shown)
my @trail = grep { defined $_->{id} || defined $_->{for} }
$self->received_trail();
if (@trail) {
push @out, '[ RECEIVED CHAIN TRACKING IDs ]';
push @out, ' (Supply these to the relevant ISP abuse team to trace the session)';
push @out, '';
for my $hop (@trail) {
push @out, ' IP : ' . (_sanitise_output($hop->{ip}) // '(unknown)');
push @out, ' Envelope for : ' . _sanitise_output($hop->{for}) if $hop->{for};
push @out, ' Server ID : ' . _sanitise_output($hop->{id}) if $hop->{id};
push @out, '';
}
}
# Embedded URLs section -- grouped by hostname
push @out, '[ EMBEDDED HTTP/HTTPS URLs ]';
my @urls = $self->embedded_urls();
if (@urls) {
my (%host_order, %host_meta, %host_paths);
my $seq = 0;
for my $u (@urls) {
my $h = $u->{host};
unless (exists $host_order{$h}) {
$host_order{$h} = $seq++;
$host_meta{$h} = {
ip => $u->{ip},
org => $u->{org},
abuse => $u->{abuse},
country => $u->{country},
};
}
push @{ $host_paths{$h} }, $u->{url};
}
# Output each host group in first-seen order
for my $h (sort { $host_order{$a} <=> $host_order{$b} } keys %host_order) {
my $m = $host_meta{$h};
my $bare = lc $h; $bare =~ s/^www\.//;
push @out, ' Host : ' . _sanitise_output($h) .
(($URL_SHORTENERS{$bare} || $self->{url_shorteners}->{$bare})
? ' *** URL SHORTENER -- real destination hidden ***' : '');
push @out, ' IP : ' . _sanitise_output($m->{ip}) if $m->{ip};
push @out, ' Country : ' . _sanitise_output($m->{country}) if $m->{country};
push @out, ' Organisation : ' . _sanitise_output($m->{org}) if $m->{org};
push @out, ' Abuse addr : ' . _sanitise_output($m->{abuse}) if $m->{abuse};
my @paths = @{ $host_paths{$h} };
if (@paths == 1) {
push @out, ' URL : ' . _sanitise_output($paths[0]);
} else {
push @out, ' URLs (' . scalar(@paths) . ') :';
push @out, ' ' . _sanitise_output($_) for @paths;
}
push @out, '';
}
} else {
push @out, ' (none found)';
push @out, '';
}
# Contact / reply-to domains section
push @out, '[ CONTACT / REPLY-TO DOMAINS ]';
my @mdoms = $self->mailto_domains();
if (@mdoms) {
for my $d (@mdoms) {
push @out, ' Domain : ' . _sanitise_output($d->{domain});
push @out, ' Found in : ' . _sanitise_output($d->{source});
if ($d->{recently_registered}) {
push @out, ' *** WARNING: RECENTLY REGISTERED - possible phishing domain ***';
}
push @out, ' Registered : ' . $d->{registered} if $d->{registered};
push @out, ' Expires : ' . $d->{expires} if $d->{expires};
push @out, ' Registrar : ' . _sanitise_output($d->{registrar}) if $d->{registrar};
push @out, ' Reg. abuse : ' . _sanitise_output($d->{registrar_abuse}) if $d->{registrar_abuse};
if ($d->{web_ip}) {
push @out, ' Web host IP : ' . _sanitise_output($d->{web_ip});
push @out, ' Web host org : ' . _sanitise_output($d->{web_org}) if $d->{web_org};
( run in 0.503 second using v1.01-cache-2.11-cpan-71847e10f99 )