Insecure Authentication
Fixing Insecure Authentication
About Insecure Authentication
What is improper authentication?
Improper authentication is a security weakness that occurs when a system does not properly verify the identity of users or entities attempting to access it. Improper authentication can occur in various forms, such as no password, weak or easily guessed passwords, absence of multi-factor authentication, lack of session timeouts, etc.
Inadequate authentication mechanisms can allow unauthorized users to gain access to a system, potentially leading to data breaches, data loss, or unauthorized access to sensitive resources.
Examples of improper authentication vulnerabilities include:
- No authentication: When there is no authentication for a critical function, then attackers get unrestricted access easily.
- Weak passwords: When users choose weak passwords, it makes it easier for attackers to guess or crack them.
- Lack of multi-factor authentication: Multi-factor authentication, such as using a password and a one-time code sent to a user's mobile device, can provide an extra layer of security. If multi-factor authentication is not used, an attacker who has obtained a user's password can gain access to the system.
- Lack of session timeouts: When users do not log out of the system, the session may remain active, allowing an attacker to hijack the session and gain access to the system.
Check out this video for a high-level explanation:
What is the impact of improper authentication?
Improper authentication can lead to various security threats, such as:
- Data breaches: Improper authentication can allow unauthorized users to gain access to sensitive data, leading to data breaches, data loss, or unauthorized access to confidential information.
- Unauthorized access to resources: Attackers can exploit improper authentication to gain unauthorized access to resources, such as servers, databases, and applications.
- Impersonation of legitimate users: Attackers can use stolen or weak credentials to impersonate legitimate users and perform actions on their behalf.
- Account takeover: Attackers can use improper authentication to take over user accounts and gain access to sensitive data or resources.
- Compliance violations: Improper authentication can lead to violations of regulatory compliance requirements, such as data protection regulations.
- Reputation damage: A successful attack exploiting improper authentication can lead to loss of customer trust and reputational damage for the organization.
How to prevent improper authentication?
To prevent improper authentication vulnerabilities, it is essential to implement secure authentication mechanisms that verify the identity of users and entities attempting to access the system.
Here are some measures that can help prevent improper authentication:
- Strong passwords: Implement password policies that require users to choose strong, unique, and complex passwords. This can include length requirements, character complexity requirements, and password expiration policies.
- Multi-factor authentication: Use multi-factor authentication to provide an extra layer of security. This can include using a password and a one-time code sent to a user's mobile device or using biometric authentication.
- Session timeouts: Implement session timeouts to ensure that users are automatically logged out of the system after a certain period of inactivity. This can help prevent unauthorized access to the system through hijacked sessions.
- Access controls: Implement access controls that restrict access to sensitive resources and data based on user roles and permissions. This can help prevent unauthorized access to sensitive information or systems.
- User education: Educate users about the importance of strong passwords, multi-factor authentication, and other best practices for secure authentication. This can include regular reminders, training, and awareness campaigns.
- Regular security audits: Regularly audit your system for security vulnerabilities, including improper authentication vulnerabilities. Use automated tools and manual testing to identify potential issues and fix them before they can be exploited.
References
Taxonomies
Explanation & Prevention
Related CVEs
Training
Using Default Service Account
Google Compute Instances must not be configured to use the Default Service Account, which has full access to all Cloud APIs, which means the attribute service_account
and its sub-attribute email
must be defined. Additionally, email
must not be empty and must also not be a default Google Compute Engine service account.
This rule is violated if any of the following conditions are false:
google_compute_instance
service_account
must be defined and not nullgoogle_compute_instance
service_account.email
must be defined and not nullgoogle_compute_instance
service_account.email
must not be emptygoogle_compute_instance
service_account.email
must not be a default Google Compute Engine service accountgoogle_compute_instance
service_account.email
must be a valid email address
Rule-specific references:
Option A: Make sure none of the above conditions are true
From the following vulnerable patterns, replace them with a non-vulnerable pattern.
Locate one of the following vulnerable patterns:
Vulnerable
service_account
is undefined pattern:resource "google_compute_instance" "positive1" {
name = "test"
machine_type = "e2-medium"
zone = "us-central1-a"
tags = ["foo", "bar"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral IP
}
}
}Vulnerable
service_account.email
is undefined pattern:resource "google_compute_instance" "positive2" {
name = "test"
machine_type = "e2-medium"
zone = "us-central1-a"
tags = ["foo", "bar"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral IP
}
}
service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}Vulnerable
service_account.email
is empty pattern:resource "google_compute_instance" "positive3" {
name = "test"
machine_type = "e2-medium"
zone = "us-central1-a"
tags = ["foo", "bar"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral IP
}
}
service_account {
email = ""
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}Vulnerable
service_account.email
is not a valid email address pattern:resource "google_compute_instance" "positive4" {
name = "test"
machine_type = "e2-medium"
zone = "us-central1-a"
tags = ["foo", "bar"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral IP
}
}
service_account {
email = "a"
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}Vulnerable
service_account.email
is a default Google Compute Engine service account pattern:resource "google_compute_instance" "positive5" {
name = "test"
machine_type = "e2-medium"
zone = "us-central1-a"
tags = ["foo", "bar"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral IP
}
}
service_account {
email = "[email protected]"
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}Modify the config to something like the following:
resource "google_compute_instance" "negative1" {
name = "test"
machine_type = "e2-medium"
zone = "us-central1-a"
tags = ["foo", "bar"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
// Local SSD disk
scratch_disk {
interface = "SCSI"
}
network_interface {
network = "default"
access_config {
// Ephemeral IP
}
}
service_account {
email = "[email protected]"
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}Test it
Ship it 🚢 and relax 🌴
GKE Using Default Service Account
Kubernetes Engine Clusters should not be configured to use the default service account.
Rule-specific references:
Option A: Make sure to specify a non-default Service Account
If no resource
google_container_cluster.node_config.service_account
is specified for the cluster nodes, the "default" service account is used.
Locate the following vulnerable pattern:
Vulnerable default
service_account
pattern:resource "google_container_cluster" "positive1" {
name = "my-gke-cluster"
location = "us-central1"
remove_default_node_pool = true
initial_node_count = 1
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
labels = {
foo = "bar"
}
tags = ["foo", "bar"]
}
timeouts {
create = "30m"
update = "40m"
}
}Vulnerable default
service_account
pattern by being specific:resource "google_container_cluster" "positive2" {
name = "my-gke-cluster"
location = "us-central1"
remove_default_node_pool = true
initial_node_count = 1
node_config {
service_account = google_service_account.default.email
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
labels = {
foo = "bar"
}
tags = ["foo", "bar"]
}
timeouts {
create = "30m"
update = "40m"
}
}Modify the config to something like the following:
Replacement specific custom
service_account
pattern:resource "google_container_cluster" "negative1" {
name = "my-gke-cluster"
location = "us-central1"
remove_default_node_pool = true
initial_node_count = 1
node_config {
service_account = google_service_account.myserviceaccount.email
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
labels = {
foo = "bar"
}
tags = ["foo", "bar"]
}
timeouts {
create = "30m"
update = "40m"
}
}Test it
Ship it 🚢 and relax 🌴
EC2 Instance Using API Keys
EC2 instances should use roles to be granted access to other AWS services.
Rule-specific references:
Option A: Remove API keys from EC2 instances
- Do not include API keys in
user_data
whether encoded or not - Do not include API keys in an EC2 instance by using a "remote-exec"
provisioner
- Do not include API keys in an EC2 instance by using a "file"
provisioner
Locate any of the following vulnerable patterns:
Do not insert API keys into
user_data
as environment variables:provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "positive1" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
tags = {
Name = "test"
}
user_data = <<EOF
#!/bin/bash
apt-get install -y awscli
export AWS_ACCESS_KEY_ID=your_access_key_id_here
export AWS_SECRET_ACCESS_KEY=your_secret_access_key_here
EOF
credit_specification {
cpu_credits = "unlimited"
}
}Do not insert API keys in
user_data
so that they are inserted into configuration files:provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "positive2" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
tags = {
Name = "test"
}
user_data = <<EOT
#!/bin/bash
apt-get install -y awscli
cat << EOF > ~/.aws/config
[default]
aws_access_key_id = somekey
aws_secret_access_key = somesecret
EOF
EOT
credit_specification {
cpu_credits = "unlimited"
}
}Do not insert API keys into
user_data
so that they are inserted into credentials files:provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "positive3" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
tags = {
Name = "test"
}
user_data = <<EOT
#!/bin/bash
apt-get install -y awscli
cat << EOF > ~/.aws/credentials
[default]
aws_access_key_id = somekey
aws_secret_access_key = somesecret
EOF
EOT
credit_specification {
cpu_credits = "unlimited"
}
}Do not insert API keys into
user_data_base64
. Encoding provides no security:provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "positive4" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
tags = {
Name = "test"
}
user_data_base64 = var.init_aws_cli
credit_specification {
cpu_credits = "unlimited"
}
}Or a similar example using
user_data_base64
:provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "positive5" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
tags = {
Name = "test"
}
user_data_base64 = base64encode("apt-get install -y awscli; export AWS_ACCESS_KEY_ID=your_access_key_id_here; export AWS_SECRET_ACCESS_KEY=your_secret_access_key_here")
credit_specification {
cpu_credits = "unlimited"
}
}Do not insert API keys into
user_data
by inserting them as environment variables into a shell configuration file:provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "positive6" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
tags = {
Name = "test"
}
user_data = <<EOT
#cloud-config
repo_update: true
repo_upgrade: all
packages:
- awscli
runcmd:
- [ sh, -c, "echo export AWS_ACCESS_KEY_ID=my-key-id >> ~/.bashrc" ]
- [ sh, -c, "echo export AWS_SECRET_ACCESS_KEY=my-secret >> ~/.bashrc" ]
EOT
credit_specification {
cpu_credits = "unlimited"
}
}Do not insert API keys into EC2 instance credentials file using "remote-exec"
provisioner
:provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "positive7" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
tags = {
Name = "test"
}
provisioner "remote-exec" {
inline = [
"wget -O - http://config.remote.server.com/aws-credentials > ~/.aws/credentials;"
]
}
credit_specification {
cpu_credits = "unlimited"
}
}Do not insert API keys into EC2 instance credentials file using "file"
provisioner
:provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "positive8" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
tags = {
Name = "test"
}
provisioner "file" {
source = "conf/aws-credentials"
destination = "~/.aws/credentials"
}
}Do not insert API keys into EC2 instance shell configuration file using "remote-exec"
provisioner
:provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "positive9" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
tags = {
Name = "test"
}
provisioner "remote-exec" {
inline = [
"echo export AWS_ACCESS_KEY_ID=my-key-id >> ~/.bashrc",
"echo export AWS_SECRET_ACCESS_KEY=my-secret >> ~/.bashrc"
]
}
credit_specification {
cpu_credits = "unlimited"
}
}Modify the config to something like the following:
Using a role via
iam_instance_profile
:provider "aws" {
region = "us-east-1"
}
resource "aws_iam_role_policy_attachment" "test_attach" {
roles = [aws_iam_role.test_role.name]
policy_arn = aws_iam_policy.test_policy.arn
}
resource "aws_iam_policy" "test_policy" {
name = "test_policy"
description = "test policy"
path = "/"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:Get*",
"s3:List*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role" "test_role" {
name = "test_role"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_instance_profile" "test_profile" {
name = "test_profile"
role = aws_iam_role.role.name
}
resource "aws_instance" "negative1" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
tags = {
Name = "test"
}
iam_instance_profile = aws_iam_instance_profile.test_profile.name
credit_specification {
cpu_credits = "unlimited"
}
}Or just remove them altogether:
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "~> 3.0"
name = "single-instance"
ami = "ami-ebd02392"
instance_type = "t2.micro"
key_name = "user1"
monitoring = true
vpc_security_group_ids = ["sg-12345678"]
subnet_id = "subnet-eddcdzz4"
tags = {
Terraform = "true"
Environment = "dev"
}
}Test it
Ship it 🚢 and relax 🌴
Default Service Account In Use
Default service accounts should not be actively used.
resource
kubernetes_service_account
automount_service_account_token
should be defined and set to false.
Rule-specific references:
Option A: Opt-out of automounting API credentials for a service account
Opt-out of automounting API credentials for a service account by defining and setting resource
kubernetes_service_account
automount_service_account_token
to be false.
Locate the following vulnerable pattern:
resource "kubernetes_service_account" "example" {
metadata {
name = "default"
}
}
resource "kubernetes_service_account" "example2" {
metadata {
name = "default"
}
automount_service_account_token = true
}Modify the config to something like the following:
resource "kubernetes_service_account" "example3" {
metadata {
name = "default"
}
automount_service_account_token = false
}Test it
Ship it 🚢 and relax 🌴