kics icon indicating copy to clipboard operation
kics copied to clipboard

"Passwords And Secrets - Generic Secret" False Positive Results

Open rafaela-soares opened this issue 2 years ago • 0 comments

CASE 1

Actual Behavior

A false positive result is detected in line 76 ( SLACK_SIGNING_SECRET = "projects/455826092000/secrets/SlackSigningSecret/versions/latest"). The result is flagging a path to a secret, which is not a True Positive.

Steps to Reproduce the Problem

docker run -v /path/folder:/path checkmarx/kics:v1.6.1 scan -p /path/sample.json

Sample to reproduce the problem:


locals {
  project           = "larkworthy-tester"
  project_number    = "455826092000"
  location          = "EU"
  region            = "europe-west1"
  base_image_name   = "openresty/openresty"
  base_image_tag    = "1.15.8.3-alpine"
  upstream_url      = "https://camunda-secure-flxotk3pnq-ew.a.run.app"
  authorized_domain = "futurice.com"
  # You need to provision this manually at https://console.developers.google.com/apis/credentials
  # We are building a Web Application and do not need the client_secret
  oauth_client_id = "455826092000-oi4h9ul0b943oi8f8in89pnjiroj1d4u.apps.googleusercontent.com"
  # Chicken and egg: You can only figure this out after deploying once!
  service_url = "https://openresty-flxotk3pnq-ew.a.run.app"
}

terraform {
  backend "gcs" {
    prefix = "openresty/state"
    bucket = "terraform-larkworthy"
  }
}

provider "google" {
  project = local.project
  region  = local.region
}

# Create service account to run service
resource "google_service_account" "openresty" {
  account_id   = "openresty"
  display_name = "openresty"
}

resource "google_project_iam_member" "openresty_invoker" {
  project = local.project
  role    = "roles/run.invoker"
  member  = "serviceAccount:${google_service_account.openresty.email}"
}

resource "google_project_iam_member" "openresty_publisher" {
  project = local.project
  role    = "roles/pubsub.publisher"
  member  = "serviceAccount:${google_service_account.openresty.email}"
}
resource "google_project_iam_member" "openresty_subscriber" {
  project = local.project
  role    = "roles/pubsub.subscriber"
  member  = "serviceAccount:${google_service_account.openresty.email}"
}

# Policy to allow public access to Cloud Run endpoint
data "google_iam_policy" "noauth" {
  binding {
    role    = "roles/run.invoker"
    members = ["allUsers"]
  }
}

# Allow public access to ORY openresty
resource "google_cloud_run_service_iam_policy" "noauth" {
  location    = google_cloud_run_service.openresty.location
  project     = google_cloud_run_service.openresty.project
  service     = google_cloud_run_service.openresty.name
  policy_data = data.google_iam_policy.noauth.policy_data
}

# Hydrate config into .build directory
resource "local_file" "config" {
  content = templatefile("${path.module}/files/default.template.conf", {
    OAUTH_CLIENT_ID      = local.oauth_client_id
    UPSTREAM_URL         = local.upstream_url
    AUTHORIZED_DOMAIN    = local.authorized_domain
    WAL_TOPIC            = google_pubsub_topic.httpwal.id
    SLACK_SIGNING_SECRET = "projects/455826092000/secrets/SlackSigningSecret/versions/latest"
    AUTHORIZED_WAL_USER  = google_service_account.openresty.email
  })
  filename = "${path.module}/.build/default.conf"
}

# Hydrate login into .build directory
resource "local_file" "login" {
  content = templatefile("${path.module}/files/login.template", {
    OAUTH_CLIENT_ID = local.oauth_client_id
  })
  filename = "${path.module}/.build/login"
}

# Copy files into .build directory
resource "template_dir" "swiss" {
  source_dir      = "${path.module}/files/swiss"
  destination_dir = "${path.module}/.build/swiss"
}

# Create a zip just to generate a sha
data "archive_file" "swiss" {
  type        = "zip"
  source_dir = "${path.module}/.build/swiss"
  output_path = "/tmp/swiss.zip"
}

# Cloud Run Openresty
resource "google_cloud_run_service" "openresty" {
  name     = "openresty"
  location = local.region
  template {
    spec {
      # Use locked down Service Account
      service_account_name = google_service_account.openresty.email
      containers {
        image = null_resource.openresty_image.triggers.image
      }
    }
  }

  traffic {
    percent         = 100
    latest_revision = true
  }
}

resource "google_pubsub_topic" "httpwal" {
  name = "openresty_wal"
}

# grant Cloud Pub/Sub the permission to create tokens for authenticating the subscription
resource "google_project_iam_member" "pubsub_token_creator" {
  project = local.project
  role    = "roles/iam.serviceAccountTokenCreator"
  member  = "serviceAccount:service-${local.project_number}@gcp-sa-pubsub.iam.gserviceaccount.com"
}

resource "google_pubsub_subscription" "httpwal" {
  name  = "httpwal"
  topic = google_pubsub_topic.httpwal.name

  ack_deadline_seconds = 120
  push_config {
    push_endpoint = "${local.service_url}/wal-playback/"

    oidc_token {
      service_account_email = google_service_account.openresty.email
    }
    attributes = {
      x-goog-version = "v1"
    }
  }
}

CASE 2

Actual Behavior

A false positive result is detected in line 24 ( Description: 'Used to create resource-based authorization policy for "secretsmanager:GetSecretValue" action. E.g. All Athena JDBC Federation secret names can be prefixed with "AthenaJdbcFederation" and authorization policy will allow "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:AthenaJdbcFederation*". Parameter value in this case should be "AthenaJdbcFederation". If you do not have a prefix, you can manually update the IAM policy to add allow any secret names.'). The result is flagging a description block, which is not a True Positive.

Steps to Reproduce the Problem

docker run -v /path/folder:/path checkmarx/kics:v1.6.1 scan -p /path/sample.json

Sample to reproduce the problem:

Transform: 'AWS::Serverless-2016-10-31'
Metadata:
  'AWS::ServerlessRepo::Application':
    Name: AthenaJdbcConnector
    Description: 'This connector enables Amazon Athena to communicate with your Database instance(s) using JDBC driver.'
    Author: 'default author'
    SpdxLicenseId: Apache-2.0
    LicenseUrl: LICENSE.txt
    ReadmeUrl: README.md
    Labels:
      - athena-federation
    HomePageUrl: 'https://github.com/awslabs/aws-athena-query-federation'
    SemanticVersion: 2021.41.1
    SourceCodeUrl: 'https://github.com/awslabs/aws-athena-query-federation'
Parameters:
  LambdaFunctionName:
    Description: 'The name you will give to this catalog in Athena. It will also be used as the function name. This name must satisfy the pattern ^[a-z0-9-_]{1,64}$'
    Type: String
    AllowedPattern: ^[a-z0-9-_]{1,64}$
  DefaultConnectionString:
    Description: 'The default connection string is used when catalog is "lambda:${LambdaFunctionName}". Catalog specific Connection Strings can be added later. Format: ${DatabaseType}://${NativeJdbcConnectionString}.'
    Type: String
  SecretNamePrefix:
      Description: 'Used to create resource-based authorization policy for "secretsmanager:GetSecretValue" action. E.g. All Athena JDBC Federation secret names can be prefixed with "AthenaJdbcFederation" and authorization policy will allow "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:AthenaJdbcFederation*". Parameter value in this case should be "AthenaJdbcFederation". If you do not have a prefix, you can manually update the IAM policy to add allow any secret names.'
      Type: String
  SpillBucket:
    Description: 'The name of the bucket where this function can spill data.'
    Type: String
  SpillPrefix:
    Description: 'The prefix within SpillBucket where this function can spill data.'
    Type: String
    Default: athena-spill
  LambdaTimeout:
    Description: 'Maximum Lambda invocation runtime in seconds. (min 1 - 900 max)'
    Default: 900
    Type: Number
  LambdaMemory:
    Description: 'Lambda memory in MB (min 128 - 3008 max).'
    Default: 3008
    Type: Number
  DisableSpillEncryption:
    Description: 'If set to ''false'' data spilled to S3 is encrypted with AES GCM'
    Default: 'false'
    Type: String
  SecurityGroupIds:
    Description: 'One or more SecurityGroup IDs corresponding to the SecurityGroup that should be applied to the Lambda function. (e.g. sg1,sg2,sg3)'
    Type: 'List<AWS::EC2::SecurityGroup::Id>'
  SubnetIds:
    Description: 'One or more Subnet IDs corresponding to the Subnet that the Lambda function can use to access you data source. (e.g. subnet1,subnet2)'
    Type: 'List<AWS::EC2::Subnet::Id>'
Resources:
  JdbcConnectorConfig:
    Type: 'AWS::Serverless::Function'
    Properties:
      Environment:
        Variables:
          disable_spill_encryption: !Ref DisableSpillEncryption
          spill_bucket: !Ref SpillBucket
          spill_prefix: !Ref SpillPrefix
          default: !Ref DefaultConnectionString
      FunctionName: !Ref LambdaFunctionName
      Handler: "com.amazonaws.athena.connectors.jdbc.MultiplexingJdbcCompositeHandler"
      CodeUri: "./target/athena-jdbc-2021.41.1.jar"
      Description: "Enables Amazon Athena to communicate with Databases using JDBC"
      Runtime: java8
      Timeout: !Ref LambdaTimeout
      MemorySize: !Ref LambdaMemory
      Policies:
        - Statement:
            - Action:
                - secretsmanager:GetSecretValue
              Effect: Allow
              Resource: !Sub 'arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:${SecretNamePrefix}*'
          Version: '2012-10-17'
        - Statement:
            - Action:
                - logs:CreateLogGroup
              Effect: Allow
              Resource: !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*'
          Version: '2012-10-17'
        - Statement:
          - Action:
              - logs:CreateLogStream
              - logs:PutLogEvents
            Effect: Allow
            Resource: !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${LambdaFunctionName}:*'
          Version: '2012-10-17'
        - Statement:
          - Action:
              - athena:GetQueryExecution
              - s3:ListAllMyBuckets
            Effect: Allow
            Resource: '*'
          Version: '2012-10-17'
        #S3CrudPolicy allows our connector to spill large responses to S3. You can optionally replace this pre-made policy
        #with one that is more restrictive and can only 'put' but not read,delete, or overwrite files.
        - S3CrudPolicy:
            BucketName: !Ref SpillBucket
        #VPCAccessPolicy allows our connector to run in a VPC so that it can access your data source.
        - VPCAccessPolicy: {}
      VpcConfig:
        SecurityGroupIds: !Ref SecurityGroupIds
        SubnetIds: !Ref SubnetIds

rafaela-soares avatar Oct 03 '22 16:10 rafaela-soares