Azure Vulnerability
Management Lab
This is not a step-by-step deployment tutorial, but rather a documentation of what I implemented and the results I achieved. While you may be able to follow along and set up your own deployment, some components and configurations are not fully detailed here, such as the Azure resource deployment/scan tools setup/exact scanning process. Every finding has a traceable path from discovery to remediation. The methodology is simple: scan->analyze->harden->verify.
Overview
This lab covers the full vulnerability management lifecycle on two freshly deployed Azure VMs. The Ubuntu machine doubles as both a target and a scanner host. The Windows machine is a standalone target with no domain infrastructure. Both were assessed from an external Kali Linux host using credentialed scans, then hardened based on the findings, then re-scanned to confirm improvement.
You can find all the raw and detailed results of the scans performed during this project on my Github repo: github.com/dalli-krichen/azure-vulnerability-management-lab
1. Azure Infrastructure
A dedicated resource group DalliRG was created in the France Central region under an Azure Free Tier subscription. A virtual network vnet1 connects both VMs on the same private subnet, allowing them to communicate internally at 10.0.0.0/24.
Opening the NSG — Allowing the Scanner In
Azure NSGs block all inbound traffic by default. An inbound rule named Allow-Kali-Scanner was added at priority 100 to both VMs' NSGs, allowing all traffic from the Kali public IP 41.62.86.217.
Windows Local Firewall
The Azure NSG alone isn't enough for Windows — the OS-level Windows Defender Firewall also blocks inbound by default. A PowerShell rule was added to allow inbound connections from the Kali IP across all protocols.
2. Building the Scanner Stack
Lynis
Installed directly on the Ubuntu VM via apt. Lynis audits the local system from the inside — no network scan, no agent. It checks SSH config, PAM, kernel parameters, file permissions, services, and more, then produces a hardening index score.
Nessus Essentials
Downloaded from the Tenable website and installed on the Kali VM. Exposes a web interface at https://localhost:8834. Credentialed scans give Nessus OS-level access to inspect services, packages, and configuration from the inside — not just open ports.
Downloading via curl and confirming the output:
CIS-CAT Lite (v4.60)
Free compliance assessment tool from the Center for Internet Security. The zip was transferred to both VMs — SCP to Ubuntu, RDP file copy to Windows. On Ubuntu, navigating to the Assessor directory and running the CLI revealed a Java version conflict that needed fixing before it would execute. On Windows, the .bat launcher failed silently so the GUI version was used instead.
Transferring CIS-CAT to the Ubuntu VM and navigating to the Assessor directory:
Copying CIS-CAT to the Windows VM:
Running on Ubuntu — Java reflective access warnings, but the tool starts and lists available benchmarks. Ubuntu 24.04 LTS selected:
Java conflict on first attempt — wrong JDK version:
Switching to Oracle JDK resolves it:
CIS-CAT Ubuntu baseline result in the terminal — 64.66%:
CIS-CAT on Windows — GUI auto-detects the OS and prompts with the correct benchmark:
Interactive assessment running and completing on Windows:
OpenVAS via Docker
The initial plan was to run OpenVAS directly on Kali. After setup, the feed sync blocked all scans with no progress for several hours — a resource limitation on the local Kali VM.
OpenVAS on Kali — feed syncing, scans blocked:
The scanner was migrated to the Ubuntu cloud VM using Docker. The Ubuntu OS disk was first expanded from 32GB to 64GB in Azure to accommodate the container image and feeds.
Feed stuck on local Kali — the migration trigger:
Docker container running — OpenVAS login page (immauss image):
Feed successfully updated on the Docker container:
sudo sysctl vm.overcommit_memory=1
sudo docker run -d --name openvas -p 9392:9392 \
-e PASSWORD="admin123" immauss/openvas
ssh -L 9392:localhost:9392 [email protected]
Creating scan tasks for both VMs:
Microsoft Defender for Cloud
Azure-native security posture management — no installation required. Enabled at the subscription level, it continuously assesses both VMs against the Microsoft Cloud Security Benchmark and surfaces actionable recommendations.
3. Establishing the Baseline
Before touching any configuration, all five tools were run in sequence to capture the exact pre-hardening state.
Lynis — Ubuntu
Baseline hardening index: 60/100. Key deficiencies: no firewall active, no intrusion detection, no password complexity policy, no audit trail, no malware scanner, and several unnecessary kernel modules loaded. Lynis flags these as WARNINGs and SUGGESTIONs in the output.
Lynis warnings and suggestions grep — the specific items to address:
CIS-CAT — Ubuntu Benchmark
Assessed against the CIS Level 1 Server benchmark for Ubuntu 24.04. Baseline: 64.66% — 82 controls failing out of 232 scored.
CIS-CAT — Windows Benchmark
Assessed against both the CIS Enterprise Benchmark and IG1 controls. Enterprise baseline: 22.43%. Low but expected — 261 of 370 controls require Active Directory GPO and are not applicable to a standalone machine.
Nessus — Ubuntu (Credentialed)
The uncredentialed scan found little beyond open ports. The credentialed scan, logged in via SSH, surfaced actionable findings around SSH cipher suites and MAC algorithms.
Nessus — Windows (Credentialed)
Key Medium finding: SMB Signing not required (CVSS 5.3). Without mandatory signing, an attacker on the network could perform SMB relay attacks — capturing and replaying authentication traffic without cracking a password.
OpenVAS — Both VMs
Scans ran against both internal IPs — 20 to 30 minutes each. Both tasks completed: Ubuntu returned 3 Low findings, Windows returned 1 Medium.
Microsoft Defender for Cloud — Baseline
24 Low-severity recommendations at baseline across missing monitoring agents, NSG exposure, and guest configuration gaps. Zero critical or high alerts.
4. Closing the Gaps
Every change below is directly linked to a finding from the baseline scans. Nothing was changed speculatively — each fix has a source tool, a severity, and a before/after verification.
Ubuntu — SSH Hardening
The default SSH config on Ubuntu 24.04 is permissive: root login allowed, password auth enabled, no session limits, X11 forwarding on. A drop-in config at /etc/ssh/sshd_config.d/hardening.conf overrides these cleanly without touching the main file.
Include /etc/ssh/sshd_config.d/*.conf
KbdInteractiveAuthentication no
UsePAM yes
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
sudo tee /etc/ssh/sshd_config.d/hardening.conf << 'EOF'
Protocol 2
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
MaxAuthTries 3
MaxSessions 2
ClientAliveInterval 300
ClientAliveCountMax 2
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
TCPKeepAlive no
LogLevel VERBOSE
PrintLastLog yes
Banner /etc/issue.net
MACs hmac-sha2-256,hmac-sha2-512,[email protected],[email protected]
AllowUsers dalli
EOF
Since password auth was being disabled, key-based login had to be set up first. ED25519 key pair generated on Windows:
Public key added to Ubuntu's authorized_keys and confirmed:
Password auth disabled in the config, sshd restarted, change verified:
Ubuntu — UFW Firewall
UFW was installed but not enabled — Lynis flagged FIRE-4512. Default-deny inbound, SSH only from the Kali IP, full access from the VNet subnet.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from 41.62.86.217 to any port 22
sudo ufw allow from 10.0.0.0/24
sudo ufw --force enable
Ubuntu — Password Policy
CIS requires minimum 14-character passwords with complexity and 24-password history. Configured via PAM's pwquality module and /etc/login.defs.
minlen = 14
dcredit = -1
ucredit = -1
ocredit = -1
lcredit = -1
maxrepeat = 3
enforce_for_root
PASS_MAX_DAYS 365
PASS_MIN_DAYS 7
PASS_WARN_AGE 14
UMASK 027
Ubuntu — fail2ban, Unused Protocols, auditd, rkhunter
fail2ban: 3-attempt ban, 1-hour duration on SSH. Kernel protocols dccp, sctp, rds, tipc blacklisted via modprobe. auditd installed with custom rules on sensitive files. rkhunter installed with initial baseline.
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/ssh/sshd_config -p wa -k sshd
-w /var/log/auth.log -p wa -k auth
-a always,exit -F arch=b64 -S execve -k exec
Ubuntu — Kernel Hardening
Persistent sysctl settings at /etc/sysctl.d/hardening.conf. Disabling TCP timestamps directly remediates the OpenVAS TCP Timestamps finding (CVSS 2.6). ICMP broadcast disabled remediates the ICMP Timestamp finding (CVSS 2.1).
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.log_martians = 1
kernel.randomize_va_space = 2
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
Lynis intermediate check after SSH and firewall hardening — already at 76 before the remaining steps:
CIS-CAT reports saved locally after baseline and after hardening — both HTML files present:
Windows — Round 1: Core Security Controls
auditpol /set /subcategory:"Credential Validation" /success:enable /failure:enable
auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Account Lockout" /success:enable /failure:enable
auditpol /set /subcategory:"Sensitive Privilege Use" /success:enable /failure:enable
auditpol /set /subcategory:"System Integrity" /success:enable /failure:enable
reg add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" /v RequireSecuritySignature /t REG_DWORD /d 1 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v RequireSecuritySignature /t REG_DWORD /d 1 /f
Additional Round 1: LmCompatibilityLevel set to 5 (NTLMv2 only), LM hash storage disabled, Windows Firewall enabled on all profiles, AutoRun disabled, 15-minute screen lock, UAC fully enforced, WDigest auth disabled, RemoteRegistry and Print Spooler stopped.
Windows — Round 2: Second Pass
CIS-CAT re-run after Round 1 — score at 30.27%. A second targeted script addressed remaining failures, pushing it to 62.16%.
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v UserAuthentication /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v SecurityLayer /t REG_DWORD /d 2 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v MinEncryptionLevel /t REG_DWORD /d 3 /f
Additional Round 2: 11 unnecessary services disabled, firewall logging on all profiles, NTLM session security hardened, mDNS and LLMNR disabled, WinRM hardened, LSA Protection enabled, Defender hardened via policy.
Defender for Cloud — Fixes Applied
5. Verifying the Fixes
All five tools re-run after hardening. Every result maps directly to the baseline — same scan config, same targets.
Lynis — Ubuntu After
Hardening index improved from 60 to 78 — an 18-point gain. Remaining gap is Azure infrastructure constraints: no separate /tmp partition, no AppArmor profiles, no bootloader password, platform-managed NTP.
CIS-CAT — Ubuntu After
Overall score improved from 64.66% to 87.07%. Host-Based Firewall jumped from 0% to 92%, Logging from ~40% to 88%.
CIS-CAT — Windows After
Enterprise benchmark improved from 22.43% to 62.16% across two rounds. System Services and Advanced Audit Policy both reached 100%.
OpenVAS — Both VMs After
Zero Critical, High, Medium, or Low findings on either VM. Every baseline finding fully remediated.
Nessus — Post-Hardening Credential Setup
Password auth was disabled on Ubuntu during hardening, so the Nessus credential had to switch from password to SSH public key with sudo privilege escalation.
Nessus — Windows After
A new High finding appeared post-hardening: SWEET32 (CVSS 7.5) on RDP port 3389. Not present before — it surfaced because the RDP hardening changes altered cipher negotiation, making the 3DES birthday attack vulnerability visible. The fix (disabling 3DES/RC4 via SCHANNEL) is documented as a known residual risk, not applied within this lab scope.
Nessus — Ubuntu After
15 total findings — all INFO severity. Zero Medium, High, or Critical. Nothing actionable.
Microsoft Defender for Cloud — After
Secure Score reached 25%, 45 of 63 MCSB controls passing, zero security alerts. Recommendation count went from 24 to 26 — the two new items are Defender preview recommendations added by Azure over time, not regressions.
6. The Full Picture
Finding → Fix → Verification
What Worked
- OpenVAS verified a clean sweep — 4 findings before, 0 after on both VMs
- Ubuntu CIS-CAT improved 22 percentage points with documented, targeted changes
- Windows Services and Audit Policy both hit 100% on the CIS Enterprise benchmark
- Every fix is traceable to a specific tool finding with a CVSS score
- Migrating OpenVAS to Docker on the cloud VM unblocked a real resource bottleneck
Limitations & Residual Risks
- SWEET32 (CVSS 7.5) on Windows RDP — fix documented, not yet applied
- Nessus credentialed scans incomplete — ED25519 format issues on Ubuntu, WMI restrictions on Windows
- Windows CIS score capped at ~62% without Active Directory for GPO-dependent controls
- /tmp partition, AppArmor, and bootloader password are Azure infrastructure constraints on Ubuntu
- Defender for Cloud Secure Score limited by free-tier subscription