From e1708af1bb8d44dbef05b9f495c4e276158238fb Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Thu, 13 Aug 2020 00:34:00 +0500 Subject: [PATCH 01/76] SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation --- collectors/aws/collector.js | 6 + exports.js | 388 +++++++++--------- .../aws/cloudformation/plainTextParameters.js | 70 ++++ 3 files changed, 270 insertions(+), 194 deletions(-) create mode 100644 plugins/aws/cloudformation/plainTextParameters.js diff --git a/collectors/aws/collector.js b/collectors/aws/collector.js index be291cf944..fe386d0b27 100644 --- a/collectors/aws/collector.js +++ b/collectors/aws/collector.js @@ -60,6 +60,12 @@ var calls = { } } }, + CloudFormation: { + describeStacks: { + property: 'Stacks', + paginate: 'NextToken' + } + }, CloudFront: { // TODO: Pagination is using an older format listDistributions: { diff --git a/exports.js b/exports.js index 912d562838..f8dac891a1 100644 --- a/exports.js +++ b/exports.js @@ -2,200 +2,200 @@ module.exports = { aws : { - 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), - 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), - 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), - 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), - 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), - 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), - 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), - 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), - 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), - 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), - 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - - 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), - 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), - 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), - 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), - 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), - 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), - 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), - - 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), - - 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), - - 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), - - 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), - 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), - 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), - 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), - 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), - 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), - 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), - 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), - 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), - 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), - 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), - 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), - 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), - 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), - 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), - 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), - 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), - 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), - 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), - 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), - 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), - 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), - 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), - 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), - 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), - 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), - 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), - 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), - 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), - 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), - 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), - 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), - 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), - 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), - 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), - 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), - 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), - 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), - 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), - 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), - 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), - 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), - 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), - 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), - 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), - 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), - 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), - - 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), - - 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), - 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), - - 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), - 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), - 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), - 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), - - 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), - 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), - 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), - 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), - - 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), - 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), - 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), - 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), - - 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), - 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), - 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), - 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), - 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), - 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), - 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), - - 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), - 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), - 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), - 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), - 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), - 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), - 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), - 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), - 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), - 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), - 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), - 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), - 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), - 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), - 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), - 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), - 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), - 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), - 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), - 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), - 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), - 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), - 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), - 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), - 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), - 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), - 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), - 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), - 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), - 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), - 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), - 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), - - 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), - 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), - 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), - 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), - 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), - 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), - 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), - 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), - - 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), - 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), - 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), - - 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), - 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), - 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), - 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), - 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), - 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), - 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), - 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), - 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), - 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), - - 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), - 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), - - 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), - - 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), - 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), - 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), - - 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), - 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), - 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), - - 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), - 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), - 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), - 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), - - 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), - - 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), - 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), - - 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), - - 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), - 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), - 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), - - 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), - 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), - 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), - 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), - - 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js') + // 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), + // 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), + // 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), + // 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), + // 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), + // 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), + // 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), + // 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), + // 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), + // 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), + // 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), + 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), + // 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), + // 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), + // 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), + // 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), + // 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), + // 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), + // 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), + + // 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), + + // 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), + + // 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), + + // 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), + // 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), + // 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), + // 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), + // 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), + // 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), + // 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), + // 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), + // 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), + // 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), + // 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), + // 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), + // 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), + // 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), + // 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), + // 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), + // 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), + // 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), + // 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), + // 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), + // 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), + // 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), + // 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), + // 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), + // 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), + // 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), + // 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), + // 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), + // 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), + // 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), + // 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), + // 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), + // 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), + // 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), + // 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), + // 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), + // 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), + // 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), + // 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), + // 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), + // 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), + // 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), + // 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), + // 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), + // 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), + // 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), + // 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), + + // 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), + + // 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), + // 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), + + // 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), + // 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), + // 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), + // 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), + + // 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), + // 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), + // 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), + // 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), + + // 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), + // 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), + // 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), + // 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), + + // 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), + // 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), + // 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), + // 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), + // 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), + // 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), + // 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), + + // 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), + // 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), + // 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), + // 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), + // 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), + // 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), + // 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), + // 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), + // 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), + // 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), + // 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), + // 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), + // 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), + // 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), + // 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), + // 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), + // 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), + // 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), + // 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), + // 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), + // 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), + // 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), + // 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), + // 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), + // 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), + // 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), + // 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), + // 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), + // 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), + // 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), + // 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), + // 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), + + // 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), + // 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), + // 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), + // 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), + // 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), + // 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), + // 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), + // 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), + + // 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), + // 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), + // 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), + + // 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), + // 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), + // 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), + // 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), + // 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), + // 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), + // 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), + // 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), + // 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), + // 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), + + // 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), + // 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), + + // 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), + + // 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), + // 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), + // 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), + + // 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), + // 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), + // 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), + + // 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), + // 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), + // 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), + // 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), + + // 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), + + // 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), + // 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), + + // 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), + + // 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), + // 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), + // 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), + + // 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), + // 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), + // 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), + // 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), + + // 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js') }, azure : { 'fileServiceEncryption' : require(__dirname + '/plugins/azure/storageaccounts/fileServiceEncryption.js'), diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js new file mode 100644 index 0000000000..658dc42f3d --- /dev/null +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -0,0 +1,70 @@ +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'CloudFormation Plaintext Parameters', + category: 'CloudFormation', + description: 'Ensures CloudFormation parameters that reference sensitive values are configured to use NoEcho.', + more_info: 'CloudFormation supports the NoEcho property for sensitive values, which should be used to ensure secrets are not exposed in the CloudFormation UI and APIs.', + link: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html', + recommended_action: 'Update the sensitive parameters to use the NoEcho property.', + apis: ['CloudFormation:describeStacks'], + compliance: { + hipaa: 'HIPAA requires all data to be transmitted over secure channels. ' + + 'CloudFront HTTPS redirection should be used to ensure site visitors ' + + 'are always connecting over a secure channel.' + }, + // settings : { secretWords : ["password", "privatekey", "secret"] }, + + run: function(cache, settings, callback) { + + var results = []; + var source = {}; + + var region = helpers.defaultRegion(settings); + + var describeStacks = helpers.addSource(cache, source, + ['cloudformation', 'describeStacks', region]); + + console.log(describeStacks); + console.log("results received"); + // if (!describeStacks) return callback(null, results, source); + + // if (describeStacks.err || !describeStacks.data) { + // helpers.addResult(results, 3, + // 'Unable to describe stacks: ' + helpers.addError(describeStacks)); + // return callback(null, results, source); + // } + + // if (!describeStacks.data.length) { + // helpers.addResult(results, 0, 'No stacks descriptions found'); + // return callback(null, results, source); + // } + // console.log(describeStacks.data); + // loop through stacks for every template retrieval + // describeStacks.data.forEach(function(Distribution){ + // var stackTemplate = helpers.addSource(cache, source, + // ['cloudformation', 'getTemplate', region]); + + // if (!describeStacks) return callback(null, results, source); + + // if (describeStacks.err || !describeStacks.data) { + // helpers.addResult(results, 3, + // 'Unable to describe stacks: ' + helpers.addError(describeStacks)); + // return callback(null, results, source); + // } + + // if (Distribution.DefaultCacheBehavior.ViewerProtocolPolicy == 'redirect-to-https') { + // helpers.addResult(results, 0, 'CloudFront distribution ' + + // 'is configured to redirect non-HTTPS traffic to HTTPS', 'global', Distribution.ARN); + // } else if (Distribution.DefaultCacheBehavior.ViewerProtocolPolicy == 'https-only') { + // helpers.addResult(results, 0, 'The CloudFront ' + + // 'distribution is set to use HTTPS only.', 'global', Distribution.ARN); + // } else { + // helpers.addResult(results, 2, 'CloudFront distribution ' + + // 'is not configured to use HTTPS', 'global', Distribution.ARN); + // } + // }); + + callback(null, results, source); + } +}; \ No newline at end of file From 2122ade6414d7ce065c47a3e5841b9ca454a493a Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 13 Aug 2020 19:59:59 +0500 Subject: [PATCH 02/76] Added vpcEndpointAcceptance plugin and spec file --- collectors/aws/collector.js | 4 + plugins/aws/ec2/vpcEndpointAcceptance.js | 57 +++++++ plugins/aws/ec2/vpcEndpointAcceptance.spec.js | 141 ++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 plugins/aws/ec2/vpcEndpointAcceptance.js create mode 100644 plugins/aws/ec2/vpcEndpointAcceptance.spec.js diff --git a/collectors/aws/collector.js b/collectors/aws/collector.js index be291cf944..20a75b5269 100644 --- a/collectors/aws/collector.js +++ b/collectors/aws/collector.js @@ -230,6 +230,10 @@ var calls = { ] } }, + describeVpcEndpointServices: { + property: 'ServiceDetails', + paginate: 'NextToken' + }, describeRouteTables: { property: 'RouteTables', paginate: 'NextToken' diff --git a/plugins/aws/ec2/vpcEndpointAcceptance.js b/plugins/aws/ec2/vpcEndpointAcceptance.js new file mode 100644 index 0000000000..9d0530bd7e --- /dev/null +++ b/plugins/aws/ec2/vpcEndpointAcceptance.js @@ -0,0 +1,57 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'VPC PrivateLink Endpoint Acceptance Required', + category: 'EC2', + description: 'Ensures VPC PrivateLink endpoints require acceptance', + more_info: 'VPC PrivateLink endpoints should be configured to require acceptance so that access to the endpoint is controlled on a case-by-case basis.', + recommended_action: 'Update the VPC PrivateLink endpoint to require acceptance', + link: 'https://docs.aws.amazon.com/vpc/latest/userguide/accept-reject-endpoint-requests.html', + apis: ['EC2:describeVpcEndpointServices'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.ec2, function(region, rcb){ + var describeVpcEndpointServices = helpers.addSource(cache, source, + ['ec2', 'describeVpcEndpointServices', region]); + + if (!describeVpcEndpointServices) return rcb(); + + if (describeVpcEndpointServices.err || !describeVpcEndpointServices.data) { + helpers.addResult(results, 3, + 'Unable to query for VPC endpoint services: ' + helpers.addError(describeVpcEndpointServices), region); + return rcb(); + } + + describeVpcEndpointServices.data = describeVpcEndpointServices.data.filter(service => service.Owner != 'amazon'); + + if (!describeVpcEndpointServices.data.length) { + helpers.addResult(results, 0, + 'No user owned VPC endpoint services present', region); + return rcb(); + } + + for (var s in describeVpcEndpointServices.data) { + var service = describeVpcEndpointServices.data[s]; + var resource = service.ServiceName; + if (service.AcceptanceRequired) { + helpers.addResult(results, 0, + 'VPC endpoint service ' + (service.ServiceId) + ' requires acceptance by the service owner', + region, resource); + } else { + helpers.addResult(results, 2, + 'VPC endpoint service ' + (service.ServiceId) + ' does not require acceptance by the service owner', + region, resource); + } + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; \ No newline at end of file diff --git a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js new file mode 100644 index 0000000000..0946f5a682 --- /dev/null +++ b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js @@ -0,0 +1,141 @@ +var expect = require('chai').expect; +const vpcEndpointAcceptance = require('./vpcEndpointAcceptance'); + +const vpcEndpointServices = [ + { + "ServiceName": "com.amazonaws.vpce.us-east-1.vpce-svc-09d3a6a098dce6e8c", + "ServiceId": "vpce-svc-09d3a6a098dce6e8c", + "ServiceType": [ + { + "ServiceType": "Interface" + } + ], + "AvailabilityZones": [ + "us-east-1a", + "us-east-1b" + ], + "Owner": "560213429563", + "BaseEndpointDnsNames": [ + "vpce-svc-09d3a6a098dce6e8c.us-east-1.vpce.amazonaws.com" + ], + "VpcEndpointPolicySupported": false, + "AcceptanceRequired": true, + "ManagesVpcEndpoints": false, + "Tags": [] + }, + { + "ServiceName": "com.amazonaws.vpce.us-east-1.vpce-svc-09145867a106679a3", + "ServiceId": "vpce-svc-09145867a106679a3", + "ServiceType": [ + { + "ServiceType": "Interface" + } + ], + "AvailabilityZones": [ + "us-east-1a", + "us-east-1b", + "us-east-1c" + ], + "Owner": "560213429563", + "BaseEndpointDnsNames": [ + "vpce-svc-09145867a106679a3.us-east-1.vpce.amazonaws.com" + ], + "VpcEndpointPolicySupported": false, + "AcceptanceRequired": false, + "ManagesVpcEndpoints": false, + "Tags": [] + }, +] + +const createCache = (ServiceDetails) => { + return { + ec2: { + describeVpcEndpointServices: { + 'us-east-1': { + data: ServiceDetails + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + ec2: { + describeVpcEndpointServices: { + 'us-east-1': { + err: { + message: 'error describing VPC endpoint services' + }, + }, + }, + }, + }; +}; + +const createNullCache = () => { + return { + ec2: { + describeVpcEndpointServices: { + 'us-east-1': null, + }, + }, + }; +}; + +describe('vpcEndpointAcceptance', function () { + describe('run', function () { + it('should PASS if VPC endpoint service requires acceptance by the service owner', function (done) { + const cache = createCache([vpcEndpointServices[0]]); + vpcEndpointAcceptance.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should FAIL if VPC endpoint service does not require acceptance by the service owner', function (done) { + const cache = createCache([vpcEndpointServices[1]]); + vpcEndpointAcceptance.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should PASS if no VPC endpoint service is detected', function (done) { + const cache = createCache([]); + vpcEndpointAcceptance.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should PASS if no VPC endpoint services are detected', function (done) { + const cache = createCache([]); + vpcEndpointAcceptance.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should UNKNOWN if there was an error querying for VPC endpoint services', function (done) { + const cache = createErrorCache(); + vpcEndpointAcceptance.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should not return any results if unable to query for VPC endpoint services', function (done) { + const cache = createNullCache(); + vpcEndpointAcceptance.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); From 306d7218921e93751176dc09b524f8fa18639608 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 14 Aug 2020 05:55:55 +0500 Subject: [PATCH 03/76] SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation --- exports.js | 386 +++++++++--------- helpers/aws/regions.js | 1 + index.js | 8 +- .../aws/cloudformation/plainTextParameters.js | 91 ++--- .../plainTextParameters.spec.js | 161 ++++++++ 5 files changed, 406 insertions(+), 241 deletions(-) create mode 100644 plugins/aws/cloudformation/plainTextParameters.spec.js diff --git a/exports.js b/exports.js index f8dac891a1..fa901a2af7 100644 --- a/exports.js +++ b/exports.js @@ -2,200 +2,200 @@ module.exports = { aws : { - // 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), - // 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), - // 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), - // 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), - // 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), - // 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), - // 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), - // 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), - // 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), - // 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), - // 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), + 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), + 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), + 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), + 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), + 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), + 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), + 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), + 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), + 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), + 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), + 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), - // 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), - // 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), - // 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), - // 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), - // 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), - // 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), - // 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), - - // 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), - - // 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), - - // 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), - - // 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), - // 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), - // 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), - // 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), - // 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), - // 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), - // 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), - // 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), - // 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), - // 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), - // 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), - // 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), - // 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), - // 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), - // 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), - // 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), - // 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), - // 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), - // 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), - // 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), - // 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), - // 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), - // 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), - // 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), - // 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), - // 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), - // 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), - // 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), - // 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), - // 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), - // 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), - // 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), - // 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), - // 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), - // 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), - // 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), - // 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), - // 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), - // 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), - // 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), - // 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), - // 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), - // 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), - // 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), - // 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), - // 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), - // 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), - - // 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), - - // 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), - // 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), - - // 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), - // 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), - // 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), - // 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), - - // 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), - // 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), - // 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), - // 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), - - // 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), - // 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), - // 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), - // 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), - - // 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), - // 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), - // 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), - // 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), - // 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), - // 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), - // 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), - - // 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), - // 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), - // 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), - // 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), - // 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), - // 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), - // 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), - // 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), - // 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), - // 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), - // 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), - // 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), - // 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), - // 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), - // 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), - // 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), - // 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), - // 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), - // 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), - // 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), - // 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), - // 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), - // 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), - // 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), - // 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), - // 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), - // 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), - // 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), - // 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), - // 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), - // 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), - // 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), - - // 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), - // 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), - // 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), - // 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), - // 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), - // 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), - // 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), - // 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), - - // 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), - // 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), - // 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), - - // 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), - // 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), - // 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), - // 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), - // 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), - // 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), - // 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), - // 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), - // 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), - // 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), - - // 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), - // 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), - - // 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), - - // 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), - // 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), - // 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), - - // 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), - // 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), - // 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), - - // 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), - // 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), - // 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), - // 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), - - // 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), - - // 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), - // 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), - - // 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), - - // 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), - // 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), - // 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), - - // 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), - // 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), - // 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), - // 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), - - // 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js') + 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), + 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), + 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), + 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), + 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), + 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), + 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), + + 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), + + 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), + + 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), + + 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), + 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), + 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), + 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), + 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), + 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), + 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), + 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), + 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), + 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), + 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), + 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), + 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), + 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), + 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), + 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), + 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), + 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), + 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), + 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), + 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), + 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), + 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), + 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), + 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), + 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), + 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), + 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), + 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), + 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), + 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), + 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), + 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), + 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), + 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), + 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), + 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), + 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), + 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), + 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), + 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), + 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), + 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), + 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), + 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), + 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), + 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), + + 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), + + 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), + 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), + + 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), + 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), + 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), + 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), + + 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), + 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), + 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), + 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), + + 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), + 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), + 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), + 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), + + 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), + 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), + 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), + 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), + 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), + 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), + 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), + + 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), + 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), + 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), + 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), + 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), + 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), + 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), + 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), + 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), + 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), + 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), + 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), + 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), + 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), + 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), + 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), + 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), + 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), + 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), + 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), + 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), + 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), + 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), + 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), + 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), + 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), + 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), + 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), + 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), + 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), + 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), + 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), + + 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), + 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), + 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), + 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), + 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), + 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), + 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), + 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), + + 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), + 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), + 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), + + 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), + 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), + 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), + 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), + 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), + 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), + 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), + 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), + 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), + 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), + + 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), + 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), + + 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), + + 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), + 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), + 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), + + 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), + 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), + 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), + + 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), + 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), + 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), + 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), + + 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), + + 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), + 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), + + 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), + + 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), + 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), + 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), + + 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), + 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), + 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), + 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), + + 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js') }, azure : { 'fileServiceEncryption' : require(__dirname + '/plugins/azure/storageaccounts/fileServiceEncryption.js'), diff --git a/helpers/aws/regions.js b/helpers/aws/regions.js index 4609df93b3..3749d0093f 100644 --- a/helpers/aws/regions.js +++ b/helpers/aws/regions.js @@ -35,6 +35,7 @@ module.exports = { route53: ['us-east-1'], route53domains: ['us-east-1'], s3: ['us-east-1'], + cloudformation: regions, cloudtrail: regions, cloudwatchlogs: regions, configservice: regions, diff --git a/index.js b/index.js index 3b97033a22..cceed66ab0 100644 --- a/index.js +++ b/index.js @@ -113,7 +113,13 @@ if(process.env.GOOGLE_APPLICATION_CREDENTIALS){ } // Custom settings - place plugin-specific settings here -var settings = {}; +var settings = { + plainTextParameters: { + secretWords: [ + 'secret', 'password', 'privatekey' + ] + } +}; // If running in GovCloud, uncomment the following // settings.govcloud = true; diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 658dc42f3d..6075fd59f7 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -1,3 +1,4 @@ +var async = require('async'); var helpers = require('../../../helpers/aws'); module.exports = { @@ -8,63 +9,59 @@ module.exports = { link: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html', recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], - compliance: { - hipaa: 'HIPAA requires all data to be transmitted over secure channels. ' + - 'CloudFront HTTPS redirection should be used to ensure site visitors ' + - 'are always connecting over a secure channel.' - }, - // settings : { secretWords : ["password", "privatekey", "secret"] }, run: function(cache, settings, callback) { - var results = []; var source = {}; + var regions = helpers.regions(settings); + secretWords = settings.plainTextParameters.secretWords; - var region = helpers.defaultRegion(settings); + async.each(regions.cloudformation, function(region, rcb){ - var describeStacks = helpers.addSource(cache, source, - ['cloudformation', 'describeStacks', region]); + var describeStacks = helpers.addSource(cache, source, + ['cloudformation', 'describeStacks', region]); + + if (!describeStacks) return rcb(); - console.log(describeStacks); - console.log("results received"); - // if (!describeStacks) return callback(null, results, source); + if (describeStacks.err || !describeStacks.data) { + helpers.addResult(results, 3, + 'Unable to describe stacks: ' + helpers.addError(describeStacks), region); + return rcb(); + } - // if (describeStacks.err || !describeStacks.data) { - // helpers.addResult(results, 3, - // 'Unable to describe stacks: ' + helpers.addError(describeStacks)); - // return callback(null, results, source); - // } + if (!describeStacks.data.length) { + helpers.addResult(results, 0, 'No stack description found', region); + return rcb(); + } + + var parameterFound; + describeStacks.data.forEach(function(stack){ + parameterFound = false; - // if (!describeStacks.data.length) { - // helpers.addResult(results, 0, 'No stacks descriptions found'); - // return callback(null, results, source); - // } - // console.log(describeStacks.data); - // loop through stacks for every template retrieval - // describeStacks.data.forEach(function(Distribution){ - // var stackTemplate = helpers.addSource(cache, source, - // ['cloudformation', 'getTemplate', region]); - - // if (!describeStacks) return callback(null, results, source); - - // if (describeStacks.err || !describeStacks.data) { - // helpers.addResult(results, 3, - // 'Unable to describe stacks: ' + helpers.addError(describeStacks)); - // return callback(null, results, source); - // } + if(!stack.Parameters.length) { + helpers.addResult(results, 0, + 'The template did not contain any potentially-sensitive parameters', region); + return; + } - // if (Distribution.DefaultCacheBehavior.ViewerProtocolPolicy == 'redirect-to-https') { - // helpers.addResult(results, 0, 'CloudFront distribution ' + - // 'is configured to redirect non-HTTPS traffic to HTTPS', 'global', Distribution.ARN); - // } else if (Distribution.DefaultCacheBehavior.ViewerProtocolPolicy == 'https-only') { - // helpers.addResult(results, 0, 'The CloudFront ' + - // 'distribution is set to use HTTPS only.', 'global', Distribution.ARN); - // } else { - // helpers.addResult(results, 2, 'CloudFront distribution ' + - // 'is not configured to use HTTPS', 'global', Distribution.ARN); - // } - // }); + stack.Parameters.forEach(function(parameter){ + if(secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameterFound) { + parameterFound = true; + helpers.addResult(results, 1, + 'The template contained one of the following potentially-sensitive parameters: secret, key, password', region); + return; + } + }); + + if(!parameterFound) { + helpers.addResult(results, 0, + 'The template did not contain any potentially-sensitive parameters', region); + } - callback(null, results, source); + }); + rcb(); + }, function(){ + callback(null, results, source); + }); } }; \ No newline at end of file diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js new file mode 100644 index 0000000000..792f454333 --- /dev/null +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -0,0 +1,161 @@ +var expect = require('chai').expect; +const plainTextParameters = require('./plainTextParameters'); +const settings = { + plainTextParameters: { + secretWords: [ + 'secret', 'password', 'privatekey' + ] + } +}; +const describeStacks = [ + { + StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', + StackName: 'TestStack', + Parameters: [ + { + ParameterKey: 'Secret', + ParameterValue: 'bucketwithsecretparameter1' + }, + { + ParameterKey: 'Password', + ParameterValue: 'bucketwithsecretparameter1' + } + ], + CreationTime: '2020-08-13T13:34:52.435Z', + RollbackConfiguration: { RollbackTriggers: [] }, + StackStatus: 'CREATE_COMPLETE', + DisableRollback: false, + NotificationARNs: [], + Capabilities: [], + Outputs: [], + Tags: [], + DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } + }, + { + StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', + StackName: 'TestStack', + Parameters: [ + { + ParameterKey: 'S3BucketName', + ParameterValue: 'testbucketplaintext1' + } + ], + CreationTime: '2020-08-12T09:42:04.803Z', + RollbackConfiguration: { RollbackTriggers: [] }, + StackStatus: 'CREATE_COMPLETE', + DisableRollback: false, + NotificationARNs: [], + Capabilities: [], + Outputs: [], + Tags: [], + DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } + }, + { + StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', + StackName: 'TestStack', + Parameters: [], + CreationTime: '2020-08-12T09:42:04.803Z', + RollbackConfiguration: { RollbackTriggers: [] }, + StackStatus: 'CREATE_COMPLETE', + DisableRollback: false, + NotificationARNs: [], + Capabilities: [], + Outputs: [], + Tags: [], + DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } + } +] + +const createCache = (stacks) => { + return { + cloudformation: { + describeStacks: { + 'us-east-1': { + data: stacks + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + cloudformation: { + describeStacks: { + 'us-east-1': { + err: { + message: 'error describing cloudformation stacks' + }, + }, + }, + }, + }; +}; + +const createNullCache = () => { + return { + cloudformation: { + describeStacks: { + 'us-east-1': null, + }, + }, + }; +}; + +describe('plainTextParameters', function () { + describe('run', function () { + it('should FAIL if Stack parameters contain one of secret words ["password" , "privatekey", "secret"]', function (done) { + const cache = createCache([describeStacks[0]]); + plainTextParameters.run(cache, settings, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); + done(); + }); + }); + + it('should PASS if Stack parameters does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { + const cache = createCache([describeStacks[1]]); + plainTextParameters.run(cache, settings, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should PASS if unable to describe stacks', function (done) { + const cache = createCache([]); + plainTextParameters.run(cache, settings, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should PASS if there is no parameter in the stack', function (done) { + const cache = createCache([describeStacks[2]]); + plainTextParameters.run(cache, settings, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should not return any results if unable to fetch any stack description', function (done) { + const cache = createNullCache(); + plainTextParameters.run(cache, settings, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + + it('should UNKNOWN if error occurs while fetching stack description', function (done) { + const cache = createErrorCache(); + plainTextParameters.run(cache, settings, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + }); +}); \ No newline at end of file From 7c8616c9c54503cb3c9e2f7b565fd89478a21bef Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 15:30:57 +0500 Subject: [PATCH 04/76] Added plugin and spec file for launch wizard security groups --- exports.js | 4 +- plugins/aws/ec2/launchWizardSecurityGroups.js | 55 +++++++ .../ec2/launchWizardSecurityGroups.spec.js | 153 ++++++++++++++++++ plugins/aws/ec2/vpcEndpointAcceptance.spec.js | 9 -- 4 files changed, 211 insertions(+), 10 deletions(-) create mode 100644 plugins/aws/ec2/launchWizardSecurityGroups.js create mode 100644 plugins/aws/ec2/launchWizardSecurityGroups.spec.js diff --git a/exports.js b/exports.js index 912d562838..0c8b893a09 100644 --- a/exports.js +++ b/exports.js @@ -29,6 +29,7 @@ module.exports = { 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), + 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), @@ -71,8 +72,9 @@ module.exports = { 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), - 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), + 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), + 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), diff --git a/plugins/aws/ec2/launchWizardSecurityGroups.js b/plugins/aws/ec2/launchWizardSecurityGroups.js new file mode 100644 index 0000000000..252cabd11c --- /dev/null +++ b/plugins/aws/ec2/launchWizardSecurityGroups.js @@ -0,0 +1,55 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'EC2 LaunchWizard Security Groups', + category: 'EC2', + description: 'Ensures security groups created by the EC2 launch wizard are not used', + more_info: 'The EC2 launch wizard frequently creates insecure security groups that are exposed publicly. These groups should not be used and custom security groups should be created instead.', + link: 'https://docs.aws.amazon.com/launchwizard/latest/userguide/launch-wizard-sap-security-groups.html', + recommended_action: 'Delete the launch wizard security group and replace it with a custom security group.', + apis: ['EC2:describeSecurityGroups'], + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + async.each(regions.ec2, function(region, rcb){ + var describeSecurityGroups = helpers.addSource(cache, source, + ['ec2', 'describeSecurityGroups', region]); + + if (!describeSecurityGroups) return rcb(); + + if (describeSecurityGroups.err || !describeSecurityGroups.data) { + helpers.addResult(results, 3, + 'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region); + return rcb(); + } + + if (!describeSecurityGroups.data.length) { + helpers.addResult(results, 0, 'No security groups present', region); + return rcb(); + } + + for (var s in describeSecurityGroups.data) { + var sg = describeSecurityGroups.data[s]; + var resource = sg.GroupId; + + if (sg.GroupName.toLowerCase().startsWith('launch-wizard')) { + helpers.addResult(results, 2, + 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', + region, resource); + } else { + helpers.addResult(results, 0, + 'Security Group ' + sg.GroupName + ' was not launched using EC2 launch wizard', + region, resource); + } + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/ec2/launchWizardSecurityGroups.spec.js b/plugins/aws/ec2/launchWizardSecurityGroups.spec.js new file mode 100644 index 0000000000..a2b8baa2e9 --- /dev/null +++ b/plugins/aws/ec2/launchWizardSecurityGroups.spec.js @@ -0,0 +1,153 @@ +var expect = require('chai').expect; +const launchWizardSecurityGroups = require('./launchWizardSecurityGroups'); + +const securityGroups = [ + { + "Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00", + "GroupName": "launch-wizard-1", + "IpPermissions": [ + { + "FromPort": 22, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "ToPort": 22, + "UserIdGroupPairs": [] + } + ], + "OwnerId": "560213429563", + "GroupId": "sg-0ff1642cae23c309a", + "IpPermissionsEgress": [ + { + "IpProtocol": "-1", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "UserIdGroupPairs": [] + } + ], + "Tags": [], + "VpcId": "vpc-99de2fe4" + }, + { + "Description": "Allows SSh access to developer", + "GroupName": "spec-test-sg", + "IpPermissions": [], + "OwnerId": "560213429563", + "GroupId": "sg-0b5f2771716acfee4", + "IpPermissionsEgress": [ + { + "FromPort": 22, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [ + { + "CidrIpv6": "::/0" + } + ], + "PrefixListIds": [], + "ToPort": 22, + "UserIdGroupPairs": [] + } + ], + "Tags": [], + "VpcId": "vpc-99de2fe4" + } + ]; + +const createCache = (securityGroups) => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': { + data: securityGroups + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': { + err: { + message: 'error describing security groups' + }, + }, + }, + }, + }; +}; + +const createNullCache = () => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': null, + }, + }, + }; +}; + +describe('launchWizardSecurityGroups', function () { + describe('run', function () { + it('should PASS if security groups was not created using EC2 launch wizard', function (done) { + const cache = createCache([securityGroups[1]]); + launchWizardSecurityGroups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should FAIL if security groups was created using EC2 launch wizard', function (done) { + const cache = createCache([securityGroups[0]]); + launchWizardSecurityGroups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should PASS if no security groups are detected', function (done) { + const cache = createCache([]); + launchWizardSecurityGroups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should UNKNOWN if there was an error describing security groups', function (done) { + const cache = createErrorCache(); + launchWizardSecurityGroups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should not return any results if unable to query for security groups', function (done) { + const cache = createNullCache(); + launchWizardSecurityGroups.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + }); +}); diff --git a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js index 0946f5a682..62053b7238 100644 --- a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js +++ b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js @@ -112,15 +112,6 @@ describe('vpcEndpointAcceptance', function () { }); }); - it('should PASS if no VPC endpoint services are detected', function (done) { - const cache = createCache([]); - vpcEndpointAcceptance.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); - done(); - }); - }); - it('should UNKNOWN if there was an error querying for VPC endpoint services', function (done) { const cache = createErrorCache(); vpcEndpointAcceptance.run(cache, {}, (err, results) => { From 3da6672d99647eeb68b4966e069826edf6319e4c Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 16:50:46 +0500 Subject: [PATCH 05/76] Refactored code in plaintextParameters plugin and spec file --- exports.js | 4 ++- index.js | 8 +----- .../aws/cloudformation/plainTextParameters.js | 28 +++++++++++++------ .../plainTextParameters.spec.js | 28 ++++++++----------- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/exports.js b/exports.js index 56084148d3..ee2b81f9ee 100644 --- a/exports.js +++ b/exports.js @@ -13,7 +13,9 @@ module.exports = { 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), + + 'plaintextParameters' : require(__dirname + '/plugins/aws/cloudformation/plaintextParameters.js'), + 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), diff --git a/index.js b/index.js index cceed66ab0..3b97033a22 100644 --- a/index.js +++ b/index.js @@ -113,13 +113,7 @@ if(process.env.GOOGLE_APPLICATION_CREDENTIALS){ } // Custom settings - place plugin-specific settings here -var settings = { - plainTextParameters: { - secretWords: [ - 'secret', 'password', 'privatekey' - ] - } -}; +var settings = {}; // If running in GovCloud, uncomment the following // settings.govcloud = true; diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 6075fd59f7..2ed03af7f0 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -9,12 +9,19 @@ module.exports = { link: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html', recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], + settings: { + plainTextParameters: { + secretWords: [ + 'secret', 'password', 'privatekey' + ] + } + }, run: function(cache, settings, callback) { var results = []; var source = {}; var regions = helpers.regions(settings); - secretWords = settings.plainTextParameters.secretWords; + secretWords = this.settings.plainTextParameters.secretWords; async.each(regions.cloudformation, function(region, rcb){ @@ -35,30 +42,33 @@ module.exports = { } var parameterFound; - describeStacks.data.forEach(function(stack){ + for (var s in describeStacks.data){ + // arn:aws:cloudformation:region:account-id:stack/stack-name/stack-id + var stack = describeStacks.data[s]; + var resource = stack.StackId; parameterFound = false; if(!stack.Parameters.length) { helpers.addResult(results, 0, - 'The template did not contain any potentially-sensitive parameters', region); - return; + 'The template does not contain any potentially-sensitive parameters', region, resource); + return rcb(); } stack.Parameters.forEach(function(parameter){ - if(secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameterFound) { + if(!parameterFound && secretWords.includes(parameter.ParameterKey.toLowerCase())) { parameterFound = true; helpers.addResult(results, 1, - 'The template contained one of the following potentially-sensitive parameters: secret, key, password', region); - return; + 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); } }); if(!parameterFound) { helpers.addResult(results, 0, - 'The template did not contain any potentially-sensitive parameters', region); + 'Template does not contain any potentially-sensitive parameters', region, resource); } - }); + } + rcb(); }, function(){ callback(null, results, source); diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index 792f454333..490d978002 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -1,12 +1,6 @@ var expect = require('chai').expect; -const plainTextParameters = require('./plainTextParameters'); -const settings = { - plainTextParameters: { - secretWords: [ - 'secret', 'password', 'privatekey' - ] - } -}; +const plaintextParameters = require('./plaintextParameters'); + const describeStacks = [ { StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', @@ -102,20 +96,20 @@ const createNullCache = () => { }; }; -describe('plainTextParameters', function () { +describe('plaintextParameters', function () { describe('run', function () { - it('should FAIL if Stack parameters contain one of secret words ["password" , "privatekey", "secret"]', function (done) { + it('should WARN if template contains one of secret words ["password" , "privatekey", "secret"]', function (done) { const cache = createCache([describeStacks[0]]); - plainTextParameters.run(cache, settings, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(1); done(); }); }); - it('should PASS if Stack parameters does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { + it('should PASS if template does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { const cache = createCache([describeStacks[1]]); - plainTextParameters.run(cache, settings, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -124,7 +118,7 @@ describe('plainTextParameters', function () { it('should PASS if unable to describe stacks', function (done) { const cache = createCache([]); - plainTextParameters.run(cache, settings, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -133,7 +127,7 @@ describe('plainTextParameters', function () { it('should PASS if there is no parameter in the stack', function (done) { const cache = createCache([describeStacks[2]]); - plainTextParameters.run(cache, settings, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -142,7 +136,7 @@ describe('plainTextParameters', function () { it('should not return any results if unable to fetch any stack description', function (done) { const cache = createNullCache(); - plainTextParameters.run(cache, settings, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(0); done(); }); @@ -150,7 +144,7 @@ describe('plainTextParameters', function () { it('should UNKNOWN if error occurs while fetching stack description', function (done) { const cache = createErrorCache(); - plainTextParameters.run(cache, settings, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); done(); From ce6532523dca0f672a0824cfd3cc1e8161d9984c Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 14 Aug 2020 18:09:45 +0500 Subject: [PATCH 06/76] SPLOIT-113: Updated custom settings --- plugins/aws/cloudformation/plainTextParameters.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 2ed03af7f0..0a53028425 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -10,10 +10,11 @@ module.exports = { recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], settings: { - plainTextParameters: { - secretWords: [ - 'secret', 'password', 'privatekey' - ] + plain_text_parameters: { + name: "CloudFormation Plaintext Parameters", + description: "A comma-delimited list of parameter strings that indicate a sensitive value", + regex: "[a-zA-Z0-9,]", + default: "secret,password,privatekey" } }, @@ -21,8 +22,7 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); - secretWords = this.settings.plainTextParameters.secretWords; - + secretWords = this.settings.plain_text_parameters.default; async.each(regions.cloudformation, function(region, rcb){ var describeStacks = helpers.addSource(cache, source, From e70b96aac28a75ed99c4f51b9d89e0003d0e5b0b Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 21:24:30 +0500 Subject: [PATCH 07/76] Made PR requested changes --- plugins/aws/cloudformation/plainTextParameters.js | 8 ++++---- plugins/aws/ec2/launchWizardSecurityGroups.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 0a53028425..30da85236a 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -22,7 +22,7 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); - secretWords = this.settings.plain_text_parameters.default; + var secretWords = this.settings.plain_text_parameters.default; async.each(regions.cloudformation, function(region, rcb){ var describeStacks = helpers.addSource(cache, source, @@ -48,14 +48,14 @@ module.exports = { var resource = stack.StackId; parameterFound = false; - if(!stack.Parameters.length) { + if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, - 'The template does not contain any potentially-sensitive parameters', region, resource); + 'Template does not contain any potentially-sensitive parameters', region, resource); return rcb(); } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && secretWords.includes(parameter.ParameterKey.toLowerCase())) { + if((!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()))) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); diff --git a/plugins/aws/ec2/launchWizardSecurityGroups.js b/plugins/aws/ec2/launchWizardSecurityGroups.js index 252cabd11c..0e028778a7 100644 --- a/plugins/aws/ec2/launchWizardSecurityGroups.js +++ b/plugins/aws/ec2/launchWizardSecurityGroups.js @@ -36,7 +36,7 @@ module.exports = { var sg = describeSecurityGroups.data[s]; var resource = sg.GroupId; - if (sg.GroupName.toLowerCase().startsWith('launch-wizard')) { + if (sg.GroupName && sg.GroupName.toLowerCase().startsWith('launch-wizard')) { helpers.addResult(results, 2, 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', region, resource); From f62a1d5037ebd20dda78959f5d2b0a073bb4abee Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sat, 15 Aug 2020 01:07:50 +0500 Subject: [PATCH 08/76] SPLOIT-113: Added regex to check if NoEcho is enabled --- plugins/aws/cloudformation/plainTextParameters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 30da85236a..f6a5ce193a 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -55,7 +55,7 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if((!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()))) { + if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match("^[\*]+$")) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); From 1b80ac47565110c4ba276805f233d1aa11620a40 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 04:13:40 +0500 Subject: [PATCH 09/76] Accommodated PR changes --- exports.js | 2 +- plugins/aws/cloudformation/plainTextParameters.js | 6 +++--- .../aws/cloudformation/plainTextParameters.spec.js | 2 +- plugins/aws/ec2/launchWizardSecurityGroups.js | 11 +++++++++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/exports.js b/exports.js index ee2b81f9ee..a61fddd2cc 100644 --- a/exports.js +++ b/exports.js @@ -14,7 +14,7 @@ module.exports = { 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - 'plaintextParameters' : require(__dirname + '/plugins/aws/cloudformation/plaintextParameters.js'), + 'plaintextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index f6a5ce193a..5e5f227feb 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -46,12 +46,12 @@ module.exports = { // arn:aws:cloudformation:region:account-id:stack/stack-name/stack-id var stack = describeStacks.data[s]; var resource = stack.StackId; - parameterFound = false; + let parameterFound = false; if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, - 'Template does not contain any potentially-sensitive parameters', region, resource); - return rcb(); + 'Template does not contain any parameters', region, resource); + continue; } stack.Parameters.forEach(function(parameter){ diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index 490d978002..cdad731db6 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -const plaintextParameters = require('./plaintextParameters'); +const plaintextParameters = require('./plainTextParameters'); const describeStacks = [ { diff --git a/plugins/aws/ec2/launchWizardSecurityGroups.js b/plugins/aws/ec2/launchWizardSecurityGroups.js index 0e028778a7..48f040b7ed 100644 --- a/plugins/aws/ec2/launchWizardSecurityGroups.js +++ b/plugins/aws/ec2/launchWizardSecurityGroups.js @@ -28,7 +28,7 @@ module.exports = { } if (!describeSecurityGroups.data.length) { - helpers.addResult(results, 0, 'No security groups present', region); + helpers.addResult(results, 0, 'No security groups found', region); return rcb(); } @@ -36,7 +36,14 @@ module.exports = { var sg = describeSecurityGroups.data[s]; var resource = sg.GroupId; - if (sg.GroupName && sg.GroupName.toLowerCase().startsWith('launch-wizard')) { + if(!sg.GroupName) { + helpers.addResult(results, 2, + 'Unable to get group name of security group', + region, resource); + continue; + } + + if (sg.GroupName.toLowerCase().startsWith('launch-wizard')) { helpers.addResult(results, 2, 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', region, resource); From c0dc834c5739260ca9acfc7f11ef78bf73987535 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 06:09:46 +0500 Subject: [PATCH 10/76] Fixed eslint issues --- plugins/aws/cloudformation/plainTextParameters.js | 15 +++++++-------- plugins/aws/ec2/launchWizardSecurityGroups.js | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 5e5f227feb..5f9906591c 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -11,10 +11,10 @@ module.exports = { apis: ['CloudFormation:describeStacks'], settings: { plain_text_parameters: { - name: "CloudFormation Plaintext Parameters", - description: "A comma-delimited list of parameter strings that indicate a sensitive value", - regex: "[a-zA-Z0-9,]", - default: "secret,password,privatekey" + name: 'CloudFormation Plaintext Parameters', + description: 'A comma-delimited list of parameter strings that indicate a sensitive value', + regex: '[a-zA-Z0-9,]', + default: 'secret,password,privatekey' } }, @@ -33,7 +33,7 @@ module.exports = { if (describeStacks.err || !describeStacks.data) { helpers.addResult(results, 3, 'Unable to describe stacks: ' + helpers.addError(describeStacks), region); - return rcb(); + return rcb(); } if (!describeStacks.data.length) { @@ -41,7 +41,6 @@ module.exports = { return rcb(); } - var parameterFound; for (var s in describeStacks.data){ // arn:aws:cloudformation:region:account-id:stack/stack-name/stack-id var stack = describeStacks.data[s]; @@ -55,7 +54,7 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match("^[\*]+$")) { + if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); @@ -64,7 +63,7 @@ module.exports = { if(!parameterFound) { helpers.addResult(results, 0, - 'Template does not contain any potentially-sensitive parameters', region, resource); + 'Template does not contain any potentially-sensitive parameters', region, resource); } } diff --git a/plugins/aws/ec2/launchWizardSecurityGroups.js b/plugins/aws/ec2/launchWizardSecurityGroups.js index 48f040b7ed..caa173be82 100644 --- a/plugins/aws/ec2/launchWizardSecurityGroups.js +++ b/plugins/aws/ec2/launchWizardSecurityGroups.js @@ -45,8 +45,8 @@ module.exports = { if (sg.GroupName.toLowerCase().startsWith('launch-wizard')) { helpers.addResult(results, 2, - 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', - region, resource); + 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', + region, resource); } else { helpers.addResult(results, 0, 'Security Group ' + sg.GroupName + ' was not launched using EC2 launch wizard', From 7d457bd2c6def38589b805cb7de4d2cb8340b95d Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:38:01 +0500 Subject: [PATCH 11/76] Update exports.js --- exports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exports.js b/exports.js index a61fddd2cc..5a338cfa5e 100644 --- a/exports.js +++ b/exports.js @@ -14,7 +14,7 @@ module.exports = { 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - 'plaintextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), + 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), From 8c2466c91d58ce0de34eb75c62bcb02e844efd32 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:41:20 +0500 Subject: [PATCH 12/76] Fixed eslint issues --- index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 3b97033a22..262b4c8c73 100644 --- a/index.js +++ b/index.js @@ -10,12 +10,12 @@ var GoogleConfig; // OPTION 1: Configure service provider credentials through hard-coded config objects -// AWSConfig = { -// accessKeyId: '', -// secretAccessKey: '', -// sessionToken: '', -// region: 'us-east-1' -// }; +AWSConfig = { + accessKeyId: 'AKIAYE32SRU5XWXGIMV3', + secretAccessKey: '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', + sessionToken: '', + region: 'us-east-1' +}; // AzureConfig = { // ApplicationID: '', // A.K.A ClientID From ccb92eef611140d3c36698417db0755e6483ea74 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:42:00 +0500 Subject: [PATCH 13/76] Update index.js --- index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 262b4c8c73..019fc78f81 100644 --- a/index.js +++ b/index.js @@ -10,12 +10,12 @@ var GoogleConfig; // OPTION 1: Configure service provider credentials through hard-coded config objects -AWSConfig = { - accessKeyId: 'AKIAYE32SRU5XWXGIMV3', - secretAccessKey: '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', - sessionToken: '', - region: 'us-east-1' -}; +// AWSConfig = { +// accessKeyId: '', +// secretAccessKey: '', +// sessionToken: '', +// region: '' +// }; // AzureConfig = { // ApplicationID: '', // A.K.A ClientID From 93c553d4c7be0b44e7553149f7a2f3f461103008 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:48:02 +0500 Subject: [PATCH 14/76] Update index.js --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 019fc78f81..6f61d149a8 100644 --- a/index.js +++ b/index.js @@ -14,7 +14,7 @@ var GoogleConfig; // accessKeyId: '', // secretAccessKey: '', // sessionToken: '', -// region: '' +// region: 'us-east-1' // }; // AzureConfig = { From cf21d1d1513bef533823eb547389a0d3ede895cf Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 15:59:26 +0500 Subject: [PATCH 15/76] Added cloudformation in china and gov regions --- helpers/aws/regions_china.js | 1 + helpers/aws/regions_gov.js | 1 + 2 files changed, 2 insertions(+) diff --git a/helpers/aws/regions_china.js b/helpers/aws/regions_china.js index 18c482aca6..3d82dca40c 100644 --- a/helpers/aws/regions_china.js +++ b/helpers/aws/regions_china.js @@ -18,6 +18,7 @@ module.exports = { s3: regions, cloudtrail: regions, cloudwatchlogs: regions, + cloudformation: regions, configservice: regions, dms: regions, dynamodb: regions, diff --git a/helpers/aws/regions_gov.js b/helpers/aws/regions_gov.js index f84f8f923d..c55424fce6 100644 --- a/helpers/aws/regions_gov.js +++ b/helpers/aws/regions_gov.js @@ -18,6 +18,7 @@ module.exports = { s3: regions, cloudtrail: regions, cloudwatchlogs: regions, + cloudformation: regions, configservice: regions, dms: regions, dynamodb: regions, From aac8ece7116bcc8bf98a826339f543ecb69a5e10 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 20:15:26 +0500 Subject: [PATCH 16/76] Accomodated PR changes --- .../aws/cloudformation/plainTextParameters.js | 18 +-- .../plainTextParameters.spec.js | 144 +++++++++++------- 2 files changed, 95 insertions(+), 67 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 5f9906591c..e6e899268f 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -27,7 +27,6 @@ module.exports = { var describeStacks = helpers.addSource(cache, source, ['cloudformation', 'describeStacks', region]); - if (!describeStacks) return rcb(); if (describeStacks.err || !describeStacks.data) { @@ -45,7 +44,7 @@ module.exports = { // arn:aws:cloudformation:region:account-id:stack/stack-name/stack-id var stack = describeStacks.data[s]; var resource = stack.StackId; - let parameterFound = false; + let foundStrings = []; if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, @@ -54,18 +53,19 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { - parameterFound = true; - helpers.addResult(results, 1, - 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); + if(parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { + foundStrings.push(parameter.ParameterKey); } }); - - if(!parameterFound) { + + if(foundStrings && foundStrings.length) { + helpers.addResult(results, 1, + 'Template contains the following potentially-sensitive parameters: ' + foundStrings, region, resource); + } + else { helpers.addResult(results, 0, 'Template does not contain any potentially-sensitive parameters', region, resource); } - } rcb(); diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index cdad731db6..d471a555f3 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -2,62 +2,81 @@ var expect = require('chai').expect; const plaintextParameters = require('./plainTextParameters'); const describeStacks = [ - { - StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', - StackName: 'TestStack', - Parameters: [ - { - ParameterKey: 'Secret', - ParameterValue: 'bucketwithsecretparameter1' - }, - { - ParameterKey: 'Password', - ParameterValue: 'bucketwithsecretparameter1' - } - ], - CreationTime: '2020-08-13T13:34:52.435Z', - RollbackConfiguration: { RollbackTriggers: [] }, - StackStatus: 'CREATE_COMPLETE', - DisableRollback: false, - NotificationARNs: [], - Capabilities: [], - Outputs: [], - Tags: [], - DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } - }, - { - StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', - StackName: 'TestStack', - Parameters: [ - { - ParameterKey: 'S3BucketName', - ParameterValue: 'testbucketplaintext1' - } - ], - CreationTime: '2020-08-12T09:42:04.803Z', - RollbackConfiguration: { RollbackTriggers: [] }, - StackStatus: 'CREATE_COMPLETE', - DisableRollback: false, - NotificationARNs: [], - Capabilities: [], - Outputs: [], - Tags: [], - DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } - }, - { - StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', - StackName: 'TestStack', - Parameters: [], - CreationTime: '2020-08-12T09:42:04.803Z', - RollbackConfiguration: { RollbackTriggers: [] }, - StackStatus: 'CREATE_COMPLETE', - DisableRollback: false, - NotificationARNs: [], - Capabilities: [], - Outputs: [], - Tags: [], - DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } - } + { + StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', + StackName: 'TestStack', + Parameters: [ + { + ParameterKey: 'Secret', + ParameterValue: 'bucketwithsecretparameter1' + }, + { + ParameterKey: 'Password', + ParameterValue: 'bucketwithsecretparameter1' + } + ], + CreationTime: '2020-08-13T13:34:52.435Z', + RollbackConfiguration: { RollbackTriggers: [] }, + StackStatus: 'CREATE_COMPLETE', + DisableRollback: false, + NotificationARNs: [], + Capabilities: [], + Outputs: [], + Tags: [], + DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } + }, + { + StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', + StackName: 'TestStack', + Parameters: [ + { + ParameterKey: 'S3BucketName', + ParameterValue: 'testbucketplaintext1' + } + ], + CreationTime: '2020-08-12T09:42:04.803Z', + RollbackConfiguration: { RollbackTriggers: [] }, + StackStatus: 'CREATE_COMPLETE', + DisableRollback: false, + NotificationARNs: [], + Capabilities: [], + Outputs: [], + Tags: [], + DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } + }, + { + StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', + StackName: 'TestStack', + Parameters: [ + { + ParameterKey: 'Secret', + ParameterValue: '****' + } + ], + CreationTime: '2020-08-13T13:34:52.435Z', + RollbackConfiguration: { RollbackTriggers: [] }, + StackStatus: 'CREATE_COMPLETE', + DisableRollback: false, + NotificationARNs: [], + Capabilities: [], + Outputs: [], + Tags: [], + DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } + }, + { + StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', + StackName: 'TestStack', + Parameters: [], + CreationTime: '2020-08-12T09:42:04.803Z', + RollbackConfiguration: { RollbackTriggers: [] }, + StackStatus: 'CREATE_COMPLETE', + DisableRollback: false, + NotificationARNs: [], + Capabilities: [], + Outputs: [], + Tags: [], + DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } + } ] const createCache = (stacks) => { @@ -98,7 +117,7 @@ const createNullCache = () => { describe('plaintextParameters', function () { describe('run', function () { - it('should WARN if template contains one of secret words ["password" , "privatekey", "secret"]', function (done) { + it('should WARN if template contains one of secret words', function (done) { const cache = createCache([describeStacks[0]]); plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); @@ -107,7 +126,7 @@ describe('plaintextParameters', function () { }); }); - it('should PASS if template does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { + it('should PASS if template does not contain any of secret words', function (done) { const cache = createCache([describeStacks[1]]); plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); @@ -116,6 +135,15 @@ describe('plaintextParameters', function () { }); }); + it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { + const cache = createCache([describeStacks[2]]); + plaintextParameters.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + it('should PASS if unable to describe stacks', function (done) { const cache = createCache([]); plaintextParameters.run(cache, {}, (err, results) => { From 7707dbd49add468d82ae24466b8bda804e9c2f4b Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 21:12:35 +0500 Subject: [PATCH 17/76] Updated status in result of failure --- plugins/aws/cloudformation/plainTextParameters.js | 2 +- plugins/aws/cloudformation/plainTextParameters.spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index e6e899268f..6803911fef 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -59,7 +59,7 @@ module.exports = { }); if(foundStrings && foundStrings.length) { - helpers.addResult(results, 1, + helpers.addResult(results, 2, 'Template contains the following potentially-sensitive parameters: ' + foundStrings, region, resource); } else { diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index d471a555f3..03e8abf7e9 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -117,11 +117,11 @@ const createNullCache = () => { describe('plaintextParameters', function () { describe('run', function () { - it('should WARN if template contains one of secret words', function (done) { + it('should FAIL if template contains one of secret words', function (done) { const cache = createCache([describeStacks[0]]); plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(1); + expect(results[0].status).to.equal(2); done(); }); }); From 45b797359ad6f964030efb85c9d79dc5c6fcbbeb Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 17 Aug 2020 01:00:39 +0500 Subject: [PATCH 18/76] SPLOIT-947: Added 'Custom Open Ports' plugin --- exports.js | 1 + plugins/aws/ec2/openCustomPorts.js | 95 +++++++++++++ plugins/aws/ec2/openCustomPorts.spec.js | 169 ++++++++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 plugins/aws/ec2/openCustomPorts.js create mode 100644 plugins/aws/ec2/openCustomPorts.spec.js diff --git a/exports.js b/exports.js index 5a338cfa5e..e0d0841b15 100644 --- a/exports.js +++ b/exports.js @@ -79,6 +79,7 @@ module.exports = { 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), + 'openCustomPorts' : require(__dirname + '/plugins/aws/ec2/openCustomPorts.js'), 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js new file mode 100644 index 0000000000..9063f6453f --- /dev/null +++ b/plugins/aws/ec2/openCustomPorts.js @@ -0,0 +1,95 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Open Custom Ports', + category: 'EC2', + description: 'Ensures that the defined ports are not exposed publicly.', + more_info: 'Security groups should be used to restrict access to ports from known networks.', + link: 'https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html', + recommended_action: 'Modify the security group to ensure the ports are not exposed publicly.', + apis: ['EC2:describeSecurityGroups'], + settings: { + open_port_allowed_list: { + name: 'EC2 Allowed Open Ports', + description: 'A comma-delimited list of ports that indicates open ports allowed for any connection', + regex: '[a-zA-Z0-9,]', + default: [22, 443] + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + var allowed_open_ports = this.settings.open_port_allowed_list.default; + + async.each(regions.ec2, function(region, rcb){ + var describeSecurityGroups = helpers.addSource(cache, source, + ['ec2', 'describeSecurityGroups', region]); + + if (!describeSecurityGroups) return rcb(); + + if (describeSecurityGroups.err || !describeSecurityGroups.data) { + helpers.addResult(results, 3, + 'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region); + return rcb(); + } + + if (!describeSecurityGroups.data.length) { + helpers.addResult(results, 0, 'No security groups present', region); + return rcb(); + } + + var found = false; + var groups = describeSecurityGroups.data; + + for (var g in groups) { + var strings = []; + var resource = 'arn:aws:ec2:' + region + ':' + + groups[g].OwnerId + ':security-group/' + + groups[g].GroupId; + + for (var p in groups[g].IpPermissions) { + var permission = groups[g].IpPermissions[p]; + + for (var k in permission.IpRanges) { + var range = permission.IpRanges[k]; + + if (range.CidrIp === '0.0.0.0/0') { + var portRange = permission.ToPort - permission.FromPort; + + for (let p=0; p <= portRange; p++) { + var port = permission.FromPort + p; + + if (!allowed_open_ports.includes(port)) { + var string = permission.IpProtocol.toUpperCase() + + ' port ' + port + ' open to 0.0.0.0/0'; + if (strings.indexOf(string) === -1) strings.push(string); + found = true; + } + } + } + } + } + + if (strings.length) { + helpers.addResult(results, 2, + 'Security group: ' + groups[g].GroupId + + ' (' + groups[g].GroupName + + ') has ' + ': ' + strings.join(' and '), region, + resource); + } + } + + if (!found) { + helpers.addResult(results, 0, 'No public open ports found', region); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/ec2/openCustomPorts.spec.js b/plugins/aws/ec2/openCustomPorts.spec.js new file mode 100644 index 0000000000..83b682bb0c --- /dev/null +++ b/plugins/aws/ec2/openCustomPorts.spec.js @@ -0,0 +1,169 @@ +var expect = require('chai').expect; +const openCustomPorts = require('./openCustomPorts'); + +const securityGroups = [ + { + "Description": "Allows SSh access to developer", + "GroupName": "spec-test-sg", + "IpPermissions": [{ + "FromPort": 25, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [ + { + "CidrIpv6": "::/0" + } + ], + "PrefixListIds": [], + "ToPort": 25, + "UserIdGroupPairs": [] + }], + "OwnerId": "560213429563", + "GroupId": "sg-0b5f2771716acfee4", + "IpPermissionsEgress": [ + { + "FromPort": 25, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [ + { + "CidrIpv6": "::/0" + } + ], + "PrefixListIds": [], + "ToPort": 25, + "UserIdGroupPairs": [] + } + ], + "VpcId": "vpc-99de2fe4" + }, + { + "Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00", + "GroupName": "launch-wizard-1", + "IpPermissions": [ + { + "FromPort": 22, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "ToPort": 22, + "UserIdGroupPairs": [] + } + ], + "OwnerId": "560213429563", + "GroupId": "sg-0ff1642cae23c309a", + "IpPermissionsEgress": [ + { + "IpProtocol": "-1", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "UserIdGroupPairs": [] + } + ], + "VpcId": "vpc-99de2fe4" + } +] + +const createCache = (groups) => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': { + data: groups + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': { + err: { + message: 'error describing cloudformation stacks' + }, + }, + }, + }, + }; +}; + +const createNullCache = () => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': null, + }, + }, + }; +}; + +describe('openCustomPorts', function () { + describe('run', function () { + + it('should not return any results if unable to fetch any security groups description', function (done) { + const cache = createNullCache(); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + + it('should UNKNOWN if error occurs while fetching any security groups description', function (done) { + const cache = createErrorCache(); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should PASS if no security groups are present', function (done) { + const cache = createCache([]); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should FAIL if any public open port is found', function (done) { + const cache = createCache([securityGroups[0]]); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should PASS if no public open port is found', function (done) { + const cache = createCache([securityGroups[1]]); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + }); +}); \ No newline at end of file From fb12862c8a2d0c815853a49c6aa47f27a6c16e7a Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 20 Aug 2020 16:23:49 +0500 Subject: [PATCH 19/76] Refactor plugin file --- plugins/aws/ec2/openCustomPorts.js | 56 +++++++++----------- plugins/aws/ec2/openCustomPorts.spec.js | 70 ++++++++++++------------- 2 files changed, 61 insertions(+), 65 deletions(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index 9063f6453f..c0c99d02ee 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/aws'); module.exports = { title: 'Open Custom Ports', category: 'EC2', - description: 'Ensures that the defined ports are not exposed publicly.', + description: 'Ensures that the defined ports are not exposed publicly', more_info: 'Security groups should be used to restrict access to ports from known networks.', link: 'https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html', recommended_action: 'Modify the security group to ensure the ports are not exposed publicly.', @@ -14,7 +14,7 @@ module.exports = { name: 'EC2 Allowed Open Ports', description: 'A comma-delimited list of ports that indicates open ports allowed for any connection', regex: '[a-zA-Z0-9,]', - default: [22, 443] + default: [80, 443] } }, @@ -28,9 +28,7 @@ module.exports = { async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, ['ec2', 'describeSecurityGroups', region]); - if (!describeSecurityGroups) return rcb(); - if (describeSecurityGroups.err || !describeSecurityGroups.data) { helpers.addResult(results, 3, 'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region); @@ -38,55 +36,53 @@ module.exports = { } if (!describeSecurityGroups.data.length) { - helpers.addResult(results, 0, 'No security groups present', region); + helpers.addResult(results, 0, 'No security groups found', region); return rcb(); } - var found = false; - var groups = describeSecurityGroups.data; + // Loop through each security group + for (var g in describeSecurityGroups.data) { + var group = describeSecurityGroups.data[g]; + var resource = group.GroupId; + var openPorts = []; - for (var g in groups) { - var strings = []; - var resource = 'arn:aws:ec2:' + region + ':' + - groups[g].OwnerId + ':security-group/' + - groups[g].GroupId; + if (!group.IpPermissions) continue; - for (var p in groups[g].IpPermissions) { - var permission = groups[g].IpPermissions[p]; + // Loop through each ip permissions in a security group + for (var p in group.IpPermissions) { + var permission = group.IpPermissions[p]; - for (var k in permission.IpRanges) { - var range = permission.IpRanges[k]; + // Loop through each ip range for an ip permissions list + for (var r in permission.IpRanges) { + var range = permission.IpRanges[r]; - if (range.CidrIp === '0.0.0.0/0') { + if (range.CidrIp && range.CidrIp === '0.0.0.0/0') { var portRange = permission.ToPort - permission.FromPort; + // Check for all the ports in port range for (let p=0; p <= portRange; p++) { var port = permission.FromPort + p; if (!allowed_open_ports.includes(port)) { - var string = permission.IpProtocol.toUpperCase() + - ' port ' + port + ' open to 0.0.0.0/0'; - if (strings.indexOf(string) === -1) strings.push(string); - found = true; + var openPort = permission.IpProtocol.toUpperCase() + ' port ' + port; + if (openPorts.indexOf(openPort) === -1) openPorts.push(openPort); } } } } } - if (strings.length) { + if (openPorts.length) { helpers.addResult(results, 2, - 'Security group: ' + groups[g].GroupId + - ' (' + groups[g].GroupName + - ') has ' + ': ' + strings.join(' and '), region, - resource); + 'Security group ' + group.GroupName + ' has: ' + openPorts.join(' , ') + ' open to 0.0.0.0/0', + region, resource); + } else { + helpers.addResult(results, 0, + 'Security group: ' + group.GroupName + ' has no open ports', + region, resource); } } - if (!found) { - helpers.addResult(results, 0, 'No public open ports found', region); - } - rcb(); }, function(){ callback(null, results, source); diff --git a/plugins/aws/ec2/openCustomPorts.spec.js b/plugins/aws/ec2/openCustomPorts.spec.js index 83b682bb0c..57f63f2c46 100644 --- a/plugins/aws/ec2/openCustomPorts.spec.js +++ b/plugins/aws/ec2/openCustomPorts.spec.js @@ -19,7 +19,7 @@ const securityGroups = [ } ], "PrefixListIds": [], - "ToPort": 25, + "ToPort": 30, "UserIdGroupPairs": [] }], "OwnerId": "560213429563", @@ -45,40 +45,40 @@ const securityGroups = [ ], "VpcId": "vpc-99de2fe4" }, - { - "Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00", - "GroupName": "launch-wizard-1", - "IpPermissions": [ - { - "FromPort": 22, - "IpProtocol": "tcp", - "IpRanges": [ - { - "CidrIp": "0.0.0.0/0" - } - ], - "Ipv6Ranges": [], - "PrefixListIds": [], - "ToPort": 22, - "UserIdGroupPairs": [] - } - ], - "OwnerId": "560213429563", - "GroupId": "sg-0ff1642cae23c309a", - "IpPermissionsEgress": [ - { - "IpProtocol": "-1", - "IpRanges": [ - { - "CidrIp": "0.0.0.0/0" - } - ], - "Ipv6Ranges": [], - "PrefixListIds": [], - "UserIdGroupPairs": [] - } - ], - "VpcId": "vpc-99de2fe4" + { + "Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00", + "GroupName": "launch-wizard-1", + "IpPermissions": [ + { + "FromPort": 80, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "ToPort": 80, + "UserIdGroupPairs": [] + } + ], + "OwnerId": "560213429563", + "GroupId": "sg-0ff1642cae23c309a", + "IpPermissionsEgress": [ + { + "IpProtocol": "-1", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "UserIdGroupPairs": [] + } + ], + "VpcId": "vpc-99de2fe4" } ] From a4ea92f1b8c5baa7867659a7315805b15b2bf203 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 14 Aug 2020 05:55:55 +0500 Subject: [PATCH 20/76] SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation --- exports.js | 7 ++++ index.js | 8 ++++- .../plainTextParameters.spec.js | 32 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/exports.js b/exports.js index 5a338cfa5e..b3eca51f7d 100644 --- a/exports.js +++ b/exports.js @@ -13,9 +13,13 @@ module.exports = { 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), +<<<<<<< HEAD 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), +======= + 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), @@ -31,7 +35,10 @@ module.exports = { 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), +<<<<<<< HEAD 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), +======= +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), diff --git a/index.js b/index.js index 6f61d149a8..2f90a29fa4 100644 --- a/index.js +++ b/index.js @@ -113,7 +113,13 @@ if(process.env.GOOGLE_APPLICATION_CREDENTIALS){ } // Custom settings - place plugin-specific settings here -var settings = {}; +var settings = { + plainTextParameters: { + secretWords: [ + 'secret', 'password', 'privatekey' + ] + } +}; // If running in GovCloud, uncomment the following // settings.govcloud = true; diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index 03e8abf7e9..cdf14fb564 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -115,6 +115,7 @@ const createNullCache = () => { }; }; +<<<<<<< HEAD describe('plaintextParameters', function () { describe('run', function () { it('should FAIL if template contains one of secret words', function (done) { @@ -122,10 +123,20 @@ describe('plaintextParameters', function () { plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); +======= +describe('plainTextParameters', function () { + describe('run', function () { + it('should FAIL if Stack parameters contain one of secret words ["password" , "privatekey", "secret"]', function (done) { + const cache = createCache([describeStacks[0]]); + plainTextParameters.run(cache, settings, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation done(); }); }); +<<<<<<< HEAD it('should PASS if template does not contain any of secret words', function (done) { const cache = createCache([describeStacks[1]]); plaintextParameters.run(cache, {}, (err, results) => { @@ -138,6 +149,11 @@ describe('plaintextParameters', function () { it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { const cache = createCache([describeStacks[2]]); plaintextParameters.run(cache, {}, (err, results) => { +======= + it('should PASS if Stack parameters does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { + const cache = createCache([describeStacks[1]]); + plainTextParameters.run(cache, settings, (err, results) => { +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -146,7 +162,11 @@ describe('plaintextParameters', function () { it('should PASS if unable to describe stacks', function (done) { const cache = createCache([]); +<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { +======= + plainTextParameters.run(cache, settings, (err, results) => { +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -155,7 +175,11 @@ describe('plaintextParameters', function () { it('should PASS if there is no parameter in the stack', function (done) { const cache = createCache([describeStacks[2]]); +<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { +======= + plainTextParameters.run(cache, settings, (err, results) => { +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -164,7 +188,11 @@ describe('plaintextParameters', function () { it('should not return any results if unable to fetch any stack description', function (done) { const cache = createNullCache(); +<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { +======= + plainTextParameters.run(cache, settings, (err, results) => { +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(0); done(); }); @@ -172,7 +200,11 @@ describe('plaintextParameters', function () { it('should UNKNOWN if error occurs while fetching stack description', function (done) { const cache = createErrorCache(); +<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { +======= + plainTextParameters.run(cache, settings, (err, results) => { +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); done(); From 8e5b6be04baa584ba2e3aafc64076ad49175f6ef Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 15:30:57 +0500 Subject: [PATCH 21/76] Added plugin and spec file for launch wizard security groups --- exports.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/exports.js b/exports.js index b3eca51f7d..5a338cfa5e 100644 --- a/exports.js +++ b/exports.js @@ -13,13 +13,9 @@ module.exports = { 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), -<<<<<<< HEAD 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), -======= - 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), @@ -35,10 +31,7 @@ module.exports = { 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), -<<<<<<< HEAD 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), -======= ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), From a9afe440de80c185bdd8df63bad1c28c990daa99 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 13 Aug 2020 19:59:59 +0500 Subject: [PATCH 22/76] Added vpcEndpointAcceptance plugin and spec file --- plugins/aws/ec2/vpcEndpointAcceptance.spec.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js index 62053b7238..0946f5a682 100644 --- a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js +++ b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js @@ -112,6 +112,15 @@ describe('vpcEndpointAcceptance', function () { }); }); + it('should PASS if no VPC endpoint services are detected', function (done) { + const cache = createCache([]); + vpcEndpointAcceptance.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + it('should UNKNOWN if there was an error querying for VPC endpoint services', function (done) { const cache = createErrorCache(); vpcEndpointAcceptance.run(cache, {}, (err, results) => { From 0323a988487eb779a7897c75f464d38217877c19 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 16:50:46 +0500 Subject: [PATCH 23/76] Refactored code in plaintextParameters plugin and spec file --- index.js | 8 +--- .../aws/cloudformation/plainTextParameters.js | 22 +++++++++-- .../plainTextParameters.spec.js | 38 ++++++------------- 3 files changed, 31 insertions(+), 37 deletions(-) diff --git a/index.js b/index.js index 2f90a29fa4..6f61d149a8 100644 --- a/index.js +++ b/index.js @@ -113,13 +113,7 @@ if(process.env.GOOGLE_APPLICATION_CREDENTIALS){ } // Custom settings - place plugin-specific settings here -var settings = { - plainTextParameters: { - secretWords: [ - 'secret', 'password', 'privatekey' - ] - } -}; +var settings = {}; // If running in GovCloud, uncomment the following // settings.govcloud = true; diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 6803911fef..912e7f4eda 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -10,11 +10,18 @@ module.exports = { recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], settings: { +<<<<<<< HEAD plain_text_parameters: { name: 'CloudFormation Plaintext Parameters', description: 'A comma-delimited list of parameter strings that indicate a sensitive value', regex: '[a-zA-Z0-9,]', default: 'secret,password,privatekey' +======= + plainTextParameters: { + secretWords: [ + 'secret', 'password', 'privatekey' + ] +>>>>>>> 3da6672... Refactored code in plaintextParameters plugin and spec file } }, @@ -22,7 +29,12 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); +<<<<<<< HEAD var secretWords = this.settings.plain_text_parameters.default; +======= + secretWords = this.settings.plainTextParameters.secretWords; + +>>>>>>> 3da6672... Refactored code in plaintextParameters plugin and spec file async.each(regions.cloudformation, function(region, rcb){ var describeStacks = helpers.addSource(cache, source, @@ -48,13 +60,15 @@ module.exports = { if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, - 'Template does not contain any parameters', region, resource); - continue; + 'The template does not contain any potentially-sensitive parameters', region, resource); + return rcb(); } stack.Parameters.forEach(function(parameter){ - if(parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { - foundStrings.push(parameter.ParameterKey); + if(!parameterFound && secretWords.includes(parameter.ParameterKey.toLowerCase())) { + parameterFound = true; + helpers.addResult(results, 1, + 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); } }); diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index cdf14fb564..d7ac6fed08 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -115,7 +115,7 @@ const createNullCache = () => { }; }; -<<<<<<< HEAD + describe('plaintextParameters', function () { describe('run', function () { it('should FAIL if template contains one of secret words', function (done) { @@ -123,20 +123,18 @@ describe('plaintextParameters', function () { plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); -======= -describe('plainTextParameters', function () { - describe('run', function () { - it('should FAIL if Stack parameters contain one of secret words ["password" , "privatekey", "secret"]', function (done) { + }); + }); + + it('should WARN if template contains one of secret words ["password" , "privatekey", "secret"]', function (done) { const cache = createCache([describeStacks[0]]); - plainTextParameters.run(cache, settings, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(1); ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation done(); }); }); -<<<<<<< HEAD it('should PASS if template does not contain any of secret words', function (done) { const cache = createCache([describeStacks[1]]); plaintextParameters.run(cache, {}, (err, results) => { @@ -149,11 +147,12 @@ describe('plainTextParameters', function () { it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { const cache = createCache([describeStacks[2]]); plaintextParameters.run(cache, {}, (err, results) => { -======= it('should PASS if Stack parameters does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { const cache = createCache([describeStacks[1]]); plainTextParameters.run(cache, settings, (err, results) => { ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation + it('should PASS if template does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { + const cache = createCache([describeStacks[1]]); + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -162,11 +161,8 @@ describe('plainTextParameters', function () { it('should PASS if unable to describe stacks', function (done) { const cache = createCache([]); -<<<<<<< HEAD + plaintextParameters.run(cache, {}, (err, results) => { -======= - plainTextParameters.run(cache, settings, (err, results) => { ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -175,11 +171,8 @@ describe('plainTextParameters', function () { it('should PASS if there is no parameter in the stack', function (done) { const cache = createCache([describeStacks[2]]); -<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { -======= - plainTextParameters.run(cache, settings, (err, results) => { ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -188,11 +181,8 @@ describe('plainTextParameters', function () { it('should not return any results if unable to fetch any stack description', function (done) { const cache = createNullCache(); -<<<<<<< HEAD + plaintextParameters.run(cache, {}, (err, results) => { -======= - plainTextParameters.run(cache, settings, (err, results) => { ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(0); done(); }); @@ -200,11 +190,7 @@ describe('plainTextParameters', function () { it('should UNKNOWN if error occurs while fetching stack description', function (done) { const cache = createErrorCache(); -<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { -======= - plainTextParameters.run(cache, settings, (err, results) => { ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); done(); From aab9f79d36b4ead3765e8f14871f9e7b54959990 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 14 Aug 2020 18:09:45 +0500 Subject: [PATCH 24/76] SPLOIT-113: Updated custom settings --- plugins/aws/cloudformation/plainTextParameters.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 912e7f4eda..487cac1ccc 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -10,18 +10,12 @@ module.exports = { recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], settings: { -<<<<<<< HEAD + plain_text_parameters: { name: 'CloudFormation Plaintext Parameters', description: 'A comma-delimited list of parameter strings that indicate a sensitive value', regex: '[a-zA-Z0-9,]', default: 'secret,password,privatekey' -======= - plainTextParameters: { - secretWords: [ - 'secret', 'password', 'privatekey' - ] ->>>>>>> 3da6672... Refactored code in plaintextParameters plugin and spec file } }, @@ -29,12 +23,8 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); -<<<<<<< HEAD var secretWords = this.settings.plain_text_parameters.default; -======= - secretWords = this.settings.plainTextParameters.secretWords; ->>>>>>> 3da6672... Refactored code in plaintextParameters plugin and spec file async.each(regions.cloudformation, function(region, rcb){ var describeStacks = helpers.addSource(cache, source, From 12d88c1f2b7f80c945494189d9df30615e60a929 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 21:24:30 +0500 Subject: [PATCH 25/76] Made PR requested changes --- plugins/aws/cloudformation/plainTextParameters.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 487cac1ccc..b41ada95bc 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -24,7 +24,6 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); var secretWords = this.settings.plain_text_parameters.default; - async.each(regions.cloudformation, function(region, rcb){ var describeStacks = helpers.addSource(cache, source, @@ -50,12 +49,12 @@ module.exports = { if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, - 'The template does not contain any potentially-sensitive parameters', region, resource); + 'Template does not contain any potentially-sensitive parameters', region, resource); return rcb(); } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && secretWords.includes(parameter.ParameterKey.toLowerCase())) { + if((!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()))) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); From 7dd1a5b4c70e20e199b066877fef1a606e508b3d Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sat, 15 Aug 2020 01:07:50 +0500 Subject: [PATCH 26/76] SPLOIT-113: Added regex to check if NoEcho is enabled --- plugins/aws/cloudformation/plainTextParameters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index b41ada95bc..3b1eeb2f8b 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -54,7 +54,7 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if((!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()))) { + if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match("^[\*]+$")) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); From c8a23c3104275291d6fccd34ce4007beb2bbd90a Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 04:13:40 +0500 Subject: [PATCH 27/76] Accommodated PR changes --- plugins/aws/cloudformation/plainTextParameters.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 3b1eeb2f8b..ee646df8dd 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -49,8 +49,8 @@ module.exports = { if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, - 'Template does not contain any potentially-sensitive parameters', region, resource); - return rcb(); + 'Template does not contain any parameters', region, resource); + continue; } stack.Parameters.forEach(function(parameter){ From 92821dd47008f13bc10143dd8c3b64db692b1f55 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 06:09:46 +0500 Subject: [PATCH 28/76] Fixed eslint issues --- plugins/aws/cloudformation/plainTextParameters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index ee646df8dd..32db53c891 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -54,7 +54,7 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match("^[\*]+$")) { + if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); From e32accc18389dc0e73db708f5bf184738bdab68c Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:42:00 +0500 Subject: [PATCH 29/76] Update index.js --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 6f61d149a8..019fc78f81 100644 --- a/index.js +++ b/index.js @@ -14,7 +14,7 @@ var GoogleConfig; // accessKeyId: '', // secretAccessKey: '', // sessionToken: '', -// region: 'us-east-1' +// region: '' // }; // AzureConfig = { From 90094a2c0401ac04f24fd08c5c7309596ae77200 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:48:02 +0500 Subject: [PATCH 30/76] Update index.js --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 019fc78f81..6f61d149a8 100644 --- a/index.js +++ b/index.js @@ -14,7 +14,7 @@ var GoogleConfig; // accessKeyId: '', // secretAccessKey: '', // sessionToken: '', -// region: '' +// region: 'us-east-1' // }; // AzureConfig = { From c29ab07cfdc4dde85c3d6b5468f3c69738643286 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 20:15:26 +0500 Subject: [PATCH 31/76] Accomodated PR changes --- plugins/aws/cloudformation/plainTextParameters.js | 10 ++++++---- .../cloudformation/plainTextParameters.spec.js | 15 ++++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 32db53c891..e98c754121 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -54,15 +54,17 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { - parameterFound = true; - helpers.addResult(results, 1, - 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); + if(parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { + foundStrings.push(parameter.ParameterKey); } }); if(foundStrings && foundStrings.length) { +<<<<<<< HEAD helpers.addResult(results, 2, +======= + helpers.addResult(results, 1, +>>>>>>> aac8ece... Accomodated PR changes 'Template contains the following potentially-sensitive parameters: ' + foundStrings, region, resource); } else { diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index d7ac6fed08..7493e245b3 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -147,11 +147,14 @@ describe('plaintextParameters', function () { it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { const cache = createCache([describeStacks[2]]); plaintextParameters.run(cache, {}, (err, results) => { - it('should PASS if Stack parameters does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { - const cache = createCache([describeStacks[1]]); - plainTextParameters.run(cache, settings, (err, results) => { - it('should PASS if template does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { - const cache = createCache([describeStacks[1]]); + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { + const cache = createCache([describeStacks[2]]); plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -161,7 +164,6 @@ describe('plaintextParameters', function () { it('should PASS if unable to describe stacks', function (done) { const cache = createCache([]); - plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -171,7 +173,6 @@ describe('plaintextParameters', function () { it('should PASS if there is no parameter in the stack', function (done) { const cache = createCache([describeStacks[2]]); - plaintextParameters.run(cache, {}, (err, results) => { plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); From 49f12025532e2a62511d4a7bf60af22af0060f9d Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 21:12:35 +0500 Subject: [PATCH 32/76] Updated status in result of failure --- plugins/aws/cloudformation/plainTextParameters.js | 4 ---- plugins/aws/cloudformation/plainTextParameters.spec.js | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index e98c754121..00289847cb 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -60,11 +60,7 @@ module.exports = { }); if(foundStrings && foundStrings.length) { -<<<<<<< HEAD helpers.addResult(results, 2, -======= - helpers.addResult(results, 1, ->>>>>>> aac8ece... Accomodated PR changes 'Template contains the following potentially-sensitive parameters: ' + foundStrings, region, resource); } else { diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index 7493e245b3..c590d10ce9 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -130,7 +130,7 @@ describe('plaintextParameters', function () { const cache = createCache([describeStacks[0]]); plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(1); + expect(results[0].status).to.equal(2); done(); }); }); From 278ad3fd5da36201f75905c5f41b480f2ddc05eb Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 17 Aug 2020 01:00:39 +0500 Subject: [PATCH 33/76] SPLOIT-947: Added 'Custom Open Ports' plugin --- exports.js | 1 + plugins/aws/ec2/openCustomPorts.js | 95 +++++++++++++ plugins/aws/ec2/openCustomPorts.spec.js | 169 ++++++++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 plugins/aws/ec2/openCustomPorts.js create mode 100644 plugins/aws/ec2/openCustomPorts.spec.js diff --git a/exports.js b/exports.js index 5a338cfa5e..e0d0841b15 100644 --- a/exports.js +++ b/exports.js @@ -79,6 +79,7 @@ module.exports = { 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), + 'openCustomPorts' : require(__dirname + '/plugins/aws/ec2/openCustomPorts.js'), 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js new file mode 100644 index 0000000000..9063f6453f --- /dev/null +++ b/plugins/aws/ec2/openCustomPorts.js @@ -0,0 +1,95 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Open Custom Ports', + category: 'EC2', + description: 'Ensures that the defined ports are not exposed publicly.', + more_info: 'Security groups should be used to restrict access to ports from known networks.', + link: 'https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html', + recommended_action: 'Modify the security group to ensure the ports are not exposed publicly.', + apis: ['EC2:describeSecurityGroups'], + settings: { + open_port_allowed_list: { + name: 'EC2 Allowed Open Ports', + description: 'A comma-delimited list of ports that indicates open ports allowed for any connection', + regex: '[a-zA-Z0-9,]', + default: [22, 443] + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + var allowed_open_ports = this.settings.open_port_allowed_list.default; + + async.each(regions.ec2, function(region, rcb){ + var describeSecurityGroups = helpers.addSource(cache, source, + ['ec2', 'describeSecurityGroups', region]); + + if (!describeSecurityGroups) return rcb(); + + if (describeSecurityGroups.err || !describeSecurityGroups.data) { + helpers.addResult(results, 3, + 'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region); + return rcb(); + } + + if (!describeSecurityGroups.data.length) { + helpers.addResult(results, 0, 'No security groups present', region); + return rcb(); + } + + var found = false; + var groups = describeSecurityGroups.data; + + for (var g in groups) { + var strings = []; + var resource = 'arn:aws:ec2:' + region + ':' + + groups[g].OwnerId + ':security-group/' + + groups[g].GroupId; + + for (var p in groups[g].IpPermissions) { + var permission = groups[g].IpPermissions[p]; + + for (var k in permission.IpRanges) { + var range = permission.IpRanges[k]; + + if (range.CidrIp === '0.0.0.0/0') { + var portRange = permission.ToPort - permission.FromPort; + + for (let p=0; p <= portRange; p++) { + var port = permission.FromPort + p; + + if (!allowed_open_ports.includes(port)) { + var string = permission.IpProtocol.toUpperCase() + + ' port ' + port + ' open to 0.0.0.0/0'; + if (strings.indexOf(string) === -1) strings.push(string); + found = true; + } + } + } + } + } + + if (strings.length) { + helpers.addResult(results, 2, + 'Security group: ' + groups[g].GroupId + + ' (' + groups[g].GroupName + + ') has ' + ': ' + strings.join(' and '), region, + resource); + } + } + + if (!found) { + helpers.addResult(results, 0, 'No public open ports found', region); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/ec2/openCustomPorts.spec.js b/plugins/aws/ec2/openCustomPorts.spec.js new file mode 100644 index 0000000000..83b682bb0c --- /dev/null +++ b/plugins/aws/ec2/openCustomPorts.spec.js @@ -0,0 +1,169 @@ +var expect = require('chai').expect; +const openCustomPorts = require('./openCustomPorts'); + +const securityGroups = [ + { + "Description": "Allows SSh access to developer", + "GroupName": "spec-test-sg", + "IpPermissions": [{ + "FromPort": 25, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [ + { + "CidrIpv6": "::/0" + } + ], + "PrefixListIds": [], + "ToPort": 25, + "UserIdGroupPairs": [] + }], + "OwnerId": "560213429563", + "GroupId": "sg-0b5f2771716acfee4", + "IpPermissionsEgress": [ + { + "FromPort": 25, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [ + { + "CidrIpv6": "::/0" + } + ], + "PrefixListIds": [], + "ToPort": 25, + "UserIdGroupPairs": [] + } + ], + "VpcId": "vpc-99de2fe4" + }, + { + "Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00", + "GroupName": "launch-wizard-1", + "IpPermissions": [ + { + "FromPort": 22, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "ToPort": 22, + "UserIdGroupPairs": [] + } + ], + "OwnerId": "560213429563", + "GroupId": "sg-0ff1642cae23c309a", + "IpPermissionsEgress": [ + { + "IpProtocol": "-1", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "UserIdGroupPairs": [] + } + ], + "VpcId": "vpc-99de2fe4" + } +] + +const createCache = (groups) => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': { + data: groups + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': { + err: { + message: 'error describing cloudformation stacks' + }, + }, + }, + }, + }; +}; + +const createNullCache = () => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': null, + }, + }, + }; +}; + +describe('openCustomPorts', function () { + describe('run', function () { + + it('should not return any results if unable to fetch any security groups description', function (done) { + const cache = createNullCache(); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + + it('should UNKNOWN if error occurs while fetching any security groups description', function (done) { + const cache = createErrorCache(); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should PASS if no security groups are present', function (done) { + const cache = createCache([]); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should FAIL if any public open port is found', function (done) { + const cache = createCache([securityGroups[0]]); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should PASS if no public open port is found', function (done) { + const cache = createCache([securityGroups[1]]); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + }); +}); \ No newline at end of file From 67a0d8148a8293e5e6c69464358b95b6d28a0dd5 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 20 Aug 2020 16:23:49 +0500 Subject: [PATCH 34/76] Refactor plugin file --- plugins/aws/ec2/openCustomPorts.js | 43 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index 9063f6453f..eedb3d52ec 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/aws'); module.exports = { title: 'Open Custom Ports', category: 'EC2', - description: 'Ensures that the defined ports are not exposed publicly.', + description: 'Ensures that the defined ports are not exposed publicly', more_info: 'Security groups should be used to restrict access to ports from known networks.', link: 'https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html', recommended_action: 'Modify the security group to ensure the ports are not exposed publicly.', @@ -28,6 +28,7 @@ module.exports = { async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, ['ec2', 'describeSecurityGroups', region]); + console.log(describeSecurityGroups); if (!describeSecurityGroups) return rcb(); @@ -42,22 +43,22 @@ module.exports = { return rcb(); } - var found = false; - var groups = describeSecurityGroups.data; + var portFound = false; - for (var g in groups) { - var strings = []; - var resource = 'arn:aws:ec2:' + region + ':' + - groups[g].OwnerId + ':security-group/' + - groups[g].GroupId; + for (var g in describeSecurityGroups.data) { + var group = describeSecurityGroups.data[g]; + var resource = group.GroupId; + var openPorts = []; - for (var p in groups[g].IpPermissions) { - var permission = groups[g].IpPermissions[p]; + if (!group.IpPermissions) continue; + + for (var p in group.IpPermissions) { + var permission = group.IpPermissions[p]; - for (var k in permission.IpRanges) { - var range = permission.IpRanges[k]; + for (var r in permission.IpRanges) { + var range = permission.IpRanges[r]; - if (range.CidrIp === '0.0.0.0/0') { + if (range.CidrIp && range.CidrIp === '0.0.0.0/0') { var portRange = permission.ToPort - permission.FromPort; for (let p=0; p <= portRange; p++) { @@ -66,25 +67,23 @@ module.exports = { if (!allowed_open_ports.includes(port)) { var string = permission.IpProtocol.toUpperCase() + ' port ' + port + ' open to 0.0.0.0/0'; - if (strings.indexOf(string) === -1) strings.push(string); - found = true; + if (openPorts.indexOf(string) === -1) openPorts.push(string); + portFound = true; } } } } } - if (strings.length) { + if (openPorts.length) { helpers.addResult(results, 2, - 'Security group: ' + groups[g].GroupId + - ' (' + groups[g].GroupName + - ') has ' + ': ' + strings.join(' and '), region, - resource); + 'Security group: ' + group.GroupName + ' has: ' + openPorts.join(' and '), + region, resource); } } - if (!found) { - helpers.addResult(results, 0, 'No public open ports found', region); + if (!portFound) { + helpers.addResult(results, 0, 'No public open ports found', region, resource); } rcb(); From e11122a55cf5d1502832dc13578ca99113ec8e3b Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 17 Aug 2020 01:00:39 +0500 Subject: [PATCH 35/76] SPLOIT-947: Added 'Custom Open Ports' plugin --- plugins/aws/ec2/openCustomPorts.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index eedb3d52ec..0f8addb8d1 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -28,7 +28,6 @@ module.exports = { async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, ['ec2', 'describeSecurityGroups', region]); - console.log(describeSecurityGroups); if (!describeSecurityGroups) return rcb(); From d9ac92d74345fe21fb673d1f739be1bd24c30b74 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 20 Aug 2020 16:23:49 +0500 Subject: [PATCH 36/76] Refactor plugin file --- plugins/aws/ec2/openCustomPorts.js | 28 +++++----- plugins/aws/ec2/openCustomPorts.spec.js | 70 ++++++++++++------------- 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index 0f8addb8d1..c0c99d02ee 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -14,7 +14,7 @@ module.exports = { name: 'EC2 Allowed Open Ports', description: 'A comma-delimited list of ports that indicates open ports allowed for any connection', regex: '[a-zA-Z0-9,]', - default: [22, 443] + default: [80, 443] } }, @@ -28,9 +28,7 @@ module.exports = { async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, ['ec2', 'describeSecurityGroups', region]); - if (!describeSecurityGroups) return rcb(); - if (describeSecurityGroups.err || !describeSecurityGroups.data) { helpers.addResult(results, 3, 'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region); @@ -38,12 +36,11 @@ module.exports = { } if (!describeSecurityGroups.data.length) { - helpers.addResult(results, 0, 'No security groups present', region); + helpers.addResult(results, 0, 'No security groups found', region); return rcb(); } - var portFound = false; - + // Loop through each security group for (var g in describeSecurityGroups.data) { var group = describeSecurityGroups.data[g]; var resource = group.GroupId; @@ -51,23 +48,24 @@ module.exports = { if (!group.IpPermissions) continue; + // Loop through each ip permissions in a security group for (var p in group.IpPermissions) { var permission = group.IpPermissions[p]; + // Loop through each ip range for an ip permissions list for (var r in permission.IpRanges) { var range = permission.IpRanges[r]; if (range.CidrIp && range.CidrIp === '0.0.0.0/0') { var portRange = permission.ToPort - permission.FromPort; + // Check for all the ports in port range for (let p=0; p <= portRange; p++) { var port = permission.FromPort + p; if (!allowed_open_ports.includes(port)) { - var string = permission.IpProtocol.toUpperCase() + - ' port ' + port + ' open to 0.0.0.0/0'; - if (openPorts.indexOf(string) === -1) openPorts.push(string); - portFound = true; + var openPort = permission.IpProtocol.toUpperCase() + ' port ' + port; + if (openPorts.indexOf(openPort) === -1) openPorts.push(openPort); } } } @@ -76,15 +74,15 @@ module.exports = { if (openPorts.length) { helpers.addResult(results, 2, - 'Security group: ' + group.GroupName + ' has: ' + openPorts.join(' and '), + 'Security group ' + group.GroupName + ' has: ' + openPorts.join(' , ') + ' open to 0.0.0.0/0', + region, resource); + } else { + helpers.addResult(results, 0, + 'Security group: ' + group.GroupName + ' has no open ports', region, resource); } } - if (!portFound) { - helpers.addResult(results, 0, 'No public open ports found', region, resource); - } - rcb(); }, function(){ callback(null, results, source); diff --git a/plugins/aws/ec2/openCustomPorts.spec.js b/plugins/aws/ec2/openCustomPorts.spec.js index 83b682bb0c..57f63f2c46 100644 --- a/plugins/aws/ec2/openCustomPorts.spec.js +++ b/plugins/aws/ec2/openCustomPorts.spec.js @@ -19,7 +19,7 @@ const securityGroups = [ } ], "PrefixListIds": [], - "ToPort": 25, + "ToPort": 30, "UserIdGroupPairs": [] }], "OwnerId": "560213429563", @@ -45,40 +45,40 @@ const securityGroups = [ ], "VpcId": "vpc-99de2fe4" }, - { - "Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00", - "GroupName": "launch-wizard-1", - "IpPermissions": [ - { - "FromPort": 22, - "IpProtocol": "tcp", - "IpRanges": [ - { - "CidrIp": "0.0.0.0/0" - } - ], - "Ipv6Ranges": [], - "PrefixListIds": [], - "ToPort": 22, - "UserIdGroupPairs": [] - } - ], - "OwnerId": "560213429563", - "GroupId": "sg-0ff1642cae23c309a", - "IpPermissionsEgress": [ - { - "IpProtocol": "-1", - "IpRanges": [ - { - "CidrIp": "0.0.0.0/0" - } - ], - "Ipv6Ranges": [], - "PrefixListIds": [], - "UserIdGroupPairs": [] - } - ], - "VpcId": "vpc-99de2fe4" + { + "Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00", + "GroupName": "launch-wizard-1", + "IpPermissions": [ + { + "FromPort": 80, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "ToPort": 80, + "UserIdGroupPairs": [] + } + ], + "OwnerId": "560213429563", + "GroupId": "sg-0ff1642cae23c309a", + "IpPermissionsEgress": [ + { + "IpProtocol": "-1", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "UserIdGroupPairs": [] + } + ], + "VpcId": "vpc-99de2fe4" } ] From a3ed63fbe5a078cd88ff6fef2fa9fc57caeacb32 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 24 Aug 2020 23:01:37 +0500 Subject: [PATCH 37/76] Updated openCustomPorts plugin --- plugins/aws/ec2/openCustomPorts.js | 2 +- plugins/aws/ec2/openCustomPorts.spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index c0c99d02ee..c8f0bbb3fe 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -23,7 +23,7 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); - var allowed_open_ports = this.settings.open_port_allowed_list.default; + var allowed_open_ports = settings.open_port_allowed_list || this.settings.open_port_allowed_list.default; async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, diff --git a/plugins/aws/ec2/openCustomPorts.spec.js b/plugins/aws/ec2/openCustomPorts.spec.js index 57f63f2c46..e32c2ccbb8 100644 --- a/plugins/aws/ec2/openCustomPorts.spec.js +++ b/plugins/aws/ec2/openCustomPorts.spec.js @@ -22,7 +22,7 @@ const securityGroups = [ "ToPort": 30, "UserIdGroupPairs": [] }], - "OwnerId": "560213429563", + "OwnerId": "12345654321", "GroupId": "sg-0b5f2771716acfee4", "IpPermissionsEgress": [ { @@ -63,7 +63,7 @@ const securityGroups = [ "UserIdGroupPairs": [] } ], - "OwnerId": "560213429563", + "OwnerId": "12345654321", "GroupId": "sg-0ff1642cae23c309a", "IpPermissionsEgress": [ { From 357cd0b45590f5b8c80966660fbbc6ac55e29ff8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 14 Aug 2020 05:55:55 +0500 Subject: [PATCH 38/76] SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation --- exports.js | 7 +++++ index.js | 16 ++++++++++ .../plainTextParameters.spec.js | 29 +++++++------------ 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/exports.js b/exports.js index 7139c7640e..c29e867d52 100644 --- a/exports.js +++ b/exports.js @@ -14,9 +14,13 @@ module.exports = { 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), +<<<<<<< HEAD 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), +======= + 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), @@ -32,7 +36,10 @@ module.exports = { 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), +<<<<<<< HEAD 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), +======= +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), diff --git a/index.js b/index.js index 26e612ef56..993593d97f 100755 --- a/index.js +++ b/index.js @@ -96,6 +96,22 @@ try { console.error('ERROR: Config file could not be loaded. Please ensure you have copied the config_example.js file to config.js'); process.exit(1); } +<<<<<<< HEAD +======= +if(process.env.GOOGLE_APPLICATION_CREDENTIALS){ + GoogleConfig = require(process.env.GOOGLE_APPLICATION_CREDENTIALS); + GoogleConfig.project = GoogleConfig.project_id; +} + +// Custom settings - place plugin-specific settings here +var settings = { + plainTextParameters: { + secretWords: [ + 'secret', 'password', 'privatekey' + ] + } +}; +>>>>>>> a4ea92f... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation function loadHelperFile(path) { try { diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index 03e8abf7e9..b75a66ddb5 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -115,29 +115,20 @@ const createNullCache = () => { }; }; -describe('plaintextParameters', function () { +describe('plainTextParameters', function () { describe('run', function () { - it('should FAIL if template contains one of secret words', function (done) { + it('should FAIL if Stack parameters contain one of secret words ["password" , "privatekey", "secret"]', function (done) { const cache = createCache([describeStacks[0]]); - plaintextParameters.run(cache, {}, (err, results) => { + plainTextParameters.run(cache, settings, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); + expect(results[0].status).to.equal(1); done(); }); }); - it('should PASS if template does not contain any of secret words', function (done) { + it('should PASS if Stack parameters does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { const cache = createCache([describeStacks[1]]); - plaintextParameters.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); - done(); - }); - }); - - it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { - const cache = createCache([describeStacks[2]]); - plaintextParameters.run(cache, {}, (err, results) => { + plainTextParameters.run(cache, settings, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -146,7 +137,7 @@ describe('plaintextParameters', function () { it('should PASS if unable to describe stacks', function (done) { const cache = createCache([]); - plaintextParameters.run(cache, {}, (err, results) => { + plainTextParameters.run(cache, settings, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -155,7 +146,7 @@ describe('plaintextParameters', function () { it('should PASS if there is no parameter in the stack', function (done) { const cache = createCache([describeStacks[2]]); - plaintextParameters.run(cache, {}, (err, results) => { + plainTextParameters.run(cache, settings, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -164,7 +155,7 @@ describe('plaintextParameters', function () { it('should not return any results if unable to fetch any stack description', function (done) { const cache = createNullCache(); - plaintextParameters.run(cache, {}, (err, results) => { + plainTextParameters.run(cache, settings, (err, results) => { expect(results.length).to.equal(0); done(); }); @@ -172,7 +163,7 @@ describe('plaintextParameters', function () { it('should UNKNOWN if error occurs while fetching stack description', function (done) { const cache = createErrorCache(); - plaintextParameters.run(cache, {}, (err, results) => { + plainTextParameters.run(cache, settings, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); done(); From 77ca002dbdc1dcaac51452167b071eb1dd9178cf Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 15:30:57 +0500 Subject: [PATCH 39/76] Added plugin and spec file for launch wizard security groups --- exports.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/exports.js b/exports.js index c29e867d52..7139c7640e 100644 --- a/exports.js +++ b/exports.js @@ -14,13 +14,9 @@ module.exports = { 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), -<<<<<<< HEAD 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), -======= - 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), @@ -36,10 +32,7 @@ module.exports = { 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), -<<<<<<< HEAD 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), -======= ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), From 73172b8eb8842afc4f6a69ba82aa763f9d8eacdf Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 13 Aug 2020 19:59:59 +0500 Subject: [PATCH 40/76] Added vpcEndpointAcceptance plugin and spec file --- plugins/aws/ec2/vpcEndpointAcceptance.spec.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js index 62053b7238..0946f5a682 100644 --- a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js +++ b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js @@ -112,6 +112,15 @@ describe('vpcEndpointAcceptance', function () { }); }); + it('should PASS if no VPC endpoint services are detected', function (done) { + const cache = createCache([]); + vpcEndpointAcceptance.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + it('should UNKNOWN if there was an error querying for VPC endpoint services', function (done) { const cache = createErrorCache(); vpcEndpointAcceptance.run(cache, {}, (err, results) => { From 7b448ff450d02aeda95714087905d9b060421bd1 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 16:50:46 +0500 Subject: [PATCH 41/76] Refactored code in plaintextParameters plugin and spec file --- .../aws/cloudformation/plainTextParameters.js | 22 +++++----- .../plainTextParameters.spec.js | 41 +++++++++++++++---- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index e03a98bd08..0b3e156b8a 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -10,11 +10,10 @@ module.exports = { recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], settings: { - plain_text_parameters: { - name: 'CloudFormation Plaintext Parameters', - description: 'A comma-delimited list of parameter strings that indicate a sensitive value', - regex: '[a-zA-Z0-9,]', - default: 'secret,password,privatekey' + plainTextParameters: { + secretWords: [ + 'secret', 'password', 'privatekey' + ] } }, @@ -22,7 +21,8 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); - var secretWords = this.settings.plain_text_parameters.default; + secretWords = this.settings.plainTextParameters.secretWords; + async.each(regions.cloudformation, function(region, rcb){ var describeStacks = helpers.addSource(cache, source, @@ -48,13 +48,15 @@ module.exports = { if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, - 'Template does not contain any parameters', region, resource); - continue; + 'The template does not contain any potentially-sensitive parameters', region, resource); + return rcb(); } stack.Parameters.forEach(function(parameter){ - if(parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { - foundStrings.push(parameter.ParameterKey); + if(!parameterFound && secretWords.includes(parameter.ParameterKey.toLowerCase())) { + parameterFound = true; + helpers.addResult(results, 1, + 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); } }); diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index b75a66ddb5..d7ac6fed08 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -115,20 +115,44 @@ const createNullCache = () => { }; }; -describe('plainTextParameters', function () { + +describe('plaintextParameters', function () { describe('run', function () { - it('should FAIL if Stack parameters contain one of secret words ["password" , "privatekey", "secret"]', function (done) { + it('should FAIL if template contains one of secret words', function (done) { const cache = createCache([describeStacks[0]]); - plainTextParameters.run(cache, settings, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + }); + }); + + it('should WARN if template contains one of secret words ["password" , "privatekey", "secret"]', function (done) { + const cache = createCache([describeStacks[0]]); + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(1); done(); }); }); + it('should PASS if template does not contain any of secret words', function (done) { + const cache = createCache([describeStacks[1]]); + plaintextParameters.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { + const cache = createCache([describeStacks[2]]); + plaintextParameters.run(cache, {}, (err, results) => { it('should PASS if Stack parameters does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { const cache = createCache([describeStacks[1]]); plainTextParameters.run(cache, settings, (err, results) => { + it('should PASS if template does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { + const cache = createCache([describeStacks[1]]); + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -137,7 +161,8 @@ describe('plainTextParameters', function () { it('should PASS if unable to describe stacks', function (done) { const cache = createCache([]); - plainTextParameters.run(cache, settings, (err, results) => { + + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -146,7 +171,8 @@ describe('plainTextParameters', function () { it('should PASS if there is no parameter in the stack', function (done) { const cache = createCache([describeStacks[2]]); - plainTextParameters.run(cache, settings, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -155,7 +181,8 @@ describe('plainTextParameters', function () { it('should not return any results if unable to fetch any stack description', function (done) { const cache = createNullCache(); - plainTextParameters.run(cache, settings, (err, results) => { + + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(0); done(); }); @@ -163,7 +190,7 @@ describe('plainTextParameters', function () { it('should UNKNOWN if error occurs while fetching stack description', function (done) { const cache = createErrorCache(); - plainTextParameters.run(cache, settings, (err, results) => { + plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); done(); From 50d9d70715bd00ba3b8e3b76269f2d8e97ea19f4 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 14 Aug 2020 18:09:45 +0500 Subject: [PATCH 42/76] SPLOIT-113: Updated custom settings --- index.js | 3 --- plugins/aws/cloudformation/plainTextParameters.js | 12 +++++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 993593d97f..b9e7b029ab 100755 --- a/index.js +++ b/index.js @@ -96,8 +96,6 @@ try { console.error('ERROR: Config file could not be loaded. Please ensure you have copied the config_example.js file to config.js'); process.exit(1); } -<<<<<<< HEAD -======= if(process.env.GOOGLE_APPLICATION_CREDENTIALS){ GoogleConfig = require(process.env.GOOGLE_APPLICATION_CREDENTIALS); GoogleConfig.project = GoogleConfig.project_id; @@ -111,7 +109,6 @@ var settings = { ] } }; ->>>>>>> a4ea92f... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation function loadHelperFile(path) { try { diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 0b3e156b8a..c9d9f83f33 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -10,10 +10,12 @@ module.exports = { recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], settings: { - plainTextParameters: { - secretWords: [ - 'secret', 'password', 'privatekey' - ] + + plain_text_parameters: { + name: 'CloudFormation Plaintext Parameters', + description: 'A comma-delimited list of parameter strings that indicate a sensitive value', + regex: '[a-zA-Z0-9,]', + default: 'secret,password,privatekey' } }, @@ -21,7 +23,7 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); - secretWords = this.settings.plainTextParameters.secretWords; + var secretWords = this.settings.plain_text_parameters.default; async.each(regions.cloudformation, function(region, rcb){ From 46ff92cf64080381f122946d5ea4ef79df76f0ec Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 21:24:30 +0500 Subject: [PATCH 43/76] Made PR requested changes --- plugins/aws/cloudformation/plainTextParameters.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index c9d9f83f33..e396861897 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -24,7 +24,6 @@ module.exports = { var source = {}; var regions = helpers.regions(settings); var secretWords = this.settings.plain_text_parameters.default; - async.each(regions.cloudformation, function(region, rcb){ var describeStacks = helpers.addSource(cache, source, @@ -50,12 +49,12 @@ module.exports = { if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, - 'The template does not contain any potentially-sensitive parameters', region, resource); + 'Template does not contain any potentially-sensitive parameters', region, resource); return rcb(); } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && secretWords.includes(parameter.ParameterKey.toLowerCase())) { + if((!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()))) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); From ec1e5efe8b96f6cbf75cb6f73df79de25008cc97 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sat, 15 Aug 2020 01:07:50 +0500 Subject: [PATCH 44/76] SPLOIT-113: Added regex to check if NoEcho is enabled --- plugins/aws/cloudformation/plainTextParameters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index e396861897..c51ac0dcf4 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -54,7 +54,7 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if((!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()))) { + if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match("^[\*]+$")) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); From e89dd5e81b5e61bbbce3be203de259815b53a023 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 04:13:40 +0500 Subject: [PATCH 45/76] Accommodated PR changes --- plugins/aws/cloudformation/plainTextParameters.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index c51ac0dcf4..19ac1eed53 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -49,8 +49,8 @@ module.exports = { if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, - 'Template does not contain any potentially-sensitive parameters', region, resource); - return rcb(); + 'Template does not contain any parameters', region, resource); + continue; } stack.Parameters.forEach(function(parameter){ From 4d7ee30cc8604f2fdb0fe778ffcb3c35502cfa62 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 06:09:46 +0500 Subject: [PATCH 46/76] Fixed eslint issues --- plugins/aws/cloudformation/plainTextParameters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 19ac1eed53..5bda4d33b1 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -54,7 +54,7 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match("^[\*]+$")) { + if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); From f5c9bf0799a1bcd75b9c7648ceea7140a6498fcd Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:42:00 +0500 Subject: [PATCH 47/76] Update index.js --- index.js | 138 +++++++++++++++++++++++++++---------------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/index.js b/index.js index b9e7b029ab..0484fec705 100755 --- a/index.js +++ b/index.js @@ -1,74 +1,74 @@ #!/usr/bin/env node -const { ArgumentParser } = require('argparse'); -const engine = require('./engine'); - -console.log(` - _____ _ _ _____ _ _ _ - / ____| | | |/ ____| | | (_) | - | | | | ___ _ _ __| | (___ _ __ | | ___ _| |_ - | | | |/ _ \\| | | |/ _\` |\\___ \\| '_ \\| |/ _ \\| | __| - | |____| | (_) | |_| | (_| |____) | |_) | | (_) | | |_ - \\_____|_|\\___/ \\__,_|\\__,_|_____/| .__/|_|\\___/|_|\\__| - | | - |_| - - CloudSploit by Aqua Security, Ltd. - Cloud security auditing for AWS, Azure, GCP, Oracle, and GitHub -`); - -const parser = new ArgumentParser({}); - -parser.add_argument('--config', { - help: 'The path to a CloudSploit config file containing cloud credentials. See config_example.js' -}); - -parser.add_argument('--compliance', { - help: 'Compliance mode. Only return results applicable to the selected program.', - choices: ['hipaa', 'cis', 'cis1', 'cis2', 'pci'], - action: 'append' -}); -parser.add_argument('--plugin', { - help: 'A specific plugin to run. If none provided, all plugins will be run. Obtain from the exports.js file. E.g. acmValidation' -}); -parser.add_argument('--govcloud', { - help: 'AWS only. Enables GovCloud mode.', - action: 'store_true' -}); -parser.add_argument('--china', { - help: 'AWS only. Enables AWS China mode.', - action: 'store_true' -}); -parser.add_argument('--csv', { help: 'Output: CSV file' }); -parser.add_argument('--json', { help: 'Output: JSON file' }); -parser.add_argument('--junit', { help: 'Output: Junit file' }); -parser.add_argument('--console', { - help: 'Console output format. Default: table', - choices: ['none', 'text', 'table'], - default: 'table' -}); -parser.add_argument('--collection', { help: 'Output: full collection JSON as file' }); -parser.add_argument('--ignore-ok', { - help: 'Ignore passing (OK) results', - action: 'store_true' -}); -parser.add_argument('--exit-code', { - help: 'Exits with a non-zero status code if non-passing results are found', - action: 'store_true' -}); -parser.add_argument('--skip-paginate', { - help: 'AWS only. Skips pagination (for debugging).', - action: 'store_false' -}); -parser.add_argument('--suppress', { - help: 'Suppress results matching the provided Regex. Format: pluginId:region:resourceId', - action: 'append' -}); - -let settings = parser.parse_args(); -let cloudConfig = {}; - -settings.cloud = 'aws'; +var engine = require('./engine'); + +var AWSConfig; +var AzureConfig; +var GitHubConfig; +var OracleConfig; +var GoogleConfig; + +// OPTION 1: Configure service provider credentials through hard-coded config objects + +// AWSConfig = { +// accessKeyId: '', +// secretAccessKey: '', +// sessionToken: '', +// region: '' +// }; + +// AzureConfig = { +// ApplicationID: '', // A.K.A ClientID +// KeyValue: '', // Secret +// DirectoryID: '', // A.K.A TenantID or Domain +// SubscriptionID: '', +// location: 'East US' +// }; + +// GitHubConfig = { +// token: '', // GitHub app token +// url: 'https://api.github.com', // BaseURL if not using public GitHub +// organization: false, // Set to true if the login is an organization +// login: '' // The login id for the user or organization +// }; + +// Oracle Important Note: +// Please read Oracle API's key generation instructions: config/_oracle/keys/Readme.md +// You will want an API signing key to fill the keyFingerprint and privateKey params +// OracleConfig = { +// RESTversion: '/20160918', +// tenancyId: 'ocid1.tenancy.oc1..', +// compartmentId: 'ocid1.compartment.oc1..', +// userId: 'ocid1.user.oc1..', +// keyFingerprint: 'YOURKEYFINGERPRINT', +// keyValue: "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-GOES-HERE\n-----END PRIVATE KEY-----\n", +// region: 'us-ashburn-1', +// }; + +// GoogleConfig = { +// "type": "service_account", +// "project": "your-project-name", +// "client_email": "cloudsploit@your-project-name.iam.gserviceaccount.com", +// "private_key": "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-GOES-HERE\n-----END PRIVATE KEY-----\n", +// }; + +// OPTION 2: Import a service provider config file containing credentials + +// AWSConfig = require(__dirname + '/aws_credentials.json'); +// AzureConfig = require(__dirname + '/azure_credentials.json'); +// GitHubConfig = require(__dirname + '/github_credentials.json'); +// OracleConfig = require(__dirname + '/oracle_credentials.json'); +// GoogleConfig = require(__dirname + '/google_credentials.json'); + +// OPTION 3: ENV configuration with service provider env vars +if(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY){ + AWSConfig = { + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + sessionToken: process.env.AWS_SESSION_TOKEN, + region: process.env.AWS_DEFAULT_REGION || 'us-east-1' + }; +} // Now execute the scans using the defined configuration information. if (!settings.config) { From 53e18b8d6f575caa387507c1dcc5e1fa59914c58 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:48:02 +0500 Subject: [PATCH 48/76] Update index.js --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 0484fec705..de6616b22a 100755 --- a/index.js +++ b/index.js @@ -14,7 +14,7 @@ var GoogleConfig; // accessKeyId: '', // secretAccessKey: '', // sessionToken: '', -// region: '' +// region: 'us-east-1' // }; // AzureConfig = { From 6ec73bc80abccbaaa104aa932fc6e48d7ae6f436 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 20:15:26 +0500 Subject: [PATCH 49/76] Accomodated PR changes --- plugins/aws/cloudformation/plainTextParameters.js | 10 ++++++---- .../cloudformation/plainTextParameters.spec.js | 15 ++++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 5bda4d33b1..94e7f92cff 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -54,15 +54,17 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { - parameterFound = true; - helpers.addResult(results, 1, - 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); + if(parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { + foundStrings.push(parameter.ParameterKey); } }); if(foundStrings && foundStrings.length) { +<<<<<<< HEAD helpers.addResult(results, 2, +======= + helpers.addResult(results, 1, +>>>>>>> aac8ece... Accomodated PR changes 'Template contains the following potentially-sensitive parameters: ' + foundStrings, region, resource); } else { diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index d7ac6fed08..7493e245b3 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -147,11 +147,14 @@ describe('plaintextParameters', function () { it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { const cache = createCache([describeStacks[2]]); plaintextParameters.run(cache, {}, (err, results) => { - it('should PASS if Stack parameters does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { - const cache = createCache([describeStacks[1]]); - plainTextParameters.run(cache, settings, (err, results) => { - it('should PASS if template does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { - const cache = createCache([describeStacks[1]]); + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { + const cache = createCache([describeStacks[2]]); plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -161,7 +164,6 @@ describe('plaintextParameters', function () { it('should PASS if unable to describe stacks', function (done) { const cache = createCache([]); - plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); @@ -171,7 +173,6 @@ describe('plaintextParameters', function () { it('should PASS if there is no parameter in the stack', function (done) { const cache = createCache([describeStacks[2]]); - plaintextParameters.run(cache, {}, (err, results) => { plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); From 2f55a118e1ad6692c2ea78209ec6852cb7782354 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 21:12:35 +0500 Subject: [PATCH 50/76] Updated status in result of failure --- plugins/aws/cloudformation/plainTextParameters.js | 4 ---- plugins/aws/cloudformation/plainTextParameters.spec.js | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 94e7f92cff..133fa51b6b 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -60,11 +60,7 @@ module.exports = { }); if(foundStrings && foundStrings.length) { -<<<<<<< HEAD helpers.addResult(results, 2, -======= - helpers.addResult(results, 1, ->>>>>>> aac8ece... Accomodated PR changes 'Template contains the following potentially-sensitive parameters: ' + foundStrings, region, resource); } else { diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index 7493e245b3..c590d10ce9 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -130,7 +130,7 @@ describe('plaintextParameters', function () { const cache = createCache([describeStacks[0]]); plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(1); + expect(results[0].status).to.equal(2); done(); }); }); From 0ba2fbf09b4518ed41903f7a68809b6a3179cf6b Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Thu, 13 Aug 2020 00:34:00 +0500 Subject: [PATCH 51/76] SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation --- exports.js | 3 - .../aws/cloudformation/plainTextParameters.js | 99 +++++++++---------- 2 files changed, 46 insertions(+), 56 deletions(-) diff --git a/exports.js b/exports.js index 7139c7640e..d2ab19673e 100644 --- a/exports.js +++ b/exports.js @@ -14,9 +14,7 @@ module.exports = { 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), - 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), @@ -32,7 +30,6 @@ module.exports = { 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), - 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 133fa51b6b..0b4863765c 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -1,4 +1,3 @@ -var async = require('async'); var helpers = require('../../../helpers/aws'); module.exports = { @@ -9,69 +8,63 @@ module.exports = { link: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html', recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], - settings: { - - plain_text_parameters: { - name: 'CloudFormation Plaintext Parameters', - description: 'A comma-delimited list of parameter strings that indicate a sensitive value', - regex: '[a-zA-Z0-9,]', - default: 'secret,password,privatekey' - } + compliance: { + hipaa: 'HIPAA requires all data to be transmitted over secure channels. ' + + 'CloudFront HTTPS redirection should be used to ensure site visitors ' + + 'are always connecting over a secure channel.' }, + // settings : { secretWords : ["password", "privatekey", "secret"] }, run: function(cache, settings, callback) { + var results = []; var source = {}; - var regions = helpers.regions(settings); - var secretWords = this.settings.plain_text_parameters.default; - async.each(regions.cloudformation, function(region, rcb){ - var describeStacks = helpers.addSource(cache, source, - ['cloudformation', 'describeStacks', region]); - if (!describeStacks) return rcb(); + var region = helpers.defaultRegion(settings); - if (describeStacks.err || !describeStacks.data) { - helpers.addResult(results, 3, - 'Unable to describe stacks: ' + helpers.addError(describeStacks), region); - return rcb(); - } + var describeStacks = helpers.addSource(cache, source, + ['cloudformation', 'describeStacks', region]); - if (!describeStacks.data.length) { - helpers.addResult(results, 0, 'No CloudFormation stacks found', region); - return rcb(); - } - - for (var s in describeStacks.data){ - // arn:aws:cloudformation:region:account-id:stack/stack-name/stack-id - var stack = describeStacks.data[s]; - var resource = stack.StackId; - let foundStrings = []; + console.log(describeStacks); + console.log("results received"); + // if (!describeStacks) return callback(null, results, source); - if(!stack.Parameters || !stack.Parameters.length) { - helpers.addResult(results, 0, - 'Template does not contain any parameters', region, resource); - continue; - } + // if (describeStacks.err || !describeStacks.data) { + // helpers.addResult(results, 3, + // 'Unable to describe stacks: ' + helpers.addError(describeStacks)); + // return callback(null, results, source); + // } - stack.Parameters.forEach(function(parameter){ - if(parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { - foundStrings.push(parameter.ParameterKey); - } - }); + // if (!describeStacks.data.length) { + // helpers.addResult(results, 0, 'No stacks descriptions found'); + // return callback(null, results, source); + // } + // console.log(describeStacks.data); + // loop through stacks for every template retrieval + // describeStacks.data.forEach(function(Distribution){ + // var stackTemplate = helpers.addSource(cache, source, + // ['cloudformation', 'getTemplate', region]); + + // if (!describeStacks) return callback(null, results, source); + + // if (describeStacks.err || !describeStacks.data) { + // helpers.addResult(results, 3, + // 'Unable to describe stacks: ' + helpers.addError(describeStacks)); + // return callback(null, results, source); + // } - if(foundStrings && foundStrings.length) { - helpers.addResult(results, 2, - 'Template contains the following potentially-sensitive parameters: ' + foundStrings, region, resource); - } - else { - helpers.addResult(results, 0, - 'Template does not contain any potentially-sensitive parameters', region, resource); - } - } + // if (Distribution.DefaultCacheBehavior.ViewerProtocolPolicy == 'redirect-to-https') { + // helpers.addResult(results, 0, 'CloudFront distribution ' + + // 'is configured to redirect non-HTTPS traffic to HTTPS', 'global', Distribution.ARN); + // } else if (Distribution.DefaultCacheBehavior.ViewerProtocolPolicy == 'https-only') { + // helpers.addResult(results, 0, 'The CloudFront ' + + // 'distribution is set to use HTTPS only.', 'global', Distribution.ARN); + // } else { + // helpers.addResult(results, 2, 'CloudFront distribution ' + + // 'is not configured to use HTTPS', 'global', Distribution.ARN); + // } + // }); - rcb(); - }, function(){ - callback(null, results, source); - }); + callback(null, results, source); } }; From e9415b917bd99069cbf1fb8c3a9423ae127fb51b Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 14 Aug 2020 05:55:55 +0500 Subject: [PATCH 52/76] SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation --- exports.js | 6 +- index.js | 15 +-- .../aws/cloudformation/plainTextParameters.js | 91 ++++++++-------- .../plainTextParameters.spec.js | 100 ++++++++++++++++++ 4 files changed, 150 insertions(+), 62 deletions(-) diff --git a/exports.js b/exports.js index d2ab19673e..fa901a2af7 100644 --- a/exports.js +++ b/exports.js @@ -5,7 +5,6 @@ module.exports = { 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), - 'emptyASG' : require(__dirname + '/plugins/aws/autoscaling/emptyASG.js'), 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), @@ -72,9 +71,8 @@ module.exports = { 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), - 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), + 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), - 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), @@ -114,7 +112,6 @@ module.exports = { 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), - 'iamRoleLastUsed' : require(__dirname + '/plugins/aws/iam/iamRoleLastUsed.js'), 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), @@ -125,7 +122,6 @@ module.exports = { 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), - 'rootSigningCertificate' : require(__dirname + '/plugins/aws/iam/rootSigningCertificate.js'), 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), diff --git a/index.js b/index.js index de6616b22a..45aa3d7df9 100755 --- a/index.js +++ b/index.js @@ -110,16 +110,11 @@ var settings = { } }; -function loadHelperFile(path) { - try { - var contents = require(path); - } catch (e) { - console.error(`ERROR: The credential file could not be loaded ${path}`); - console.error(e); - process.exit(1); - } - return contents; -} +// If running in GovCloud, uncomment the following +// settings.govcloud = true; + +// If running in AWS China, uncomment the following +// settings.china = true; function checkRequiredKeys(obj, keys) { keys.forEach(function(key){ diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 0b4863765c..f57b6ec2b7 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -1,3 +1,4 @@ +var async = require('async'); var helpers = require('../../../helpers/aws'); module.exports = { @@ -8,63 +9,59 @@ module.exports = { link: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html', recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], - compliance: { - hipaa: 'HIPAA requires all data to be transmitted over secure channels. ' + - 'CloudFront HTTPS redirection should be used to ensure site visitors ' + - 'are always connecting over a secure channel.' - }, - // settings : { secretWords : ["password", "privatekey", "secret"] }, run: function(cache, settings, callback) { - var results = []; var source = {}; + var regions = helpers.regions(settings); + secretWords = settings.plainTextParameters.secretWords; - var region = helpers.defaultRegion(settings); + async.each(regions.cloudformation, function(region, rcb){ - var describeStacks = helpers.addSource(cache, source, - ['cloudformation', 'describeStacks', region]); + var describeStacks = helpers.addSource(cache, source, + ['cloudformation', 'describeStacks', region]); + + if (!describeStacks) return rcb(); - console.log(describeStacks); - console.log("results received"); - // if (!describeStacks) return callback(null, results, source); + if (describeStacks.err || !describeStacks.data) { + helpers.addResult(results, 3, + 'Unable to describe stacks: ' + helpers.addError(describeStacks), region); + return rcb(); + } - // if (describeStacks.err || !describeStacks.data) { - // helpers.addResult(results, 3, - // 'Unable to describe stacks: ' + helpers.addError(describeStacks)); - // return callback(null, results, source); - // } + if (!describeStacks.data.length) { + helpers.addResult(results, 0, 'No stack description found', region); + return rcb(); + } + + var parameterFound; + describeStacks.data.forEach(function(stack){ + parameterFound = false; - // if (!describeStacks.data.length) { - // helpers.addResult(results, 0, 'No stacks descriptions found'); - // return callback(null, results, source); - // } - // console.log(describeStacks.data); - // loop through stacks for every template retrieval - // describeStacks.data.forEach(function(Distribution){ - // var stackTemplate = helpers.addSource(cache, source, - // ['cloudformation', 'getTemplate', region]); - - // if (!describeStacks) return callback(null, results, source); - - // if (describeStacks.err || !describeStacks.data) { - // helpers.addResult(results, 3, - // 'Unable to describe stacks: ' + helpers.addError(describeStacks)); - // return callback(null, results, source); - // } + if(!stack.Parameters.length) { + helpers.addResult(results, 0, + 'The template did not contain any potentially-sensitive parameters', region); + return; + } - // if (Distribution.DefaultCacheBehavior.ViewerProtocolPolicy == 'redirect-to-https') { - // helpers.addResult(results, 0, 'CloudFront distribution ' + - // 'is configured to redirect non-HTTPS traffic to HTTPS', 'global', Distribution.ARN); - // } else if (Distribution.DefaultCacheBehavior.ViewerProtocolPolicy == 'https-only') { - // helpers.addResult(results, 0, 'The CloudFront ' + - // 'distribution is set to use HTTPS only.', 'global', Distribution.ARN); - // } else { - // helpers.addResult(results, 2, 'CloudFront distribution ' + - // 'is not configured to use HTTPS', 'global', Distribution.ARN); - // } - // }); + stack.Parameters.forEach(function(parameter){ + if(secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameterFound) { + parameterFound = true; + helpers.addResult(results, 1, + 'The template contained one of the following potentially-sensitive parameters: secret, key, password', region); + return; + } + }); + + if(!parameterFound) { + helpers.addResult(results, 0, + 'The template did not contain any potentially-sensitive parameters', region); + } - callback(null, results, source); + }); + rcb(); + }, function(){ + callback(null, results, source); + }); } }; diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index c590d10ce9..238ff315a9 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -1,4 +1,5 @@ var expect = require('chai').expect; +<<<<<<< HEAD const plaintextParameters = require('./plainTextParameters'); const describeStacks = [ @@ -77,6 +78,73 @@ const describeStacks = [ Tags: [], DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } } +======= +const plainTextParameters = require('./plainTextParameters'); +const settings = { + plainTextParameters: { + secretWords: [ + 'secret', 'password', 'privatekey' + ] + } +}; +const describeStacks = [ + { + StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', + StackName: 'TestStack', + Parameters: [ + { + ParameterKey: 'Secret', + ParameterValue: 'bucketwithsecretparameter1' + }, + { + ParameterKey: 'Password', + ParameterValue: 'bucketwithsecretparameter1' + } + ], + CreationTime: '2020-08-13T13:34:52.435Z', + RollbackConfiguration: { RollbackTriggers: [] }, + StackStatus: 'CREATE_COMPLETE', + DisableRollback: false, + NotificationARNs: [], + Capabilities: [], + Outputs: [], + Tags: [], + DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } + }, + { + StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', + StackName: 'TestStack', + Parameters: [ + { + ParameterKey: 'S3BucketName', + ParameterValue: 'testbucketplaintext1' + } + ], + CreationTime: '2020-08-12T09:42:04.803Z', + RollbackConfiguration: { RollbackTriggers: [] }, + StackStatus: 'CREATE_COMPLETE', + DisableRollback: false, + NotificationARNs: [], + Capabilities: [], + Outputs: [], + Tags: [], + DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } + }, + { + StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', + StackName: 'TestStack', + Parameters: [], + CreationTime: '2020-08-12T09:42:04.803Z', + RollbackConfiguration: { RollbackTriggers: [] }, + StackStatus: 'CREATE_COMPLETE', + DisableRollback: false, + NotificationARNs: [], + Capabilities: [], + Outputs: [], + Tags: [], + DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } + } +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation ] const createCache = (stacks) => { @@ -115,6 +183,7 @@ const createNullCache = () => { }; }; +<<<<<<< HEAD describe('plaintextParameters', function () { describe('run', function () { @@ -131,10 +200,20 @@ describe('plaintextParameters', function () { plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); +======= +describe('plainTextParameters', function () { + describe('run', function () { + it('should FAIL if Stack parameters contain one of secret words ["password" , "privatekey", "secret"]', function (done) { + const cache = createCache([describeStacks[0]]); + plainTextParameters.run(cache, settings, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(1); +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation done(); }); }); +<<<<<<< HEAD it('should PASS if template does not contain any of secret words', function (done) { const cache = createCache([describeStacks[1]]); plaintextParameters.run(cache, {}, (err, results) => { @@ -156,6 +235,11 @@ describe('plaintextParameters', function () { it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { const cache = createCache([describeStacks[2]]); plaintextParameters.run(cache, {}, (err, results) => { +======= + it('should PASS if Stack parameters does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { + const cache = createCache([describeStacks[1]]); + plainTextParameters.run(cache, settings, (err, results) => { +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -164,7 +248,11 @@ describe('plaintextParameters', function () { it('should PASS if unable to describe stacks', function (done) { const cache = createCache([]); +<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { +======= + plainTextParameters.run(cache, settings, (err, results) => { +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -173,7 +261,11 @@ describe('plaintextParameters', function () { it('should PASS if there is no parameter in the stack', function (done) { const cache = createCache([describeStacks[2]]); +<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { +======= + plainTextParameters.run(cache, settings, (err, results) => { +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -182,8 +274,12 @@ describe('plaintextParameters', function () { it('should not return any results if unable to fetch any stack description', function (done) { const cache = createNullCache(); +<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { +======= + plainTextParameters.run(cache, settings, (err, results) => { +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(0); done(); }); @@ -191,7 +287,11 @@ describe('plaintextParameters', function () { it('should UNKNOWN if error occurs while fetching stack description', function (done) { const cache = createErrorCache(); +<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { +======= + plainTextParameters.run(cache, settings, (err, results) => { +>>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); done(); From 882077517afe5da597b13ec40e4d705ae7613872 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 15:30:57 +0500 Subject: [PATCH 53/76] Added plugin and spec file for launch wizard security groups --- exports.js | 4 +++- plugins/aws/ec2/launchWizardSecurityGroups.js | 15 ++++----------- plugins/aws/ec2/vpcEndpointAcceptance.spec.js | 9 --------- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/exports.js b/exports.js index fa901a2af7..56084148d3 100644 --- a/exports.js +++ b/exports.js @@ -29,6 +29,7 @@ module.exports = { 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), + 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), @@ -71,8 +72,9 @@ module.exports = { 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), - 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), + 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), + 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), diff --git a/plugins/aws/ec2/launchWizardSecurityGroups.js b/plugins/aws/ec2/launchWizardSecurityGroups.js index 5c73babd28..252cabd11c 100644 --- a/plugins/aws/ec2/launchWizardSecurityGroups.js +++ b/plugins/aws/ec2/launchWizardSecurityGroups.js @@ -28,25 +28,18 @@ module.exports = { } if (!describeSecurityGroups.data.length) { - helpers.addResult(results, 0, 'No security groups found', region); + helpers.addResult(results, 0, 'No security groups present', region); return rcb(); } for (var s in describeSecurityGroups.data) { var sg = describeSecurityGroups.data[s]; - var resource = 'arn:aws:ec2:' + region + ':' + sg.OwnerId + ':security-group/' + sg.GroupId; + var resource = sg.GroupId; - if(!sg.GroupName) { - helpers.addResult(results, 2, - 'Unable to get group name of security group', - region, resource); - continue; - } - if (sg.GroupName.toLowerCase().startsWith('launch-wizard')) { helpers.addResult(results, 2, - 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', - region, resource); + 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', + region, resource); } else { helpers.addResult(results, 0, 'Security Group ' + sg.GroupName + ' was not launched using EC2 launch wizard', diff --git a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js index 0946f5a682..62053b7238 100644 --- a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js +++ b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js @@ -112,15 +112,6 @@ describe('vpcEndpointAcceptance', function () { }); }); - it('should PASS if no VPC endpoint services are detected', function (done) { - const cache = createCache([]); - vpcEndpointAcceptance.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); - done(); - }); - }); - it('should UNKNOWN if there was an error querying for VPC endpoint services', function (done) { const cache = createErrorCache(); vpcEndpointAcceptance.run(cache, {}, (err, results) => { From 8e6b23b5ad41c0a70bfabff1276416718c9039d1 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 13 Aug 2020 19:59:59 +0500 Subject: [PATCH 54/76] Added vpcEndpointAcceptance plugin and spec file --- plugins/aws/ec2/vpcEndpointAcceptance.spec.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js index 62053b7238..0946f5a682 100644 --- a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js +++ b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js @@ -112,6 +112,15 @@ describe('vpcEndpointAcceptance', function () { }); }); + it('should PASS if no VPC endpoint services are detected', function (done) { + const cache = createCache([]); + vpcEndpointAcceptance.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + it('should UNKNOWN if there was an error querying for VPC endpoint services', function (done) { const cache = createErrorCache(); vpcEndpointAcceptance.run(cache, {}, (err, results) => { From 82d840671935c1139fabb28f8f786918e4b02a13 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 16:50:46 +0500 Subject: [PATCH 55/76] Refactored code in plaintextParameters plugin and spec file --- exports.js | 4 +- index.js | 8 +- .../aws/cloudformation/plainTextParameters.js | 28 +++-- .../plainTextParameters.spec.js | 119 ------------------ 4 files changed, 23 insertions(+), 136 deletions(-) diff --git a/exports.js b/exports.js index 56084148d3..ee2b81f9ee 100644 --- a/exports.js +++ b/exports.js @@ -13,7 +13,9 @@ module.exports = { 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), + + 'plaintextParameters' : require(__dirname + '/plugins/aws/cloudformation/plaintextParameters.js'), + 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), diff --git a/index.js b/index.js index 45aa3d7df9..53b6b4fb75 100755 --- a/index.js +++ b/index.js @@ -102,13 +102,7 @@ if(process.env.GOOGLE_APPLICATION_CREDENTIALS){ } // Custom settings - place plugin-specific settings here -var settings = { - plainTextParameters: { - secretWords: [ - 'secret', 'password', 'privatekey' - ] - } -}; +var settings = {}; // If running in GovCloud, uncomment the following // settings.govcloud = true; diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index f57b6ec2b7..8e538c23d4 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -9,12 +9,19 @@ module.exports = { link: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html', recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], + settings: { + plainTextParameters: { + secretWords: [ + 'secret', 'password', 'privatekey' + ] + } + }, run: function(cache, settings, callback) { var results = []; var source = {}; var regions = helpers.regions(settings); - secretWords = settings.plainTextParameters.secretWords; + secretWords = this.settings.plainTextParameters.secretWords; async.each(regions.cloudformation, function(region, rcb){ @@ -35,30 +42,33 @@ module.exports = { } var parameterFound; - describeStacks.data.forEach(function(stack){ + for (var s in describeStacks.data){ + // arn:aws:cloudformation:region:account-id:stack/stack-name/stack-id + var stack = describeStacks.data[s]; + var resource = stack.StackId; parameterFound = false; if(!stack.Parameters.length) { helpers.addResult(results, 0, - 'The template did not contain any potentially-sensitive parameters', region); - return; + 'The template does not contain any potentially-sensitive parameters', region, resource); + return rcb(); } stack.Parameters.forEach(function(parameter){ - if(secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameterFound) { + if(!parameterFound && secretWords.includes(parameter.ParameterKey.toLowerCase())) { parameterFound = true; helpers.addResult(results, 1, - 'The template contained one of the following potentially-sensitive parameters: secret, key, password', region); - return; + 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); } }); if(!parameterFound) { helpers.addResult(results, 0, - 'The template did not contain any potentially-sensitive parameters', region); + 'Template does not contain any potentially-sensitive parameters', region, resource); } - }); + } + rcb(); }, function(){ callback(null, results, source); diff --git a/plugins/aws/cloudformation/plainTextParameters.spec.js b/plugins/aws/cloudformation/plainTextParameters.spec.js index 238ff315a9..03e8abf7e9 100644 --- a/plugins/aws/cloudformation/plainTextParameters.spec.js +++ b/plugins/aws/cloudformation/plainTextParameters.spec.js @@ -1,5 +1,4 @@ var expect = require('chai').expect; -<<<<<<< HEAD const plaintextParameters = require('./plainTextParameters'); const describeStacks = [ @@ -78,73 +77,6 @@ const describeStacks = [ Tags: [], DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } } -======= -const plainTextParameters = require('./plainTextParameters'); -const settings = { - plainTextParameters: { - secretWords: [ - 'secret', 'password', 'privatekey' - ] - } -}; -const describeStacks = [ - { - StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', - StackName: 'TestStack', - Parameters: [ - { - ParameterKey: 'Secret', - ParameterValue: 'bucketwithsecretparameter1' - }, - { - ParameterKey: 'Password', - ParameterValue: 'bucketwithsecretparameter1' - } - ], - CreationTime: '2020-08-13T13:34:52.435Z', - RollbackConfiguration: { RollbackTriggers: [] }, - StackStatus: 'CREATE_COMPLETE', - DisableRollback: false, - NotificationARNs: [], - Capabilities: [], - Outputs: [], - Tags: [], - DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } - }, - { - StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', - StackName: 'TestStack', - Parameters: [ - { - ParameterKey: 'S3BucketName', - ParameterValue: 'testbucketplaintext1' - } - ], - CreationTime: '2020-08-12T09:42:04.803Z', - RollbackConfiguration: { RollbackTriggers: [] }, - StackStatus: 'CREATE_COMPLETE', - DisableRollback: false, - NotificationARNs: [], - Capabilities: [], - Outputs: [], - Tags: [], - DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } - }, - { - StackId: 'arn:aws:cloudformation:us-east-1:55005500:stack/TestStack/1493b310-dc80-11ea-b8ab-1214c28caebf', - StackName: 'TestStack', - Parameters: [], - CreationTime: '2020-08-12T09:42:04.803Z', - RollbackConfiguration: { RollbackTriggers: [] }, - StackStatus: 'CREATE_COMPLETE', - DisableRollback: false, - NotificationARNs: [], - Capabilities: [], - Outputs: [], - Tags: [], - DriftInformation: { StackDriftStatus: 'NOT_CHECKED' } - } ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation ] const createCache = (stacks) => { @@ -183,8 +115,6 @@ const createNullCache = () => { }; }; -<<<<<<< HEAD - describe('plaintextParameters', function () { describe('run', function () { it('should FAIL if template contains one of secret words', function (done) { @@ -192,28 +122,10 @@ describe('plaintextParameters', function () { plaintextParameters.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); expect(results[0].status).to.equal(2); - }); - }); - - it('should WARN if template contains one of secret words ["password" , "privatekey", "secret"]', function (done) { - const cache = createCache([describeStacks[0]]); - plaintextParameters.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); -======= -describe('plainTextParameters', function () { - describe('run', function () { - it('should FAIL if Stack parameters contain one of secret words ["password" , "privatekey", "secret"]', function (done) { - const cache = createCache([describeStacks[0]]); - plainTextParameters.run(cache, settings, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(1); ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation done(); }); }); -<<<<<<< HEAD it('should PASS if template does not contain any of secret words', function (done) { const cache = createCache([describeStacks[1]]); plaintextParameters.run(cache, {}, (err, results) => { @@ -232,27 +144,9 @@ describe('plainTextParameters', function () { }); }); - it('should PASS if template contains any of secret words but with NoEcho enabled', function (done) { - const cache = createCache([describeStacks[2]]); - plaintextParameters.run(cache, {}, (err, results) => { -======= - it('should PASS if Stack parameters does not contain any of secret words ["password" , "privatekey", "secret"]', function (done) { - const cache = createCache([describeStacks[1]]); - plainTextParameters.run(cache, settings, (err, results) => { ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); - done(); - }); - }); - it('should PASS if unable to describe stacks', function (done) { const cache = createCache([]); -<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { -======= - plainTextParameters.run(cache, settings, (err, results) => { ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -261,11 +155,7 @@ describe('plainTextParameters', function () { it('should PASS if there is no parameter in the stack', function (done) { const cache = createCache([describeStacks[2]]); -<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { -======= - plainTextParameters.run(cache, settings, (err, results) => { ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(0); done(); @@ -274,12 +164,7 @@ describe('plainTextParameters', function () { it('should not return any results if unable to fetch any stack description', function (done) { const cache = createNullCache(); -<<<<<<< HEAD - plaintextParameters.run(cache, {}, (err, results) => { -======= - plainTextParameters.run(cache, settings, (err, results) => { ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(0); done(); }); @@ -287,11 +172,7 @@ describe('plainTextParameters', function () { it('should UNKNOWN if error occurs while fetching stack description', function (done) { const cache = createErrorCache(); -<<<<<<< HEAD plaintextParameters.run(cache, {}, (err, results) => { -======= - plainTextParameters.run(cache, settings, (err, results) => { ->>>>>>> 306d721... SPLOIT-113: Added Plain Text Parameters plugin for CloudFormation expect(results.length).to.equal(1); expect(results[0].status).to.equal(3); done(); From b022a527f8eb642304b4e38cdd5c082f060e448b Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Fri, 14 Aug 2020 18:09:45 +0500 Subject: [PATCH 56/76] SPLOIT-113: Updated custom settings --- plugins/aws/cloudformation/plainTextParameters.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 8e538c23d4..7f1cd285ae 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -10,10 +10,11 @@ module.exports = { recommended_action: 'Update the sensitive parameters to use the NoEcho property.', apis: ['CloudFormation:describeStacks'], settings: { - plainTextParameters: { - secretWords: [ - 'secret', 'password', 'privatekey' - ] + plain_text_parameters: { + name: "CloudFormation Plaintext Parameters", + description: "A comma-delimited list of parameter strings that indicate a sensitive value", + regex: "[a-zA-Z0-9,]", + default: "secret,password,privatekey" } }, @@ -21,8 +22,7 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); - secretWords = this.settings.plainTextParameters.secretWords; - + secretWords = this.settings.plain_text_parameters.default; async.each(regions.cloudformation, function(region, rcb){ var describeStacks = helpers.addSource(cache, source, From d3ee38043531013576170b657eb1fe429231cec8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Fri, 14 Aug 2020 21:24:30 +0500 Subject: [PATCH 57/76] Made PR requested changes --- plugins/aws/cloudformation/plainTextParameters.js | 8 ++++---- plugins/aws/ec2/launchWizardSecurityGroups.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 7f1cd285ae..9b91b0d2e6 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -22,7 +22,7 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); - secretWords = this.settings.plain_text_parameters.default; + var secretWords = this.settings.plain_text_parameters.default; async.each(regions.cloudformation, function(region, rcb){ var describeStacks = helpers.addSource(cache, source, @@ -48,14 +48,14 @@ module.exports = { var resource = stack.StackId; parameterFound = false; - if(!stack.Parameters.length) { + if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, - 'The template does not contain any potentially-sensitive parameters', region, resource); + 'Template does not contain any potentially-sensitive parameters', region, resource); return rcb(); } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && secretWords.includes(parameter.ParameterKey.toLowerCase())) { + if((!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()))) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); diff --git a/plugins/aws/ec2/launchWizardSecurityGroups.js b/plugins/aws/ec2/launchWizardSecurityGroups.js index 252cabd11c..0e028778a7 100644 --- a/plugins/aws/ec2/launchWizardSecurityGroups.js +++ b/plugins/aws/ec2/launchWizardSecurityGroups.js @@ -36,7 +36,7 @@ module.exports = { var sg = describeSecurityGroups.data[s]; var resource = sg.GroupId; - if (sg.GroupName.toLowerCase().startsWith('launch-wizard')) { + if (sg.GroupName && sg.GroupName.toLowerCase().startsWith('launch-wizard')) { helpers.addResult(results, 2, 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', region, resource); From 560d273d4265e8eddd90de4da7768b174326281c Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sat, 15 Aug 2020 01:07:50 +0500 Subject: [PATCH 58/76] SPLOIT-113: Added regex to check if NoEcho is enabled --- plugins/aws/cloudformation/plainTextParameters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 9b91b0d2e6..e2890bc58e 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -55,7 +55,7 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if((!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()))) { + if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match("^[\*]+$")) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); From 9195d32e992bf53a2b81447e2290fa71e9f8ae58 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 04:13:40 +0500 Subject: [PATCH 59/76] Accommodated PR changes --- exports.js | 2 +- plugins/aws/cloudformation/plainTextParameters.js | 6 +++--- plugins/aws/ec2/launchWizardSecurityGroups.js | 11 +++++++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/exports.js b/exports.js index ee2b81f9ee..a61fddd2cc 100644 --- a/exports.js +++ b/exports.js @@ -14,7 +14,7 @@ module.exports = { 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - 'plaintextParameters' : require(__dirname + '/plugins/aws/cloudformation/plaintextParameters.js'), + 'plaintextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index e2890bc58e..f5ebb6898b 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -46,12 +46,12 @@ module.exports = { // arn:aws:cloudformation:region:account-id:stack/stack-name/stack-id var stack = describeStacks.data[s]; var resource = stack.StackId; - parameterFound = false; + let parameterFound = false; if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, - 'Template does not contain any potentially-sensitive parameters', region, resource); - return rcb(); + 'Template does not contain any parameters', region, resource); + continue; } stack.Parameters.forEach(function(parameter){ diff --git a/plugins/aws/ec2/launchWizardSecurityGroups.js b/plugins/aws/ec2/launchWizardSecurityGroups.js index 0e028778a7..48f040b7ed 100644 --- a/plugins/aws/ec2/launchWizardSecurityGroups.js +++ b/plugins/aws/ec2/launchWizardSecurityGroups.js @@ -28,7 +28,7 @@ module.exports = { } if (!describeSecurityGroups.data.length) { - helpers.addResult(results, 0, 'No security groups present', region); + helpers.addResult(results, 0, 'No security groups found', region); return rcb(); } @@ -36,7 +36,14 @@ module.exports = { var sg = describeSecurityGroups.data[s]; var resource = sg.GroupId; - if (sg.GroupName && sg.GroupName.toLowerCase().startsWith('launch-wizard')) { + if(!sg.GroupName) { + helpers.addResult(results, 2, + 'Unable to get group name of security group', + region, resource); + continue; + } + + if (sg.GroupName.toLowerCase().startsWith('launch-wizard')) { helpers.addResult(results, 2, 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', region, resource); From 0287cc54eb44d1b44e77f7750837cbe8878773b5 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 06:09:46 +0500 Subject: [PATCH 60/76] Fixed eslint issues --- plugins/aws/cloudformation/plainTextParameters.js | 15 +++++++-------- plugins/aws/ec2/launchWizardSecurityGroups.js | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index f5ebb6898b..52be0d6ea8 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -11,10 +11,10 @@ module.exports = { apis: ['CloudFormation:describeStacks'], settings: { plain_text_parameters: { - name: "CloudFormation Plaintext Parameters", - description: "A comma-delimited list of parameter strings that indicate a sensitive value", - regex: "[a-zA-Z0-9,]", - default: "secret,password,privatekey" + name: 'CloudFormation Plaintext Parameters', + description: 'A comma-delimited list of parameter strings that indicate a sensitive value', + regex: '[a-zA-Z0-9,]', + default: 'secret,password,privatekey' } }, @@ -33,7 +33,7 @@ module.exports = { if (describeStacks.err || !describeStacks.data) { helpers.addResult(results, 3, 'Unable to describe stacks: ' + helpers.addError(describeStacks), region); - return rcb(); + return rcb(); } if (!describeStacks.data.length) { @@ -41,7 +41,6 @@ module.exports = { return rcb(); } - var parameterFound; for (var s in describeStacks.data){ // arn:aws:cloudformation:region:account-id:stack/stack-name/stack-id var stack = describeStacks.data[s]; @@ -55,7 +54,7 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match("^[\*]+$")) { + if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { parameterFound = true; helpers.addResult(results, 1, 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); @@ -64,7 +63,7 @@ module.exports = { if(!parameterFound) { helpers.addResult(results, 0, - 'Template does not contain any potentially-sensitive parameters', region, resource); + 'Template does not contain any potentially-sensitive parameters', region, resource); } } diff --git a/plugins/aws/ec2/launchWizardSecurityGroups.js b/plugins/aws/ec2/launchWizardSecurityGroups.js index 48f040b7ed..caa173be82 100644 --- a/plugins/aws/ec2/launchWizardSecurityGroups.js +++ b/plugins/aws/ec2/launchWizardSecurityGroups.js @@ -45,8 +45,8 @@ module.exports = { if (sg.GroupName.toLowerCase().startsWith('launch-wizard')) { helpers.addResult(results, 2, - 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', - region, resource); + 'Security Group ' + sg.GroupName + ' was launched using EC2 launch wizard', + region, resource); } else { helpers.addResult(results, 0, 'Security Group ' + sg.GroupName + ' was not launched using EC2 launch wizard', From 1315ccdc619767cbdd12284ecc534a185fa3994a Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:38:01 +0500 Subject: [PATCH 61/76] Update exports.js --- exports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exports.js b/exports.js index a61fddd2cc..5a338cfa5e 100644 --- a/exports.js +++ b/exports.js @@ -14,7 +14,7 @@ module.exports = { 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - 'plaintextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), + 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), From 229461ce784cc135fe4d9ebacea68cacd1523551 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:42:00 +0500 Subject: [PATCH 62/76] Update index.js --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 53b6b4fb75..94b3d7af71 100755 --- a/index.js +++ b/index.js @@ -14,7 +14,7 @@ var GoogleConfig; // accessKeyId: '', // secretAccessKey: '', // sessionToken: '', -// region: 'us-east-1' +// region: '' // }; // AzureConfig = { From f5a3b8b09786882bc807deb980e9b4e7ca9b5451 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 14:48:02 +0500 Subject: [PATCH 63/76] Update index.js --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 94b3d7af71..53b6b4fb75 100755 --- a/index.js +++ b/index.js @@ -14,7 +14,7 @@ var GoogleConfig; // accessKeyId: '', // secretAccessKey: '', // sessionToken: '', -// region: '' +// region: 'us-east-1' // }; // AzureConfig = { From c574f76cb8f427d08ad5f4fcf258d16a16bf0ddb Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Tue, 18 Aug 2020 20:15:26 +0500 Subject: [PATCH 64/76] Accomodated PR changes --- .../aws/cloudformation/plainTextParameters.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 52be0d6ea8..d05776bf37 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -27,7 +27,6 @@ module.exports = { var describeStacks = helpers.addSource(cache, source, ['cloudformation', 'describeStacks', region]); - if (!describeStacks) return rcb(); if (describeStacks.err || !describeStacks.data) { @@ -45,7 +44,7 @@ module.exports = { // arn:aws:cloudformation:region:account-id:stack/stack-name/stack-id var stack = describeStacks.data[s]; var resource = stack.StackId; - let parameterFound = false; + let foundStrings = []; if(!stack.Parameters || !stack.Parameters.length) { helpers.addResult(results, 0, @@ -54,18 +53,19 @@ module.exports = { } stack.Parameters.forEach(function(parameter){ - if(!parameterFound && parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { - parameterFound = true; - helpers.addResult(results, 1, - 'Template contains one of the following potentially-sensitive parameters: secret, key, password', region, resource); + if(parameter.ParameterKey && secretWords.includes(parameter.ParameterKey.toLowerCase()) && !parameter.ParameterValue.match('^[*]+$')) { + foundStrings.push(parameter.ParameterKey); } }); - - if(!parameterFound) { + + if(foundStrings && foundStrings.length) { + helpers.addResult(results, 1, + 'Template contains the following potentially-sensitive parameters: ' + foundStrings, region, resource); + } + else { helpers.addResult(results, 0, 'Template does not contain any potentially-sensitive parameters', region, resource); } - } rcb(); From 1a4b495fa18e3447c906128d6c1fb3575e5a775e Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Tue, 18 Aug 2020 21:12:35 +0500 Subject: [PATCH 65/76] Updated status in result of failure --- plugins/aws/cloudformation/plainTextParameters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index d05776bf37..3bd118572e 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -59,7 +59,7 @@ module.exports = { }); if(foundStrings && foundStrings.length) { - helpers.addResult(results, 1, + helpers.addResult(results, 2, 'Template contains the following potentially-sensitive parameters: ' + foundStrings, region, resource); } else { From 156d027c478cec36931628878e885b85dc0891a0 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Sat, 29 Aug 2020 02:44:42 +0500 Subject: [PATCH 66/76] Removed unnecesary rebase changes --- exports.js | 3 + index.js | 160 +++++++++--------- .../aws/cloudformation/plainTextParameters.js | 2 +- plugins/aws/ec2/launchWizardSecurityGroups.js | 2 +- plugins/aws/ec2/vpcEndpointAcceptance.spec.js | 9 - 5 files changed, 84 insertions(+), 92 deletions(-) diff --git a/exports.js b/exports.js index 5a338cfa5e..7139c7640e 100644 --- a/exports.js +++ b/exports.js @@ -5,6 +5,7 @@ module.exports = { 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), + 'emptyASG' : require(__dirname + '/plugins/aws/autoscaling/emptyASG.js'), 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), @@ -116,6 +117,7 @@ module.exports = { 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), + 'iamRoleLastUsed' : require(__dirname + '/plugins/aws/iam/iamRoleLastUsed.js'), 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), @@ -126,6 +128,7 @@ module.exports = { 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), + 'rootSigningCertificate' : require(__dirname + '/plugins/aws/iam/rootSigningCertificate.js'), 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), diff --git a/index.js b/index.js index 53b6b4fb75..26e612ef56 100755 --- a/index.js +++ b/index.js @@ -1,74 +1,74 @@ #!/usr/bin/env node -var engine = require('./engine'); - -var AWSConfig; -var AzureConfig; -var GitHubConfig; -var OracleConfig; -var GoogleConfig; - -// OPTION 1: Configure service provider credentials through hard-coded config objects - -// AWSConfig = { -// accessKeyId: '', -// secretAccessKey: '', -// sessionToken: '', -// region: 'us-east-1' -// }; - -// AzureConfig = { -// ApplicationID: '', // A.K.A ClientID -// KeyValue: '', // Secret -// DirectoryID: '', // A.K.A TenantID or Domain -// SubscriptionID: '', -// location: 'East US' -// }; - -// GitHubConfig = { -// token: '', // GitHub app token -// url: 'https://api.github.com', // BaseURL if not using public GitHub -// organization: false, // Set to true if the login is an organization -// login: '' // The login id for the user or organization -// }; - -// Oracle Important Note: -// Please read Oracle API's key generation instructions: config/_oracle/keys/Readme.md -// You will want an API signing key to fill the keyFingerprint and privateKey params -// OracleConfig = { -// RESTversion: '/20160918', -// tenancyId: 'ocid1.tenancy.oc1..', -// compartmentId: 'ocid1.compartment.oc1..', -// userId: 'ocid1.user.oc1..', -// keyFingerprint: 'YOURKEYFINGERPRINT', -// keyValue: "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-GOES-HERE\n-----END PRIVATE KEY-----\n", -// region: 'us-ashburn-1', -// }; - -// GoogleConfig = { -// "type": "service_account", -// "project": "your-project-name", -// "client_email": "cloudsploit@your-project-name.iam.gserviceaccount.com", -// "private_key": "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY-GOES-HERE\n-----END PRIVATE KEY-----\n", -// }; - -// OPTION 2: Import a service provider config file containing credentials - -// AWSConfig = require(__dirname + '/aws_credentials.json'); -// AzureConfig = require(__dirname + '/azure_credentials.json'); -// GitHubConfig = require(__dirname + '/github_credentials.json'); -// OracleConfig = require(__dirname + '/oracle_credentials.json'); -// GoogleConfig = require(__dirname + '/google_credentials.json'); - -// OPTION 3: ENV configuration with service provider env vars -if(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY){ - AWSConfig = { - accessKeyId: process.env.AWS_ACCESS_KEY_ID, - secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, - sessionToken: process.env.AWS_SESSION_TOKEN, - region: process.env.AWS_DEFAULT_REGION || 'us-east-1' - }; -} +const { ArgumentParser } = require('argparse'); +const engine = require('./engine'); + +console.log(` + _____ _ _ _____ _ _ _ + / ____| | | |/ ____| | | (_) | + | | | | ___ _ _ __| | (___ _ __ | | ___ _| |_ + | | | |/ _ \\| | | |/ _\` |\\___ \\| '_ \\| |/ _ \\| | __| + | |____| | (_) | |_| | (_| |____) | |_) | | (_) | | |_ + \\_____|_|\\___/ \\__,_|\\__,_|_____/| .__/|_|\\___/|_|\\__| + | | + |_| + + CloudSploit by Aqua Security, Ltd. + Cloud security auditing for AWS, Azure, GCP, Oracle, and GitHub +`); + +const parser = new ArgumentParser({}); + +parser.add_argument('--config', { + help: 'The path to a CloudSploit config file containing cloud credentials. See config_example.js' +}); + +parser.add_argument('--compliance', { + help: 'Compliance mode. Only return results applicable to the selected program.', + choices: ['hipaa', 'cis', 'cis1', 'cis2', 'pci'], + action: 'append' +}); +parser.add_argument('--plugin', { + help: 'A specific plugin to run. If none provided, all plugins will be run. Obtain from the exports.js file. E.g. acmValidation' +}); +parser.add_argument('--govcloud', { + help: 'AWS only. Enables GovCloud mode.', + action: 'store_true' +}); +parser.add_argument('--china', { + help: 'AWS only. Enables AWS China mode.', + action: 'store_true' +}); +parser.add_argument('--csv', { help: 'Output: CSV file' }); +parser.add_argument('--json', { help: 'Output: JSON file' }); +parser.add_argument('--junit', { help: 'Output: Junit file' }); +parser.add_argument('--console', { + help: 'Console output format. Default: table', + choices: ['none', 'text', 'table'], + default: 'table' +}); +parser.add_argument('--collection', { help: 'Output: full collection JSON as file' }); +parser.add_argument('--ignore-ok', { + help: 'Ignore passing (OK) results', + action: 'store_true' +}); +parser.add_argument('--exit-code', { + help: 'Exits with a non-zero status code if non-passing results are found', + action: 'store_true' +}); +parser.add_argument('--skip-paginate', { + help: 'AWS only. Skips pagination (for debugging).', + action: 'store_false' +}); +parser.add_argument('--suppress', { + help: 'Suppress results matching the provided Regex. Format: pluginId:region:resourceId', + action: 'append' +}); + +let settings = parser.parse_args(); +let cloudConfig = {}; + +settings.cloud = 'aws'; // Now execute the scans using the defined configuration information. if (!settings.config) { @@ -96,19 +96,17 @@ try { console.error('ERROR: Config file could not be loaded. Please ensure you have copied the config_example.js file to config.js'); process.exit(1); } -if(process.env.GOOGLE_APPLICATION_CREDENTIALS){ - GoogleConfig = require(process.env.GOOGLE_APPLICATION_CREDENTIALS); - GoogleConfig.project = GoogleConfig.project_id; -} - -// Custom settings - place plugin-specific settings here -var settings = {}; -// If running in GovCloud, uncomment the following -// settings.govcloud = true; - -// If running in AWS China, uncomment the following -// settings.china = true; +function loadHelperFile(path) { + try { + var contents = require(path); + } catch (e) { + console.error(`ERROR: The credential file could not be loaded ${path}`); + console.error(e); + process.exit(1); + } + return contents; +} function checkRequiredKeys(obj, keys) { keys.forEach(function(key){ diff --git a/plugins/aws/cloudformation/plainTextParameters.js b/plugins/aws/cloudformation/plainTextParameters.js index 3bd118572e..e03a98bd08 100644 --- a/plugins/aws/cloudformation/plainTextParameters.js +++ b/plugins/aws/cloudformation/plainTextParameters.js @@ -36,7 +36,7 @@ module.exports = { } if (!describeStacks.data.length) { - helpers.addResult(results, 0, 'No stack description found', region); + helpers.addResult(results, 0, 'No CloudFormation stacks found', region); return rcb(); } diff --git a/plugins/aws/ec2/launchWizardSecurityGroups.js b/plugins/aws/ec2/launchWizardSecurityGroups.js index caa173be82..5c73babd28 100644 --- a/plugins/aws/ec2/launchWizardSecurityGroups.js +++ b/plugins/aws/ec2/launchWizardSecurityGroups.js @@ -34,7 +34,7 @@ module.exports = { for (var s in describeSecurityGroups.data) { var sg = describeSecurityGroups.data[s]; - var resource = sg.GroupId; + var resource = 'arn:aws:ec2:' + region + ':' + sg.OwnerId + ':security-group/' + sg.GroupId; if(!sg.GroupName) { helpers.addResult(results, 2, diff --git a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js index 0946f5a682..62053b7238 100644 --- a/plugins/aws/ec2/vpcEndpointAcceptance.spec.js +++ b/plugins/aws/ec2/vpcEndpointAcceptance.spec.js @@ -112,15 +112,6 @@ describe('vpcEndpointAcceptance', function () { }); }); - it('should PASS if no VPC endpoint services are detected', function (done) { - const cache = createCache([]); - vpcEndpointAcceptance.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); - done(); - }); - }); - it('should UNKNOWN if there was an error querying for VPC endpoint services', function (done) { const cache = createErrorCache(); vpcEndpointAcceptance.run(cache, {}, (err, results) => { From 5375e9f516ca669e603713b084beaeee37c4f4ad Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 17 Aug 2020 01:00:39 +0500 Subject: [PATCH 67/76] SPLOIT-947: Added 'Custom Open Ports' plugin --- exports.js | 1 + plugins/aws/ec2/openCustomPorts.js | 95 +++++++++++++ plugins/aws/ec2/openCustomPorts.spec.js | 169 ++++++++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 plugins/aws/ec2/openCustomPorts.js create mode 100644 plugins/aws/ec2/openCustomPorts.spec.js diff --git a/exports.js b/exports.js index 7139c7640e..7dd309b730 100644 --- a/exports.js +++ b/exports.js @@ -80,6 +80,7 @@ module.exports = { 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), + 'openCustomPorts' : require(__dirname + '/plugins/aws/ec2/openCustomPorts.js'), 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js new file mode 100644 index 0000000000..9063f6453f --- /dev/null +++ b/plugins/aws/ec2/openCustomPorts.js @@ -0,0 +1,95 @@ +var async = require('async'); +var helpers = require('../../../helpers/aws'); + +module.exports = { + title: 'Open Custom Ports', + category: 'EC2', + description: 'Ensures that the defined ports are not exposed publicly.', + more_info: 'Security groups should be used to restrict access to ports from known networks.', + link: 'https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html', + recommended_action: 'Modify the security group to ensure the ports are not exposed publicly.', + apis: ['EC2:describeSecurityGroups'], + settings: { + open_port_allowed_list: { + name: 'EC2 Allowed Open Ports', + description: 'A comma-delimited list of ports that indicates open ports allowed for any connection', + regex: '[a-zA-Z0-9,]', + default: [22, 443] + } + }, + + run: function(cache, settings, callback) { + var results = []; + var source = {}; + var regions = helpers.regions(settings); + + var allowed_open_ports = this.settings.open_port_allowed_list.default; + + async.each(regions.ec2, function(region, rcb){ + var describeSecurityGroups = helpers.addSource(cache, source, + ['ec2', 'describeSecurityGroups', region]); + + if (!describeSecurityGroups) return rcb(); + + if (describeSecurityGroups.err || !describeSecurityGroups.data) { + helpers.addResult(results, 3, + 'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region); + return rcb(); + } + + if (!describeSecurityGroups.data.length) { + helpers.addResult(results, 0, 'No security groups present', region); + return rcb(); + } + + var found = false; + var groups = describeSecurityGroups.data; + + for (var g in groups) { + var strings = []; + var resource = 'arn:aws:ec2:' + region + ':' + + groups[g].OwnerId + ':security-group/' + + groups[g].GroupId; + + for (var p in groups[g].IpPermissions) { + var permission = groups[g].IpPermissions[p]; + + for (var k in permission.IpRanges) { + var range = permission.IpRanges[k]; + + if (range.CidrIp === '0.0.0.0/0') { + var portRange = permission.ToPort - permission.FromPort; + + for (let p=0; p <= portRange; p++) { + var port = permission.FromPort + p; + + if (!allowed_open_ports.includes(port)) { + var string = permission.IpProtocol.toUpperCase() + + ' port ' + port + ' open to 0.0.0.0/0'; + if (strings.indexOf(string) === -1) strings.push(string); + found = true; + } + } + } + } + } + + if (strings.length) { + helpers.addResult(results, 2, + 'Security group: ' + groups[g].GroupId + + ' (' + groups[g].GroupName + + ') has ' + ': ' + strings.join(' and '), region, + resource); + } + } + + if (!found) { + helpers.addResult(results, 0, 'No public open ports found', region); + } + + rcb(); + }, function(){ + callback(null, results, source); + }); + } +}; diff --git a/plugins/aws/ec2/openCustomPorts.spec.js b/plugins/aws/ec2/openCustomPorts.spec.js new file mode 100644 index 0000000000..83b682bb0c --- /dev/null +++ b/plugins/aws/ec2/openCustomPorts.spec.js @@ -0,0 +1,169 @@ +var expect = require('chai').expect; +const openCustomPorts = require('./openCustomPorts'); + +const securityGroups = [ + { + "Description": "Allows SSh access to developer", + "GroupName": "spec-test-sg", + "IpPermissions": [{ + "FromPort": 25, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [ + { + "CidrIpv6": "::/0" + } + ], + "PrefixListIds": [], + "ToPort": 25, + "UserIdGroupPairs": [] + }], + "OwnerId": "560213429563", + "GroupId": "sg-0b5f2771716acfee4", + "IpPermissionsEgress": [ + { + "FromPort": 25, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [ + { + "CidrIpv6": "::/0" + } + ], + "PrefixListIds": [], + "ToPort": 25, + "UserIdGroupPairs": [] + } + ], + "VpcId": "vpc-99de2fe4" + }, + { + "Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00", + "GroupName": "launch-wizard-1", + "IpPermissions": [ + { + "FromPort": 22, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "ToPort": 22, + "UserIdGroupPairs": [] + } + ], + "OwnerId": "560213429563", + "GroupId": "sg-0ff1642cae23c309a", + "IpPermissionsEgress": [ + { + "IpProtocol": "-1", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "UserIdGroupPairs": [] + } + ], + "VpcId": "vpc-99de2fe4" + } +] + +const createCache = (groups) => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': { + data: groups + }, + }, + }, + }; +}; + +const createErrorCache = () => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': { + err: { + message: 'error describing cloudformation stacks' + }, + }, + }, + }, + }; +}; + +const createNullCache = () => { + return { + ec2: { + describeSecurityGroups: { + 'us-east-1': null, + }, + }, + }; +}; + +describe('openCustomPorts', function () { + describe('run', function () { + + it('should not return any results if unable to fetch any security groups description', function (done) { + const cache = createNullCache(); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(0); + done(); + }); + }); + + it('should UNKNOWN if error occurs while fetching any security groups description', function (done) { + const cache = createErrorCache(); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(3); + done(); + }); + }); + + it('should PASS if no security groups are present', function (done) { + const cache = createCache([]); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + it('should FAIL if any public open port is found', function (done) { + const cache = createCache([securityGroups[0]]); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); + done(); + }); + }); + + it('should PASS if no public open port is found', function (done) { + const cache = createCache([securityGroups[1]]); + openCustomPorts.run(cache, {}, (err, results) => { + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(0); + done(); + }); + }); + + }); +}); \ No newline at end of file From e1de20ef6863154e6e645f1f925d6f0a52679b2a Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 20 Aug 2020 16:23:49 +0500 Subject: [PATCH 68/76] Refactor plugin file --- plugins/aws/ec2/openCustomPorts.js | 43 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index 9063f6453f..eedb3d52ec 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -4,7 +4,7 @@ var helpers = require('../../../helpers/aws'); module.exports = { title: 'Open Custom Ports', category: 'EC2', - description: 'Ensures that the defined ports are not exposed publicly.', + description: 'Ensures that the defined ports are not exposed publicly', more_info: 'Security groups should be used to restrict access to ports from known networks.', link: 'https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html', recommended_action: 'Modify the security group to ensure the ports are not exposed publicly.', @@ -28,6 +28,7 @@ module.exports = { async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, ['ec2', 'describeSecurityGroups', region]); + console.log(describeSecurityGroups); if (!describeSecurityGroups) return rcb(); @@ -42,22 +43,22 @@ module.exports = { return rcb(); } - var found = false; - var groups = describeSecurityGroups.data; + var portFound = false; - for (var g in groups) { - var strings = []; - var resource = 'arn:aws:ec2:' + region + ':' + - groups[g].OwnerId + ':security-group/' + - groups[g].GroupId; + for (var g in describeSecurityGroups.data) { + var group = describeSecurityGroups.data[g]; + var resource = group.GroupId; + var openPorts = []; - for (var p in groups[g].IpPermissions) { - var permission = groups[g].IpPermissions[p]; + if (!group.IpPermissions) continue; + + for (var p in group.IpPermissions) { + var permission = group.IpPermissions[p]; - for (var k in permission.IpRanges) { - var range = permission.IpRanges[k]; + for (var r in permission.IpRanges) { + var range = permission.IpRanges[r]; - if (range.CidrIp === '0.0.0.0/0') { + if (range.CidrIp && range.CidrIp === '0.0.0.0/0') { var portRange = permission.ToPort - permission.FromPort; for (let p=0; p <= portRange; p++) { @@ -66,25 +67,23 @@ module.exports = { if (!allowed_open_ports.includes(port)) { var string = permission.IpProtocol.toUpperCase() + ' port ' + port + ' open to 0.0.0.0/0'; - if (strings.indexOf(string) === -1) strings.push(string); - found = true; + if (openPorts.indexOf(string) === -1) openPorts.push(string); + portFound = true; } } } } } - if (strings.length) { + if (openPorts.length) { helpers.addResult(results, 2, - 'Security group: ' + groups[g].GroupId + - ' (' + groups[g].GroupName + - ') has ' + ': ' + strings.join(' and '), region, - resource); + 'Security group: ' + group.GroupName + ' has: ' + openPorts.join(' and '), + region, resource); } } - if (!found) { - helpers.addResult(results, 0, 'No public open ports found', region); + if (!portFound) { + helpers.addResult(results, 0, 'No public open ports found', region, resource); } rcb(); From 339275e8399ce3c6fca1fdd8c83858a142c066cd Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 17 Aug 2020 01:00:39 +0500 Subject: [PATCH 69/76] SPLOIT-947: Added 'Custom Open Ports' plugin --- plugins/aws/ec2/openCustomPorts.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index eedb3d52ec..0f8addb8d1 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -28,7 +28,6 @@ module.exports = { async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, ['ec2', 'describeSecurityGroups', region]); - console.log(describeSecurityGroups); if (!describeSecurityGroups) return rcb(); From 90f8c7bbdf7bf59ca7259ebbbb5829f41e8164ca Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Thu, 20 Aug 2020 16:23:49 +0500 Subject: [PATCH 70/76] Refactor plugin file --- plugins/aws/ec2/openCustomPorts.js | 28 +++++----- plugins/aws/ec2/openCustomPorts.spec.js | 70 ++++++++++++------------- 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index 0f8addb8d1..c0c99d02ee 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -14,7 +14,7 @@ module.exports = { name: 'EC2 Allowed Open Ports', description: 'A comma-delimited list of ports that indicates open ports allowed for any connection', regex: '[a-zA-Z0-9,]', - default: [22, 443] + default: [80, 443] } }, @@ -28,9 +28,7 @@ module.exports = { async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, ['ec2', 'describeSecurityGroups', region]); - if (!describeSecurityGroups) return rcb(); - if (describeSecurityGroups.err || !describeSecurityGroups.data) { helpers.addResult(results, 3, 'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region); @@ -38,12 +36,11 @@ module.exports = { } if (!describeSecurityGroups.data.length) { - helpers.addResult(results, 0, 'No security groups present', region); + helpers.addResult(results, 0, 'No security groups found', region); return rcb(); } - var portFound = false; - + // Loop through each security group for (var g in describeSecurityGroups.data) { var group = describeSecurityGroups.data[g]; var resource = group.GroupId; @@ -51,23 +48,24 @@ module.exports = { if (!group.IpPermissions) continue; + // Loop through each ip permissions in a security group for (var p in group.IpPermissions) { var permission = group.IpPermissions[p]; + // Loop through each ip range for an ip permissions list for (var r in permission.IpRanges) { var range = permission.IpRanges[r]; if (range.CidrIp && range.CidrIp === '0.0.0.0/0') { var portRange = permission.ToPort - permission.FromPort; + // Check for all the ports in port range for (let p=0; p <= portRange; p++) { var port = permission.FromPort + p; if (!allowed_open_ports.includes(port)) { - var string = permission.IpProtocol.toUpperCase() + - ' port ' + port + ' open to 0.0.0.0/0'; - if (openPorts.indexOf(string) === -1) openPorts.push(string); - portFound = true; + var openPort = permission.IpProtocol.toUpperCase() + ' port ' + port; + if (openPorts.indexOf(openPort) === -1) openPorts.push(openPort); } } } @@ -76,15 +74,15 @@ module.exports = { if (openPorts.length) { helpers.addResult(results, 2, - 'Security group: ' + group.GroupName + ' has: ' + openPorts.join(' and '), + 'Security group ' + group.GroupName + ' has: ' + openPorts.join(' , ') + ' open to 0.0.0.0/0', + region, resource); + } else { + helpers.addResult(results, 0, + 'Security group: ' + group.GroupName + ' has no open ports', region, resource); } } - if (!portFound) { - helpers.addResult(results, 0, 'No public open ports found', region, resource); - } - rcb(); }, function(){ callback(null, results, source); diff --git a/plugins/aws/ec2/openCustomPorts.spec.js b/plugins/aws/ec2/openCustomPorts.spec.js index 83b682bb0c..57f63f2c46 100644 --- a/plugins/aws/ec2/openCustomPorts.spec.js +++ b/plugins/aws/ec2/openCustomPorts.spec.js @@ -19,7 +19,7 @@ const securityGroups = [ } ], "PrefixListIds": [], - "ToPort": 25, + "ToPort": 30, "UserIdGroupPairs": [] }], "OwnerId": "560213429563", @@ -45,40 +45,40 @@ const securityGroups = [ ], "VpcId": "vpc-99de2fe4" }, - { - "Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00", - "GroupName": "launch-wizard-1", - "IpPermissions": [ - { - "FromPort": 22, - "IpProtocol": "tcp", - "IpRanges": [ - { - "CidrIp": "0.0.0.0/0" - } - ], - "Ipv6Ranges": [], - "PrefixListIds": [], - "ToPort": 22, - "UserIdGroupPairs": [] - } - ], - "OwnerId": "560213429563", - "GroupId": "sg-0ff1642cae23c309a", - "IpPermissionsEgress": [ - { - "IpProtocol": "-1", - "IpRanges": [ - { - "CidrIp": "0.0.0.0/0" - } - ], - "Ipv6Ranges": [], - "PrefixListIds": [], - "UserIdGroupPairs": [] - } - ], - "VpcId": "vpc-99de2fe4" + { + "Description": "launch-wizard-1 created 2020-08-10T14:28:09.271+05:00", + "GroupName": "launch-wizard-1", + "IpPermissions": [ + { + "FromPort": 80, + "IpProtocol": "tcp", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "ToPort": 80, + "UserIdGroupPairs": [] + } + ], + "OwnerId": "560213429563", + "GroupId": "sg-0ff1642cae23c309a", + "IpPermissionsEgress": [ + { + "IpProtocol": "-1", + "IpRanges": [ + { + "CidrIp": "0.0.0.0/0" + } + ], + "Ipv6Ranges": [], + "PrefixListIds": [], + "UserIdGroupPairs": [] + } + ], + "VpcId": "vpc-99de2fe4" } ] From c21fadba51233e78a242a30862d34991cdfb91a8 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 14 Sep 2020 01:45:03 +0500 Subject: [PATCH 71/76] Accommodated PR changes --- plugins/aws/ec2/openCustomPorts.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/aws/ec2/openCustomPorts.spec.js b/plugins/aws/ec2/openCustomPorts.spec.js index 57f63f2c46..5a506945e7 100644 --- a/plugins/aws/ec2/openCustomPorts.spec.js +++ b/plugins/aws/ec2/openCustomPorts.spec.js @@ -22,7 +22,7 @@ const securityGroups = [ "ToPort": 30, "UserIdGroupPairs": [] }], - "OwnerId": "560213429563", + "OwnerId": "111122223333", "GroupId": "sg-0b5f2771716acfee4", "IpPermissionsEgress": [ { @@ -63,7 +63,7 @@ const securityGroups = [ "UserIdGroupPairs": [] } ], - "OwnerId": "560213429563", + "OwnerId": "111122223333", "GroupId": "sg-0ff1642cae23c309a", "IpPermissionsEgress": [ { From 6744c0952415a21669db66b11c2a612a8082c61a Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Mon, 21 Sep 2020 00:14:53 +0500 Subject: [PATCH 72/76] Accommodated PR changes requested --- plugins/aws/ec2/openCustomPorts.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index c8f0bbb3fe..e93268aa71 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -14,7 +14,7 @@ module.exports = { name: 'EC2 Allowed Open Ports', description: 'A comma-delimited list of ports that indicates open ports allowed for any connection', regex: '[a-zA-Z0-9,]', - default: [80, 443] + default: '80,443' } }, @@ -24,6 +24,7 @@ module.exports = { var regions = helpers.regions(settings); var allowed_open_ports = settings.open_port_allowed_list || this.settings.open_port_allowed_list.default; + // allowed_open_ports = allowed_open_ports.split(','); async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, @@ -65,7 +66,7 @@ module.exports = { if (!allowed_open_ports.includes(port)) { var openPort = permission.IpProtocol.toUpperCase() + ' port ' + port; - if (openPorts.indexOf(openPort) === -1) openPorts.push(openPort); + if (openPorts.indexOf(openPort) === -1) openPorts.push(openPort.toString()); } } } From c24eae0feb7f61526bb95ace79373df23f3d7ae1 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 23 Sep 2020 17:03:27 +0500 Subject: [PATCH 73/76] Accommodated PR changes --- exports.js | 414 ++++++++++++++--------------- plugins/aws/ec2/openCustomPorts.js | 31 ++- 2 files changed, 222 insertions(+), 223 deletions(-) diff --git a/exports.js b/exports.js index 102fb0fa73..c416751569 100644 --- a/exports.js +++ b/exports.js @@ -2,219 +2,219 @@ module.exports = { aws : { - 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), - 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), - 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), - 'asgActiveNotifications' : require(__dirname + '/plugins/aws/autoscaling/asgActiveNotifications.js'), - 'emptyASG' : require(__dirname + '/plugins/aws/autoscaling/emptyASG.js'), - 'asgMissingELB' : require(__dirname + '/plugins/aws/autoscaling/asgMissingELB.js'), - 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), - 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), - 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), - 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), - 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), - 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), - 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), - 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), + // 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), + // 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), + // 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), + // 'asgActiveNotifications' : require(__dirname + '/plugins/aws/autoscaling/asgActiveNotifications.js'), + // 'emptyASG' : require(__dirname + '/plugins/aws/autoscaling/emptyASG.js'), + // 'asgMissingELB' : require(__dirname + '/plugins/aws/autoscaling/asgMissingELB.js'), + // 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), + // 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), + // 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), + // 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), + // 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), + // 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), + // 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), + // 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - 'volumeEncryption' : require(__dirname + '/plugins/aws/comprehend/volumeEncryption.js'), - 'outputResultEncryption' : require(__dirname + '/plugins/aws/comprehend/outputResultEncryption.js'), - - 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), - - 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), - 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), - 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), - 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), - 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), - 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), - 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), - - 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), - - 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), - - 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), - 'daxClusterEncryption' : require(__dirname + '/plugins/aws/dynamodb/daxClusterEncryption.js'), - - 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), - 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), - 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), - 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), - 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), - 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), - 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), - 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), - 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), - 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), - 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), - 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), - 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), - 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), - 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), - 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), - 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), - 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), - 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), - 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), - 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), - 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), - 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), - 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), - 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), - 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), - 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), - 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), - 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), - 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), - 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), - 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), - 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), - 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), - 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), - 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), - 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), - 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), - 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), - 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), - 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), - 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), - 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), - 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), - 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), - 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), - 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), - 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), + // 'volumeEncryption' : require(__dirname + '/plugins/aws/comprehend/volumeEncryption.js'), + // 'outputResultEncryption' : require(__dirname + '/plugins/aws/comprehend/outputResultEncryption.js'), + + // 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), + + // 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), + // 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), + // 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), + // 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), + // 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), + // 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), + // 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), + + // 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), + + // 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), + + // 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), + // 'daxClusterEncryption' : require(__dirname + '/plugins/aws/dynamodb/daxClusterEncryption.js'), + + // 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), + // 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), + // 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), + // 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), + // 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), + // 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), + // 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), + // 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), + // 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), + // 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), + // 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), + // 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), + // 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), + // 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), + // 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), + // 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), + // 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), + // 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), + // 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), + // 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), + // 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), + // 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), + // 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), + // 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), + // 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), + // 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), + // 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), + // 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), + // 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), + // 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), + // 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), + // 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), + // 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), + // 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), + // 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), + // 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), + // 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), + // 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), + // 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), + // 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), + // 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), + // 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), + // 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), + // 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), + // 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), + // 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), + // 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), + // 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), 'openCustomPorts' : require(__dirname + '/plugins/aws/ec2/openCustomPorts.js'), - 'ebsUnusedVolumes' : require(__dirname + '/plugins/aws/ec2/ebsUnusedVolumes.js'), - 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), + // 'ebsUnusedVolumes' : require(__dirname + '/plugins/aws/ec2/ebsUnusedVolumes.js'), + // 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), - 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), + // 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), - 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), - 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), + // 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), + // 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), - 'managedPlatformUpdates' : require(__dirname + '/plugins/aws/elasticbeanstalk/managedPlatformUpdates.js'), + // 'managedPlatformUpdates' : require(__dirname + '/plugins/aws/elasticbeanstalk/managedPlatformUpdates.js'), - 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), - 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), - 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), - 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), - - 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), - 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), - 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), - 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), - - 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), - 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), - 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), - 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), - - 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), - 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), - 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), - 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), - 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), - 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), - 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), - - 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), - 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), - 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), - 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), - 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), - 'groupInlinePolicies' : require(__dirname + '/plugins/aws/iam/groupInlinePolicies.js'), - 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), - 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), - 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), - 'iamRoleLastUsed' : require(__dirname + '/plugins/aws/iam/iamRoleLastUsed.js'), - 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), - 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), - 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), - 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), - 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), - 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), - 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), - 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), - 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), - 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), - 'rootSigningCertificate' : require(__dirname + '/plugins/aws/iam/rootSigningCertificate.js'), - 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), - 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), - 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), - 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), - 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), - 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), - 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), - 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), - 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), - 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), - 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), - 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), - 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), - 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), - - 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), - 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), - 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), - 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), - 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), - 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), - 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), - 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), - 'sqlServerTLSVersion' : require(__dirname + '/plugins/aws/rds/sqlServerTLSVersion'), - - 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), - 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), - 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), - - 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), - 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), - 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), - 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), - 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), - 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), - 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), - 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), - 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), - 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), - - 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), - 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), - - 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), - - 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), - 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), - 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), - - 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), - 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), - 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), - - 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), - 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), - 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), - 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), - - 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), - - 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), - 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), - - 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), - - 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), - 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), - 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), - - 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), - 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), - 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), - 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), - - 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js') + // 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), + // 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), + // 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), + // 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), + + // 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), + // 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), + // 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), + // 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), + + // 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), + // 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), + // 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), + // 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), + + // 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), + // 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), + // 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), + // 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), + // 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), + // 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), + // 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), + + // 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), + // 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), + // 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), + // 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), + // 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), + // 'groupInlinePolicies' : require(__dirname + '/plugins/aws/iam/groupInlinePolicies.js'), + // 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), + // 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), + // 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), + // 'iamRoleLastUsed' : require(__dirname + '/plugins/aws/iam/iamRoleLastUsed.js'), + // 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), + // 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), + // 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), + // 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), + // 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), + // 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), + // 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), + // 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), + // 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), + // 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), + // 'rootSigningCertificate' : require(__dirname + '/plugins/aws/iam/rootSigningCertificate.js'), + // 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), + // 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), + // 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), + // 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), + // 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), + // 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), + // 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), + // 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), + // 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), + // 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), + // 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), + // 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), + // 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), + // 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), + + // 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), + // 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), + // 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), + // 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), + // 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), + // 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), + // 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), + // 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), + // 'sqlServerTLSVersion' : require(__dirname + '/plugins/aws/rds/sqlServerTLSVersion'), + + // 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), + // 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), + // 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), + + // 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), + // 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), + // 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), + // 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), + // 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), + // 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), + // 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), + // 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), + // 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), + // 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), + + // 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), + // 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), + + // 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), + + // 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), + // 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), + // 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), + + // 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), + // 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), + // 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), + + // 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), + // 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), + // 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), + // 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), + + // 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), + + // 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), + // 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), + + // 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), + + // 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), + // 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), + // 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), + + // 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), + // 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), + // 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), + // 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), + + // 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js') }, azure : { 'fileServiceEncryption' : require(__dirname + '/plugins/azure/storageaccounts/fileServiceEncryption.js'), diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index 18b57fe0d5..8a18d266df 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -8,13 +8,13 @@ module.exports = { more_info: 'Security groups should be used to restrict access to ports from known networks.', link: 'https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html', recommended_action: 'Modify the security group to ensure the ports are not exposed publicly.', - apis: ['EC2:describeSecurityGroups', 'STS:getCallerIdentity'], + apis: ['EC2:describeSecurityGroups'], settings: { open_port_allowed_list: { name: 'EC2 Allowed Open Ports', description: 'A comma-delimited list of ports that indicates open ports allowed for any connection', - regex: '[a-zA-Z0-9,]', - default: [80, 443] + regex: '[0-9,]', + default: '80,443' } }, @@ -22,17 +22,17 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); - var acctRegion = helpers.defaultRegion(settings); var awsOrGov = helpers.defaultPartition(settings); - var accountId = helpers.addSource(cache, source, ['sts', 'getCallerIdentity', acctRegion, 'data']); - - var allowed_open_ports = this.settings.open_port_allowed_list.default; + var allowed_open_ports = settings.open_port_allowed_list || this.settings.open_port_allowed_list.default; + allowed_open_ports = allowed_open_ports.split(','); async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, ['ec2', 'describeSecurityGroups', region]); + if (!describeSecurityGroups) return rcb(); + if (describeSecurityGroups.err || !describeSecurityGroups.data) { helpers.addResult(results, 3, 'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region); @@ -47,7 +47,8 @@ module.exports = { // Loop through each security group for (var g in describeSecurityGroups.data) { var group = describeSecurityGroups.data[g]; - var arn = 'arn:' + awsOrGov + ':ec2:' + region + ':' + accountId + ':security-group/' + group.GroupId; + var arn = 'arn:' + awsOrGov + ':ec2:' + region + ':' + group.OwnerId + ':security-group/' + group.GroupId; + var openPorts = []; if (!group.IpPermissions) continue; @@ -62,12 +63,10 @@ module.exports = { if (range.CidrIp && range.CidrIp === '0.0.0.0/0') { var portRange = permission.ToPort - permission.FromPort; - // Check for all the ports in port range for (let p=0; p <= portRange; p++) { var port = permission.FromPort + p; - - if (!allowed_open_ports.includes(port)) { + if (!allowed_open_ports.includes(port.toString())) { var openPort = permission.IpProtocol.toUpperCase() + ' port ' + port; if (openPorts.indexOf(openPort) === -1) openPorts.push(openPort); } @@ -76,13 +75,13 @@ module.exports = { } } - if (openPorts.length) { - helpers.addResult(results, 2, - 'Security group ' + group.GroupName + ' has: ' + openPorts.join(' , ') + ' open to 0.0.0.0/0', + if (!openPorts.length) { + helpers.addResult(results, 0, + 'Security group "' + group.GroupName + '" has no open ports', region, arn); } else { - helpers.addResult(results, 0, - 'Security group: ' + group.GroupName + ' has no open ports', + helpers.addResult(results, 2, + 'Security group "' + group.GroupName + '" has: ' + openPorts.join(' , ') + ' open to 0.0.0.0/0', region, arn); } } From a73983f9d9b44984f2b5b9ae791352f71be4ad18 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Wed, 23 Sep 2020 17:04:12 +0500 Subject: [PATCH 74/76] Accommodated PR changes --- exports.js | 414 ++++++++++++++++++++++++++--------------------------- 1 file changed, 207 insertions(+), 207 deletions(-) diff --git a/exports.js b/exports.js index c416751569..102fb0fa73 100644 --- a/exports.js +++ b/exports.js @@ -2,219 +2,219 @@ module.exports = { aws : { - // 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), - // 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), - // 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), - // 'asgActiveNotifications' : require(__dirname + '/plugins/aws/autoscaling/asgActiveNotifications.js'), - // 'emptyASG' : require(__dirname + '/plugins/aws/autoscaling/emptyASG.js'), - // 'asgMissingELB' : require(__dirname + '/plugins/aws/autoscaling/asgMissingELB.js'), - // 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), - // 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), - // 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), - // 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), - // 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), - // 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), - // 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), - // 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), + 'acmValidation' : require(__dirname + '/plugins/aws/acm/acmValidation.js'), + 'acmCertificateExpiry' : require(__dirname + '/plugins/aws/acm/acmCertificateExpiry.js'), + 'asgMultiAz' : require(__dirname + '/plugins/aws/autoscaling/asgMultiAz.js'), + 'asgActiveNotifications' : require(__dirname + '/plugins/aws/autoscaling/asgActiveNotifications.js'), + 'emptyASG' : require(__dirname + '/plugins/aws/autoscaling/emptyASG.js'), + 'asgMissingELB' : require(__dirname + '/plugins/aws/autoscaling/asgMissingELB.js'), + 'workgroupEncrypted' : require(__dirname + '/plugins/aws/athena/workgroupEncrypted.js'), + 'workgroupEnforceConfiguration' : require(__dirname + '/plugins/aws/athena/workgroupEnforceConfiguration.js'), + 'publicS3Origin' : require(__dirname + '/plugins/aws/cloudfront/publicS3Origin.js'), + 'secureOrigin' : require(__dirname + '/plugins/aws/cloudfront/secureOrigin.js'), + 'insecureProtocols' : require(__dirname + '/plugins/aws/cloudfront/insecureProtocols.js'), + 'cloudfrontHttpsOnly' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontHttpsOnly.js'), + 'cloudfrontLoggingEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontLoggingEnabled.js'), + 'cloudfrontWafEnabled' : require(__dirname + '/plugins/aws/cloudfront/cloudfrontWafEnabled.js'), - // 'volumeEncryption' : require(__dirname + '/plugins/aws/comprehend/volumeEncryption.js'), - // 'outputResultEncryption' : require(__dirname + '/plugins/aws/comprehend/outputResultEncryption.js'), - - // 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), - - // 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), - // 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), - // 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), - // 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), - // 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), - // 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), - // 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), - - // 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), - - // 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), - - // 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), - // 'daxClusterEncryption' : require(__dirname + '/plugins/aws/dynamodb/daxClusterEncryption.js'), - - // 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), - // 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), - // 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), - // 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), - // 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), - // 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), - // 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), - // 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), - // 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), - // 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), - // 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), - // 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), - // 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), - // 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), - // 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), - // 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), - // 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), - // 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), - // 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), - // 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), - // 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), - // 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), - // 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), - // 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), - // 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), - // 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), - // 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), - // 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), - // 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), - // 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), - // 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), - // 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), - // 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), - // 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), - // 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), - // 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), - // 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), - // 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), - // 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), - // 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), - // 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), - // 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), - // 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), - // 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), - // 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), - // 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), - // 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), - // 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), + 'volumeEncryption' : require(__dirname + '/plugins/aws/comprehend/volumeEncryption.js'), + 'outputResultEncryption' : require(__dirname + '/plugins/aws/comprehend/outputResultEncryption.js'), + + 'plainTextParameters' : require(__dirname + '/plugins/aws/cloudformation/plainTextParameters.js'), + + 'cloudtrailBucketAccessLogging' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketAccessLogging.js'), + 'cloudtrailBucketDelete' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketDelete.js'), + 'cloudtrailEnabled' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEnabled.js'), + 'cloudtrailEncryption' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailEncryption.js'), + 'cloudtrailFileValidation' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailFileValidation.js'), + 'cloudtrailToCloudwatch' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailToCloudwatch.js'), + 'cloudtrailBucketPrivate' : require(__dirname + '/plugins/aws/cloudtrail/cloudtrailBucketPrivate.js'), + + 'configServiceEnabled' : require(__dirname + '/plugins/aws/configservice/configServiceEnabled.js'), + + 'dmsEncryptionEnabled' : require(__dirname + '/plugins/aws/dms/dmsEncryptionEnabled.js'), + + 'dynamoKmsEncryption' : require(__dirname + '/plugins/aws/dynamodb/dynamoKmsEncryption.js'), + 'daxClusterEncryption' : require(__dirname + '/plugins/aws/dynamodb/daxClusterEncryption.js'), + + 'defaultSecurityGroup' : require(__dirname + '/plugins/aws/ec2/defaultSecurityGroup.js'), + 'launchWizardSecurityGroups' : require(__dirname + '/plugins/aws/ec2/launchWizardSecurityGroups'), + 'elasticIpLimit' : require(__dirname + '/plugins/aws/ec2/elasticIpLimit.js'), + 'subnetIpAvailability' : require(__dirname + '/plugins/aws/ec2/subnetIpAvailability.js'), + 'excessiveSecurityGroups' : require(__dirname + '/plugins/aws/ec2/excessiveSecurityGroups.js'), + 'instanceLimit' : require(__dirname + '/plugins/aws/ec2/instanceLimit.js'), + 'instanceVcpusLimit' : require(__dirname + '/plugins/aws/ec2/instanceVcpusLimit.js'), + 'instanceMaxCount' : require(__dirname + '/plugins/aws/ec2/instanceMaxCount.js'), + 'instanceKeyBasedLogin' : require(__dirname + '/plugins/aws/ec2/instanceKeyBasedLogin.js'), + 'openAllPortsProtocols' : require(__dirname + '/plugins/aws/ec2/openAllPortsProtocols.js'), + 'openCIFS' : require(__dirname + '/plugins/aws/ec2/openCIFS.js'), + 'openDNS' : require(__dirname + '/plugins/aws/ec2/openDNS.js'), + 'openDocker' : require(__dirname + '/plugins/aws/ec2/openDocker.js'), + 'openFTP' : require(__dirname + '/plugins/aws/ec2/openFTP.js'), + 'openHadoopNameNode' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNode.js'), + 'openHadoopNameNodeWebUI' : require(__dirname + '/plugins/aws/ec2/openHadoopNameNodeWebUI.js'), + 'openKibana' : require(__dirname + '/plugins/aws/ec2/openKibana.js'), + 'openMySQL' : require(__dirname + '/plugins/aws/ec2/openMySQL.js'), + 'openOracle' : require(__dirname + '/plugins/aws/ec2/openOracle.js'), + 'openNetBIOS' : require(__dirname + '/plugins/aws/ec2/openNetBIOS.js'), + 'openPostgreSQL' : require(__dirname + '/plugins/aws/ec2/openPostgreSQL.js'), + 'openRDP' : require(__dirname + '/plugins/aws/ec2/openRDP.js'), + 'openRPC' : require(__dirname + '/plugins/aws/ec2/openRPC.js'), + 'openSalt' : require(__dirname + '/plugins/aws/ec2/openSalt.js'), + 'openSMBoTCP' : require(__dirname + '/plugins/aws/ec2/openSMBoTCP.js'), + 'openSMTP' : require(__dirname + '/plugins/aws/ec2/openSMTP.js'), + 'openSQLServer' : require(__dirname + '/plugins/aws/ec2/openSQLServer.js'), + 'openSSH' : require(__dirname + '/plugins/aws/ec2/openSSH.js'), + 'openTelnet' : require(__dirname + '/plugins/aws/ec2/openTelnet.js'), + 'openVNCClient' : require(__dirname + '/plugins/aws/ec2/openVNCClient.js'), + 'openVNCServer' : require(__dirname + '/plugins/aws/ec2/openVNCServer.js'), + 'openElasticsearch' : require(__dirname + '/plugins/aws/ec2/openElasticsearch.js'), + 'vpcElasticIpLimit' : require(__dirname + '/plugins/aws/ec2/vpcElasticIpLimit.js'), + 'classicInstances' : require(__dirname + '/plugins/aws/ec2/classicInstances.js'), + 'flowLogsEnabled' : require(__dirname + '/plugins/aws/ec2/flowLogsEnabled.js'), + 'vpcMultipleSubnets' : require(__dirname + '/plugins/aws/ec2/multipleSubnets.js'), + 'overlappingSecurityGroups' : require(__dirname + '/plugins/aws/ec2/overlappingSecurityGroups.js'), + 'publicAmi' : require(__dirname + '/plugins/aws/ec2/publicAmi.js'), + 'encryptedAmi' : require(__dirname + '/plugins/aws/ec2/encryptedAmi.js'), + 'instanceIamRole' : require(__dirname + '/plugins/aws/ec2/instanceIamRole.js'), + 'ebsEncryptionEnabled' : require(__dirname + '/plugins/aws/ec2/ebsEncryptionEnabled.js'), + 'ebsSnapshotPrivate' : require(__dirname + '/plugins/aws/ec2/ebsSnapshotPrivate.js'), + 'natMultiAz' : require(__dirname + '/plugins/aws/ec2/natMultiAz.js'), + 'defaultVpcInUse' : require(__dirname + '/plugins/aws/ec2/defaultVpcInUse.js'), + 'defaultVpcExists' : require(__dirname + '/plugins/aws/ec2/defaultVpcExists.js'), + 'crossVpcPublicPrivate' : require(__dirname + '/plugins/aws/ec2/crossVpcPublicPrivate.js'), + 'vpcEndpointAcceptance' : require(__dirname + '/plugins/aws/ec2/vpcEndpointAcceptance'), + 'ebsEncryptedSnapshots' : require(__dirname + '/plugins/aws/ec2/ebsEncryptedSnapshots.js'), 'openCustomPorts' : require(__dirname + '/plugins/aws/ec2/openCustomPorts.js'), - // 'ebsUnusedVolumes' : require(__dirname + '/plugins/aws/ec2/ebsUnusedVolumes.js'), - // 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), + 'ebsUnusedVolumes' : require(__dirname + '/plugins/aws/ec2/ebsUnusedVolumes.js'), + 'ec2MetadataOptions' : require(__dirname + '/plugins/aws/ec2/ec2MetadataOptions.js'), - // 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), + 'efsEncryptionEnabled' : require(__dirname + '/plugins/aws/efs/efsEncryptionEnabled.js'), - // 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), - // 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), + 'ecrRepositoryPolicy' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryPolicy.js'), + 'ecrRepositoryTagImmutability' : require(__dirname + '/plugins/aws/ecr/ecrRepositoryTagImmutability.js'), - // 'managedPlatformUpdates' : require(__dirname + '/plugins/aws/elasticbeanstalk/managedPlatformUpdates.js'), + 'managedPlatformUpdates' : require(__dirname + '/plugins/aws/elasticbeanstalk/managedPlatformUpdates.js'), - // 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), - // 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), - // 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), - // 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), - - // 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), - // 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), - // 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), - // 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), - - // 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), - // 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), - // 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), - // 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), - - // 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), - // 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), - // 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), - // 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), - // 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), - // 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), - // 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), - - // 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), - // 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), - // 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), - // 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), - // 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), - // 'groupInlinePolicies' : require(__dirname + '/plugins/aws/iam/groupInlinePolicies.js'), - // 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), - // 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), - // 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), - // 'iamRoleLastUsed' : require(__dirname + '/plugins/aws/iam/iamRoleLastUsed.js'), - // 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), - // 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), - // 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), - // 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), - // 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), - // 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), - // 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), - // 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), - // 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), - // 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), - // 'rootSigningCertificate' : require(__dirname + '/plugins/aws/iam/rootSigningCertificate.js'), - // 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), - // 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), - // 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), - // 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), - // 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), - // 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), - // 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), - // 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), - // 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), - // 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), - // 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), - // 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), - // 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), - // 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), - - // 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), - // 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), - // 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), - // 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), - // 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), - // 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), - // 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), - // 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), - // 'sqlServerTLSVersion' : require(__dirname + '/plugins/aws/rds/sqlServerTLSVersion'), - - // 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), - // 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), - // 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), - - // 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), - // 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), - // 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), - // 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), - // 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), - // 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), - // 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), - // 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), - // 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), - // 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), - - // 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), - // 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), - - // 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), - - // 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), - // 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), - // 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), - - // 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), - // 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), - // 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), - - // 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), - // 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), - // 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), - // 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), - - // 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), - - // 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), - // 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), - - // 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), - - // 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), - // 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), - // 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), - - // 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), - // 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), - // 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), - // 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), - - // 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js') + 'eksKubernetesVersion' : require(__dirname + '/plugins/aws/eks/eksKubernetesVersion.js'), + 'eksLoggingEnabled' : require(__dirname + '/plugins/aws/eks/eksLoggingEnabled.js'), + 'eksPrivateEndpoint' : require(__dirname + '/plugins/aws/eks/eksPrivateEndpoint.js'), + 'eksSecurityGroups' : require(__dirname + '/plugins/aws/eks/eksSecurityGroups.js'), + + 'insecureCiphers' : require(__dirname + '/plugins/aws/elb/insecureCiphers.js'), + 'elbHttpsOnly' : require(__dirname + '/plugins/aws/elb/elbHttpsOnly.js'), + 'elbLoggingEnabled' : require(__dirname + '/plugins/aws/elb/elbLoggingEnabled.js'), + 'elbNoInstances' : require(__dirname + '/plugins/aws/elb/elbNoInstances.js'), + + 'elbv2LoggingEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2LoggingEnabled.js'), + 'elbv2HttpsOnly' : require(__dirname + '/plugins/aws/elbv2/elbv2HttpsOnly.js'), + 'elbv2NoInstances' : require(__dirname + '/plugins/aws/elbv2/elbv2NoInstances.js'), + 'elbv2WafEnabled' : require(__dirname + '/plugins/aws/elbv2/elbv2WafEnabled.js'), + + 'esPublicEndpoint' : require(__dirname + '/plugins/aws/es/esPublicEndpoint.js'), + 'esRequireIAMAuth' : require(__dirname + '/plugins/aws/es/esRequireIAMAuth.js'), + 'esEncryptedDomain' : require(__dirname + '/plugins/aws/es/esEncryptedDomain.js'), + 'esNodeToNodeEncryption' : require(__dirname + '/plugins/aws/es/esNodeToNodeEncryption.js'), + 'esLoggingEnabled' : require(__dirname + '/plugins/aws/es/esLoggingEnabled.js'), + 'esUpgradeAvailable' : require(__dirname + '/plugins/aws/es/esUpgradeAvailable.js'), + 'esHttpsOnly' : require(__dirname + '/plugins/aws/es/esHttpsOnly.js'), + + 'accessKeysExtra' : require(__dirname + '/plugins/aws/iam/accessKeysExtra.js'), + 'accessKeysLastUsed' : require(__dirname + '/plugins/aws/iam/accessKeysLastUsed.js'), + 'accessKeysRotated' : require(__dirname + '/plugins/aws/iam/accessKeysRotated.js'), + 'certificateExpiry' : require(__dirname + '/plugins/aws/iam/certificateExpiry.js'), + 'emptyGroups' : require(__dirname + '/plugins/aws/iam/emptyGroups.js'), + 'groupInlinePolicies' : require(__dirname + '/plugins/aws/iam/groupInlinePolicies.js'), + 'iamUserAdmins' : require(__dirname + '/plugins/aws/iam/iamUserAdmins.js'), + 'iamUserNameRegex' : require(__dirname + '/plugins/aws/iam/iamUserNameRegex.js'), + 'iamRolePolicies' : require(__dirname + '/plugins/aws/iam/iamRolePolicies.js'), + 'iamRoleLastUsed' : require(__dirname + '/plugins/aws/iam/iamRoleLastUsed.js'), + 'maxPasswordAge' : require(__dirname + '/plugins/aws/iam/maxPasswordAge.js'), + 'minPasswordLength' : require(__dirname + '/plugins/aws/iam/minPasswordLength.js'), + 'noUserIamPolicies' : require(__dirname + '/plugins/aws/iam/noUserIamPolicies.js'), + 'passwordExpiration' : require(__dirname + '/plugins/aws/iam/passwordExpiration.js'), + 'passwordRequiresLowercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresLowercase.js'), + 'passwordRequiresNumbers' : require(__dirname + '/plugins/aws/iam/passwordRequiresNumbers.js'), + 'passwordRequiresSymbols' : require(__dirname + '/plugins/aws/iam/passwordRequiresSymbols.js'), + 'passwordRequiresUppercase' : require(__dirname + '/plugins/aws/iam/passwordRequiresUppercase.js'), + 'passwordReusePrevention' : require(__dirname + '/plugins/aws/iam/passwordReusePrevention.js'), + 'rootAccessKeys' : require(__dirname + '/plugins/aws/iam/rootAccessKeys.js'), + 'rootSigningCertificate' : require(__dirname + '/plugins/aws/iam/rootSigningCertificate.js'), + 'rootAccountInUse' : require(__dirname + '/plugins/aws/iam/rootAccountInUse.js'), + 'rootHardwareMfa' : require(__dirname + '/plugins/aws/iam/rootHardwareMfa.js'), + 'rootMfaEnabled' : require(__dirname + '/plugins/aws/iam/rootMfaEnabled.js'), + 'sshKeysRotated' : require(__dirname + '/plugins/aws/iam/sshKeysRotated.js'), + 'usersMfaEnabled' : require(__dirname + '/plugins/aws/iam/usersMfaEnabled.js'), + 'usersPasswordAndKeys' : require(__dirname + '/plugins/aws/iam/usersPasswordAndKeys.js'), + 'usersPasswordLastUsed' : require(__dirname + '/plugins/aws/iam/usersPasswordLastUsed.js'), + 'canaryKeysUsed' : require(__dirname + '/plugins/aws/iam/canaryKeysUsed.js'), + 'kinesisEncrypted' : require(__dirname + '/plugins/aws/kinesis/kinesisEncrypted.js'), + 'firehoseEncrypted' : require(__dirname + '/plugins/aws/firehose/firehoseEncrypted.js'), + 'kmsKeyRotation' : require(__dirname + '/plugins/aws/kms/kmsKeyRotation.js'), + 'kmsScheduledDeletion' : require(__dirname + '/plugins/aws/kms/kmsScheduledDeletion.js'), + 'kmsKeyPolicy' : require(__dirname + '/plugins/aws/kms/kmsKeyPolicy.js'), + 'kmsDefaultKeyUsage' : require(__dirname + '/plugins/aws/kms/kmsDefaultKeyUsage.js'), + + 'rdsAutomatedBackups' : require(__dirname + '/plugins/aws/rds/rdsAutomatedBackups.js'), + 'rdsEncryptionEnabled' : require(__dirname + '/plugins/aws/rds/rdsEncryptionEnabled.js'), + 'rdsLoggingEnabled' : require(__dirname + '/plugins/aws/rds/rdsLoggingEnabled.js'), + 'rdsPubliclyAccessible' : require(__dirname + '/plugins/aws/rds/rdsPubliclyAccessible.js'), + 'rdsRestorable' : require(__dirname + '/plugins/aws/rds/rdsRestorable.js'), + 'rdsMultiAz' : require(__dirname + '/plugins/aws/rds/rdsMultiAz.js'), + 'rdsSnapshotEncryption' : require(__dirname + '/plugins/aws/rds/rdsSnapshotEncryption.js'), + 'rdsMinorVersionUpgrade' : require(__dirname + '/plugins/aws/rds/rdsMinorVersionUpgrade.js'), + 'sqlServerTLSVersion' : require(__dirname + '/plugins/aws/rds/sqlServerTLSVersion'), + + 'domainAutoRenew' : require(__dirname + '/plugins/aws/route53/domainAutoRenew.js'), + 'domainExpiry' : require(__dirname + '/plugins/aws/route53/domainExpiry.js'), + 'domainTransferLock' : require(__dirname + '/plugins/aws/route53/domainTransferLock.js'), + + 'bucketEncryptionInTransit' : require(__dirname + '/plugins/aws/s3/bucketEncryptionInTransit.js'), + 'bucketAllUsersPolicy' : require(__dirname + '/plugins/aws/s3/bucketAllUsersPolicy.js'), + 'bucketAllUsersAcl' : require(__dirname + '/plugins/aws/s3/bucketAllUsersAcl.js'), + 'bucketVersioning' : require(__dirname + '/plugins/aws/s3/bucketVersioning.js'), + 'bucketLogging' : require(__dirname + '/plugins/aws/s3/bucketLogging.js'), + 's3Encryption' : require(__dirname + '/plugins/aws/s3/s3Encryption.js'), + 'bucketPublicAccessBlock' : require(__dirname + '/plugins/aws/s3/bucketPublicAccessBlock.js'), + 'bucketEncryption' : require(__dirname + '/plugins/aws/s3/bucketEncryption.js'), + 'bucketWebsiteEnabled' : require(__dirname + '/plugins/aws/s3/bucketWebsiteEnabled.js'), + 'bucketEnforceEncryption' : require(__dirname + '/plugins/aws/s3/bucketEnforceEncryption.js'), + + 'notebookDataEncrypted' : require(__dirname + '/plugins/aws/sagemaker/notebookDataEncrypted.js'), + 'notebookDirectInternetAccess' : require(__dirname + '/plugins/aws/sagemaker/notebookDirectInternetAccess.js'), + + 'dkimEnabled' : require(__dirname + '/plugins/aws/ses/dkimEnabled.js'), + + 'topicPolicies' : require(__dirname + '/plugins/aws/sns/topicPolicies.js'), + 'sqsCrossAccount' : require(__dirname + '/plugins/aws/sqs/sqsCrossAccount.js'), + 'sqsEncrypted' : require(__dirname + '/plugins/aws/sqs/sqsEncrypted.js'), + + 'ssmEncryptedParameters' : require(__dirname + '/plugins/aws/ssm/ssmEncryptedParameters.js'), + 'ssmActiveOnAllInstances' : require(__dirname + '/plugins/aws/ssm/ssmActiveOnAllInstances.js'), + 'ssmAgentLatestVersion' : require(__dirname + '/plugins/aws/ssm/ssmAgentLatestVersion.js'), + + 'lambdaOldRuntimes' : require(__dirname + '/plugins/aws/lambda/lambdaOldRuntimes.js'), + 'lambdaVpcConfig' : require(__dirname + '/plugins/aws/lambda/lambdaVpcConfig.js'), + 'lambdaPublicAccess' : require(__dirname + '/plugins/aws/lambda/lambdaPublicAccess.js'), + 'lambdaLogGroups' : require(__dirname + '/plugins/aws/lambda/lambdaLogGroups.js'), + + 'monitoringMetrics' : require(__dirname + '/plugins/aws/cloudwatchlogs/monitoringMetrics.js'), + + 'redshiftEncryptionEnabled' : require(__dirname + '/plugins/aws/redshift/redshiftEncryptionEnabled.js'), + 'redshiftPubliclyAccessible' : require(__dirname + '/plugins/aws/redshift/redshiftPubliclyAccessible.js'), + + 'transferLoggingEnabled' : require(__dirname + '/plugins/aws/transfer/transferLoggingEnabled.js'), + + 'shieldAdvancedEnabled' : require(__dirname + '/plugins/aws/shield/shieldAdvancedEnabled.js'), + 'shieldEmergencyContacts' : require(__dirname + '/plugins/aws/shield/shieldEmergencyContacts.js'), + 'shieldProtections' : require(__dirname + '/plugins/aws/shield/shieldProtections.js'), + + 'enableAllFeatures' : require(__dirname + '/plugins/aws/organizations/enableAllFeatures.js'), + 'organizationInvite' : require(__dirname + '/plugins/aws/organizations/organizationInvite.js'), + 'guardDutyEnabled' : require(__dirname + '/plugins/aws/guardduty/guarddutyEnabled.js'), + 'guardDutyMaster' : require(__dirname + '/plugins/aws/guardduty/guarddutyMaster.js'), + + 'xrayEncryptionEnabled' : require(__dirname + '/plugins/aws/xray/xrayEncryptionEnabled.js') }, azure : { 'fileServiceEncryption' : require(__dirname + '/plugins/azure/storageaccounts/fileServiceEncryption.js'), From 50837f9793298f300e2ed08dd029554e02702aa5 Mon Sep 17 00:00:00 2001 From: AkhtarAmir Date: Sun, 18 Oct 2020 00:13:36 +0500 Subject: [PATCH 75/76] Modified plugin to avoid infinite loop --- plugins/aws/ec2/openCustomPorts.js | 67 +++++++++++++++++++------ plugins/aws/ec2/openCustomPorts.spec.js | 32 ++++++------ 2 files changed, 67 insertions(+), 32 deletions(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index e93268aa71..bdba9d52d3 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -13,8 +13,8 @@ module.exports = { open_port_allowed_list: { name: 'EC2 Allowed Open Ports', description: 'A comma-delimited list of ports that indicates open ports allowed for any connection', - regex: '[a-zA-Z0-9,]', - default: '80,443' + regex: '[a-zA-Z0-9,:]', + default: 'tcp:80,tcp:443' } }, @@ -22,17 +22,30 @@ module.exports = { var results = []; var source = {}; var regions = helpers.regions(settings); + var awsOrGov = helpers.defaultPartition(settings); var allowed_open_ports = settings.open_port_allowed_list || this.settings.open_port_allowed_list.default; - // allowed_open_ports = allowed_open_ports.split(','); + allowed_open_ports = allowed_open_ports.split(','); + + var ports = {}; + allowed_open_ports.forEach(port => { + var [protocol, portNo] = port.split(':'); + if (ports[protocol]) { + ports[protocol].push(Number(portNo)); + } else { + ports[protocol] = [Number(portNo)]; + } + }); async.each(regions.ec2, function(region, rcb){ var describeSecurityGroups = helpers.addSource(cache, source, ['ec2', 'describeSecurityGroups', region]); + if (!describeSecurityGroups) return rcb(); + if (describeSecurityGroups.err || !describeSecurityGroups.data) { helpers.addResult(results, 3, - 'Unable to query for security groups: ' + helpers.addError(describeSecurityGroups), region); + `Unable to query for security groups: ${helpers.addError(describeSecurityGroups)}`, region); return rcb(); } @@ -44,42 +57,66 @@ module.exports = { // Loop through each security group for (var g in describeSecurityGroups.data) { var group = describeSecurityGroups.data[g]; - var resource = group.GroupId; - var openPorts = []; + var resource = `arn:${awsOrGov}:ec2:${region}:${group.OwnerId}:security-group/${group.GroupId}`; if (!group.IpPermissions) continue; + var cidrIps = []; + // Loop through each ip permissions in a security group + IpPermissionsLoop: for (var p in group.IpPermissions) { var permission = group.IpPermissions[p]; - + // Loop through each ip range for an ip permissions list + IpRangesLoop: for (var r in permission.IpRanges) { var range = permission.IpRanges[r]; if (range.CidrIp && range.CidrIp === '0.0.0.0/0') { + var allowedPorts = ports[permission.IpProtocol] || []; var portRange = permission.ToPort - permission.FromPort; // Check for all the ports in port range for (let p=0; p <= portRange; p++) { var port = permission.FromPort + p; - if (!allowed_open_ports.includes(port)) { - var openPort = permission.IpProtocol.toUpperCase() + ' port ' + port; - if (openPorts.indexOf(openPort) === -1) openPorts.push(openPort.toString()); + if (!allowedPorts.includes(port)) { + if (!cidrIps.length) cidrIps.push(range.CidrIp); + break IpRangesLoop; + } + } + } + } + + + for (var l in permission.Ipv6Ranges) { + var rangeV6 = permission.Ipv6Ranges[l]; + + if (rangeV6.CidrIpv6 && rangeV6.CidrIpv6 === '::/0') { + var allowedV6Ports = ports[permission.IpProtocol] || []; + var portRangeV6 = permission.ToPort - permission.FromPort; + + // Check for all the ports in port range + for (let p=0; p <= portRangeV6; p++) { + var portV6 = permission.FromPort + p; + + if (!allowedV6Ports.includes(portV6)) { + cidrIps.push(rangeV6.CidrIpv6); + break IpPermissionsLoop; } } } } } - if (openPorts.length) { - helpers.addResult(results, 2, - 'Security group ' + group.GroupName + ' has: ' + openPorts.join(' , ') + ' open to 0.0.0.0/0', + if (!cidrIps.length) { + helpers.addResult(results, 0, + `Security group "${group.GroupName}" does not have ports open to 0.0.0.0/0`, region, resource); } else { - helpers.addResult(results, 0, - 'Security group: ' + group.GroupName + ' has no open ports', + helpers.addResult(results, 2, + `Security group "${group.GroupName}" has ports open to ${cidrIps}`, region, resource); } } diff --git a/plugins/aws/ec2/openCustomPorts.spec.js b/plugins/aws/ec2/openCustomPorts.spec.js index e32c2ccbb8..02f350f997 100644 --- a/plugins/aws/ec2/openCustomPorts.spec.js +++ b/plugins/aws/ec2/openCustomPorts.spec.js @@ -100,7 +100,7 @@ const createErrorCache = () => { describeSecurityGroups: { 'us-east-1': { err: { - message: 'error describing cloudformation stacks' + message: 'error describing security groups' }, }, }, @@ -120,25 +120,25 @@ const createNullCache = () => { describe('openCustomPorts', function () { describe('run', function () { - - it('should not return any results if unable to fetch any security groups description', function (done) { - const cache = createNullCache(); + it('should FAIL if security group has open ports', function (done) { + const cache = createCache([securityGroups[0]]); openCustomPorts.run(cache, {}, (err, results) => { - expect(results.length).to.equal(0); + expect(results.length).to.equal(1); + expect(results[0].status).to.equal(2); done(); }); }); - it('should UNKNOWN if error occurs while fetching any security groups description', function (done) { - const cache = createErrorCache(); + it('should PASS if no security group does not have open ports', function (done) { + const cache = createCache([securityGroups[1]]); openCustomPorts.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(3); + expect(results[0].status).to.equal(0); done(); }); }); - it('should PASS if no security groups are present', function (done) { + it('should PASS if no security groups found', function (done) { const cache = createCache([]); openCustomPorts.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); @@ -147,23 +147,21 @@ describe('openCustomPorts', function () { }); }); - it('should FAIL if any public open port is found', function (done) { - const cache = createCache([securityGroups[0]]); + it('should UNKNOWN if unable to describe security groups', function (done) { + const cache = createErrorCache(); openCustomPorts.run(cache, {}, (err, results) => { expect(results.length).to.equal(1); - expect(results[0].status).to.equal(2); + expect(results[0].status).to.equal(3); done(); }); }); - it('should PASS if no public open port is found', function (done) { - const cache = createCache([securityGroups[1]]); + it('should not return any results if describe security groups response not found', function (done) { + const cache = createNullCache(); openCustomPorts.run(cache, {}, (err, results) => { - expect(results.length).to.equal(1); - expect(results[0].status).to.equal(0); + expect(results.length).to.equal(0); done(); }); }); - }); }); \ No newline at end of file From 31412b517175f00f4b12d36861e13dd919838150 Mon Sep 17 00:00:00 2001 From: AkhtarAmir <31914988+AkhtarAmir@users.noreply.github.com> Date: Mon, 19 Oct 2020 21:32:48 +0500 Subject: [PATCH 76/76] Update plugins/aws/ec2/openCustomPorts.js --- plugins/aws/ec2/openCustomPorts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aws/ec2/openCustomPorts.js b/plugins/aws/ec2/openCustomPorts.js index 1e0c0a6726..bbcbc38845 100644 --- a/plugins/aws/ec2/openCustomPorts.js +++ b/plugins/aws/ec2/openCustomPorts.js @@ -115,7 +115,7 @@ module.exports = { region, resource); } else { helpers.addResult(results, 2, - `Security group "${group.GroupName}" has ports open to ${cidrIps}`, + `Security group "${group.GroupName}" has ports open to ${cidrIps.join(', ')}`, region, resource); } }