Skip to main content

Use of an insecure channel - HTTP

Need

Secure communication channel for client information transmission

Context

  • Usage of Terraform 0.12 for Infrastructure as Code (IaC)
  • Usage of AzureRM for managing Azure resources programmatically

Description

Non compliant code

provider "azurerm" {
version = "=2.40.0"
features {}
}

resource "azurerm_virtual_network" "main" {
name = "acctvn"
address_space = ["10.0.0.0/16"]
location = "West US 2"
resource_group_name = "my-resource-group"
}

resource "azurerm_subnet" "internal" {
name = "internal"
resource_group_name = "my-resource-group"
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.0.2.0/24"]
}

resource "azurerm_network_interface" "main" {
name = "acctni"
location = "West US 2"
resource_group_name = "my-resource-group"

ip_configuration {
name = "testconfiguration1"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Dynamic"
}
}

resource "azurerm_linux_virtual_machine" "main" {
name = "acctvm"
resource_group_name = "my-resource-group"
location = "West US 2"
size = "Standard_F2"
admin_username = "adminuser"
network_interface_id = azurerm_network_interface.main.id

os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}

source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}

admin_ssh_key {
username = "adminuser"
public_key = file("~/.ssh/id_rsa.pub")
}

custom_data = <<-EOF
#!/bin/bash
echo "Hello, World!" > index.html
nohup busybox httpd -f -p 80 &
EOF
}

This Terraform script sets up an Azure virtual machine and starts an HTTP server on port 80 without using HTTPS. The custom_data field in the azurerm_linux_virtual_machine resource contains a bash script that starts a simple HTTP server using busybox. This server listens on port 80, which is the default port for HTTP.

The use of HTTP means that any data sent to or from the server is not encrypted and could potentially be intercepted by malicious parties. This is a security risk, especially if sensitive data such as login credentials or personal information is being transmitted.

In addition, the use of HTTP instead of HTTPS can lead to other security vulnerabilities. For example, it could make the server more susceptible to man-in-the-middle attacks, where an attacker intercepts the communication between the client and the server.

To fix this vulnerability, the server should be configured to use HTTPS instead of HTTP. This would involve setting up an SSL/TLS certificate for the server and modifying the server configuration to use HTTPS.

Steps

  • Enable HTTPS for the application
  • Obtain an SSL/TLS certificate
  • Configure the web server to use HTTPS
  • Redirect HTTP traffic to HTTPS
  • Update the application code to use HTTPS endpoints

Compliant code

provider "azurerm" {
version = "=2.40.0"
features {}
}

resource "azurerm_virtual_network" "main" {
name = "acctvn"
address_space = ["10.0.0.0/16"]
location = "West US 2"
resource_group_name = "my-resource-group"
}

resource "azurerm_subnet" "internal" {
name = "internal"
resource_group_name = "my-resource-group"
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.0.2.0/24"]
}

resource "azurerm_network_interface" "main" {
name = "acctni"
location = "West US 2"
resource_group_name = "my-resource-group"

ip_configuration {
name = "testconfiguration1"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Dynamic"
}
}

resource "azurerm_linux_virtual_machine" "main" {
name = "acctvm"
resource_group_name = "my-resource-group"
location = "West US 2"
size = "Standard_F2"
admin_username = "adminuser"
network_interface_id = azurerm_network_interface.main.id

os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}

source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}

admin_ssh_key {
username = "adminuser"
public_key = file("~/.ssh/id_rsa.pub")
}

custom_data = <<-EOF
#!/bin/bash
sudo apt-get update
sudo apt-get install -y nginx
sudo ufw allow 'Nginx Full'
sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com"
sudo sh -c 'echo "server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
location / {
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
}
}" > /etc/nginx/sites-available/default'
sudo systemctl restart nginx
EOF
}

The above code is a fixed version of the original Terraform script. The main change is in the custom_data field of the azurerm_linux_virtual_machine resource.

In the original script, a simple HTTP server was started using busybox. This server was insecure as it was transmitting data over HTTP, which is not encrypted.

In the fixed script, we are installing and configuring Nginx, a popular web server. We are also generating a self-signed SSL certificate and configuring Nginx to use this certificate for HTTPS.

The Nginx configuration includes a server block that listens on port 80 (HTTP) and redirects all traffic to HTTPS. This ensures that even if a client tries to connect using HTTP, they will be redirected to the secure HTTPS endpoint.

Please note that in a production environment, you should use a certificate issued by a trusted certificate authority instead of a self-signed certificate.

References