Blog: How-Tos
Auditing AWS Security Groups
It’s difficult to run through and check a substantial list of AWS security groups using the console, so I wanted to dump it out as easily parsable text. To do this I followed these steps:
1. install AWS client. I used Linux, but there’s a Windows MSI as well:
http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html
2. configure it with access keys – create a new read only user for this purpose:
http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: eu-west-1
Default output format [None]: json
3. You should then be able to get the JSON output for the security groups, like this:
{
“SecurityGroups”: [
{
“IpPermissionsEgress”: [
{
“IpProtocol”: “-1”,
“IpRanges”: [
{
“CidrIp”: “0.0.0.0/0”
}
],
“UserIdGroupPairs”: []
}
],
“Description”: “SSH access”,
“Tags”: [
…
4. the following Security Groups Perl audit script can be used to parse this – mine is saved as json.pl for example. I had to also install the JSON parsing library with “apt-get install libjson-*perl” on Debian Linux, though CPAN should be able to do this on Windows.
use JSON qw( decode_json );
my $json = do { local $/; <STDIN> };
my $decoded = decode_json($json);
my @secgrp = @{ $decoded->{‘SecurityGroups’} };
foreach my $f ( @secgrp ) {
$desc=$f->{“Description”};
$group=$f->{“GroupName”};
my @ipperm = @{ $f->{‘IpPermissions’} };
foreach my $g ( @ipperm ) {
$toport=$g->{‘ToPort’};
$fromport=$g->{‘FromPort’};
$proto=$g->{‘IpProtocol’};
my @cidr = @{ $g->{‘IpRanges’} };
foreach my $h ( @cidr ) {
$cidr=$h->{‘CidrIp’};
print “Group Name : $group\n”;
print “Description: $desc\n”;
if ($proto==-1) {
print “any IP traffic, from source $cidr\n”;
} else {
if ($fromport ne $toport) {
print “ports $fromport:$toport/$proto, from source $cidr\n”;
} else {
print “port $fromport/$proto, from source $cidr\n”;
}
}
print “\n”;
}
}
}
5. Run this for the appropriate region, and it will display the inbound rules only:
Group Name : SomeGroup
Description: SSH Access
port 22/tcp, from source 0.0.0.0/0
…
Then you can search for potentially dangerous rules – in this case, I was interested in access from anywhere to particular services, but this currently gives the full list. You can always search for “0.0.0.0” for any source, or for “23/tcp” if you’re worried about telnet for example.
If you like you could also run it daily and diff the output against a known good version of the output to see if any unexpected changes have happened.
UPDATE: Read part 2 for the improved Perl script, and a new one for S3 buckets.