File Coverage

blib/lib/XML/IODEF/Simple.pm
Criterion Covered Total %
statement 11 48 22.9
branch 0 20 0.0
condition 0 13 0.0
subroutine 4 5 80.0
pod n/a
total 15 86 17.4


line stmt bran cond sub pod time code
1             package XML::IODEF::Simple;
2              
3 1     1   50546 use 5.008008;
  1         2  
4 1     1   4 use strict;
  1         1  
  1         14  
5 1     1   3 use warnings;
  1         8  
  1         47  
6              
7             our $VERSION = '0.00_03';
8             $VERSION = eval $VERSION; # see L<perlmodstyle>
9              
10             require XML::IODEF;
11 1     1   465 use Module::Pluggable require => 1;
  1         8269  
  1         4  
12              
13             # Preloaded methods go here.
14              
15             sub new {
16 0     0     my ($class,$info) = @_;
17            
18 0   0       my $description = lc($info->{'description'}) || 'unknown';
19 0           my $confidence = $info->{'confidence'};
20 0           my $severity = $info->{'severity'};
21 0   0       my $restriction = $info->{'restriction'} || 'private';
22 0   0       my $source = $info->{'source'} || 'localhost';
23 0           my $relatedid = $info->{'relatedid'};
24 0           my $alternativeid = $info->{'alternativeid'};
25 0   0       my $alternativeid_restriction = $info->{'alternativeid_restriction'} || 'private';
26 0   0       my $purpose = $info->{'purpose'} || 'mitigation';
27              
28 0           my $dt = $info->{'detecttime'};
29             # default it to the hour
30 0 0         unless($dt){
31 0           require DateTime;
32 0           $dt = DateTime->from_epoch(epoch => time());
33 0           $dt = $dt->ymd().'T'.$dt->hour().':00:00Z';
34             }
35 0           $info->{'detecttime'} = $dt;
36              
37 0           my $iodef = XML::IODEF->new();
38 0           $iodef->add('Incidentpurpose',$purpose);
39 0 0         $iodef->add('IncidentIncidentIDname',$source) if($source);
40 0 0         $iodef->add('IncidentDetectTime',$dt) if($dt);
41 0 0         $iodef->add('IncidentRelatedActivityIncidentID',$relatedid) if($relatedid);
42 0 0         if($alternativeid){
43 0           $iodef->add('IncidentAlternativeIDIncidentID',$alternativeid);
44 0           $iodef->add('IncidentAlternativeIDIncidentIDrestriction',$alternativeid_restriction);
45             }
46 0           $iodef->add('Incidentrestriction',$restriction);
47 0 0         $iodef->add('IncidentDescription',$description) if($description);
48 0 0         if($confidence){
49 0           $iodef->add('IncidentAssessmentConfidencerating','numeric');
50 0           $iodef->add('IncidentAssessmentConfidence',$confidence);
51             }
52 0 0 0       if($severity && $severity =~ /(low|medium|high)/){
53 0           $iodef->add('IncidentAssessmentImpactseverity',$severity);
54             }
55              
56 0           foreach($class->plugins()){
57 0 0         if($_->prepare($info)){
58 0           $iodef = $_->convert($info,$iodef);
59             }
60             }
61 0           my $impact = $info->{'impact'};
62 0 0         $iodef->add('IncidentAssessmentImpact',$impact) if($impact);
63 0           return $iodef;
64             }
65              
66              
67             1;
68             __END__
69             =head1 NAME
70              
71             XML::IODEF::Simple - Perl extension for easier IODEF message generation
72              
73             =head1 SYNOPSIS
74              
75             use XML::IODEF::Simple;
76             my $report = XML::IODEF::Simple->new({
77             guid => 'mygroup.example.com',
78             source => 'example.com',
79             restriction => 'need-to-know',
80             description => 'spyeye',
81             impact => 'botnet',
82             address => '1.2.3.4',
83             protocol => 'tcp',
84             portlist => '8080',
85             contact => {
86             name => 'root',
87             email => 'root@localhost',
88             },
89             purpose => 'mitigation',
90             confidence => '85',
91             alternativeid => 'https://example.com/rt/Ticket/Display.html?id=1234',
92             alternativeid_restriction => 'private',
93             sharewith => 'partners.example.com,leo.example.com',
94             });
95             my $xml = $report->out();
96             my $hash = $report->to_tree();
97              
98             # generates
99             <?xml version="1.0" encoding="UTF-8"?>
100             <IODEF-Document version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:ietf:params:xmls:schema:iodef-1.0"><Incident purpose="mitigation" restriction="need-to-know"><IncidentID name="example.com"/><AlternativeID><IncidentID restriction="private">https://example.com/rt/Ticket/Display.html?id=1234</IncidentID></AlternativeID><DetectTime>2011-10-24T13:00:00Z</DetectTime><Description>spyeye</Description><Assessment><Impact severity="high">botnet</Impact><Confidence rating="numeric">85</Confidence></Assessment><Contact type="person" role="creator"><ContactName>root</ContactName><Email>root@localhost</Email></Contact><EventData><Flow><System><Node><Address category="ipv4-addr">1.2.3.4</Address></Node><Service ip_protocol="6"><Portlist>8080</Portlist></Service></System></Flow></EventData><AdditionalData dtype="string" meaning="guid">mygroup.example.com</AdditionalData><AdditionalData dtype="string" meaning="sharewith">leo.example.com</AdditionalData><AdditionalData dtype="string" meaning="sharewith">partners.example.com</AdditionalData></Incident></IODEF-Document>
101              
102             =head1 DESCRIPTION
103              
104             This module makes it a bit simpler to crank out XML+IODEF messages. It uses what it finds under XML/IODEF/Simple/Plugin/ to adapt "defaults" to the keypairs it takes in. To allow for other default settings / manipulations, create XML::IODEF::Simple::Plugin::MyPlugin and Module::Pluggable will pick it up on the fly. See XML::IODEF::Simple::Plugin::Ipv4 as an example.
105              
106             This module takes into account some of the work done with the Collective Intelligence Framework. It makes assumptions about severity based on the impact given. Up to date documentation surrounding this taxonomy can be found at http://code.google.com/p/collective-intelligence-framework/wiki/Taxonomy
107              
108             =head1 Addons
109              
110             To enhance the exchange of XML::IODEF based messages, the 'sharewith' and 'guid' tags have been added to IncidentAdditionalData
111              
112             =head2 sharewith
113              
114             A comma-seperated or array value that denotes what other federations a derivative of this message may be shared with. These are usually denoted by a FQDN:
115             grp1.example.com
116             grp2.example.com
117             leo.example.com
118              
119             =head2 guid
120              
121             A simple FQDN used (in CIF) as a unix-style permission that denotes what groups within a federation can have access to this data. Groups are simple strings, in this example we use FQDN's to ensure unique-ness throughout a federation. Typically groups are hashed into v5 uuid's behind the scenes.
122              
123             =head1 EXAMPLES
124              
125             =head2 Botnet
126              
127             Typically a high-severity observation
128              
129             =head2 Malware / Exploit
130              
131             Typically a medium-severity observation
132              
133             =head2 Phishing
134              
135             Typically a medium-severity observation
136              
137             =head2 Highjacked
138              
139             Typcially a medium-severity observation
140              
141             =head1 PLUGINS
142              
143             This module can be extended at run-time by adding plugins under XML::IODEF::Simple::Plugin (eg: XML::IODEF::Simple::Plugin::MyPlug). See the lib/XML/IODEF/Simple/Plugin directory or XML::IODEF::Simple::Plugin::TLP for more examples.
144              
145             =head1 SEE ALSO
146              
147             XML::IODEF, http://code.google.com/p/collective-intelligence-framework/
148              
149             =head1 AUTHOR
150              
151             Wes Young, E<lt>wes@barely3am.comE<gt>
152              
153             =head1 COPYRIGHT AND LICENSE
154              
155             Copyright 2011 The Trustees of Indiana University, indiana.edu
156             Copyright 2011 REN-ISAC, ren-isac.net
157             Copyright 2011 Wes Young, claimid.com/wesyoung
158              
159             This library is free software; you can redistribute it and/or modify
160             it under the same terms as Perl itself, either Perl version 5.10.0 or,
161             at your option, any later version of Perl 5 you may have available.
162              
163              
164             =cut