🛡️ Reduction of the attack surface
Each service, port and auto-run task that is not needed is a door that someone can open. This guide shows how to find them and close them in Windows, macOS and Linux systems by signing in, closing them and opening them back. Teams are designed for their systems and first for the test environment.
NIST SP 800-53 CM-7, OWASP
What is the surface of the attack
The attack surface (attack surface) is a set of places where an attacker can try to enter data, get data or run code. Irritability is an error in one of these places. Reducing the surface means fewer places where there can be a mistake, so it also works against injuries that nobody knows about yet.
Physical and human surface are described in guides on physical and personnel security.
Minimum functionality
NIST SP 800-53 CM-7 requires the system to be configured so that it only does what it is designed for and prohibits unnecessary features, ports, protocols and services. CIS Controls v8 4. Control requires the same as secure configuration part.
Why It Benefites
The off service does not need to be updated, monitored and cannot be used. One less working component is one less row on the vulnerability list next month.
Before changing
You know what the system serves, record the current situation and change one step. Each change team in this guide has a team that returns it.
Start with
The sequence follows the logic of CIS Controls v8: first know what is (1st and 2nd controls), then reduce and harden (4th controls), then check. Each step leads to its own tab.
CIS Controls v8 1-2, ISO/IEC 27002 5.9, NIST CM-8
Cannot reduce what you don't know about
The first step is to list what devices are on the network and what software is installed on them. Each row answers one question - who needs it? A row without answer is a candidate for removal.
Windows main example
Installed apps and Windows additional resources. PowerShell:
Get-Package | Sort-Object Name |
Select-Object Name, Version
Get-WindowsOptionalFeature -Online |
Where-Object State -eq Enabled
Command line (cmd). The classic form is wmic, but it is outdated (Windows 11 24H2 does not include it anymore) and slow - it checks every MSI package. The modern form of the same list is winget:
wmic product get name,version
winget list --source winget
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall
macOS secondary
Applications, Homebrew packages and configuration profiles.
system_profiler SPApplicationsDataType |
grep -E "^ [A-Za-z]"
brew list --versions
sudo profiles list
Linux secondary
Packages (Debian/Ubuntu or RHEL/Fedora) and Snap/Flatpak.
# Debian, Ubuntu
apt list --installed
# RHEL, Fedora
rpm -qa --last | head -50
snap list; flatpak list
Equipment
At network level, the inventory is made up of DHCP and DNS logs, switchboard MAC tables and active scans in your network. An unknown device is a finding, not a noise.
Nutritional, not single
The inventory is ageing with each installation. It is collected automatically (MDM, Intune, Ansible Facts, EDR) and compared with the previous one - the new is what is checked.
CM-7, CIS Benchmarks, ISO/IEC 27002 8.9
Needless services and functions
A service that runs in the background, listens to the network or processes files is a code that executes with elevated rights. If the system does not need it, it shall be stopped and run prohibited. Examples below are typical candidates - make sure that they are not really needed in your environment before switching off.
Windows
Services that run automatically and are currently running.
Get-Service |
Where-Object { $_.StartType -eq 'Automatic' } |
Where-Object { $_.Status -eq 'Running' } |
Sort-Object Name | Select-Object Name, DisplayName
Print on Spooler server not printed (PrintNightmare, CVE-2021-34527):
Disable
Stop-Service Spooler
Set-Service Spooler -StartupType Disabled
Revert
Set-Service Spooler -StartupType Automatic
Start-Service Spooler
SMBv1 - an outdated protocol used by WannaCry:
Disable
Disable-WindowsOptionalFeature -Online `
-FeatureName SMB1Protocol -NoRestart
Revert
Enable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol
Checking for success
Get-Service Spooler | Select-Object Name, Status, StartType
Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol |
Select-Object FeatureName, State
macOS
Loaded launchd works and off system services. Shared services are more convenient to manage System Settings, General, Sharing.
sudo launchctl list | grep -v com.apple
sudo launchctl print-disabled system
Remote login (SSH) if not in use. Terminal needs Full Disk Access:
Disable
sudo systemsetup -setremotelogin off
Revert
sudo systemsetup -setremotelogin on
Screen sharing:
Disable
sudo launchctl disable system/com.apple.screensharing
Revert
sudo launchctl enable system/com.apple.screensharing
Checking for success
sudo systemsetup -getremotelogin
sudo launchctl print-disabled system | grep screensharing
Linux
Enabled and operating systemd units.
systemctl list-unit-files --type=service --state=enabled
systemctl list-units --type=service --state=running
Printer service on the server (including scant activation):
Disable
sudo systemctl disable --now cups.service cups.socket cups.path
Revert
sudo systemctl enable --now cups.service cups.socket cups.path
mDNA (Avahi) - announce the device on the local network:
Disable and prohibit startup
sudo systemctl disable --now avahi-daemon.service avahi-daemon.socket
sudo systemctl mask avahi-daemon.service avahi-daemon.socket
Revert
sudo systemctl unmask avahi-daemon.service avahi-daemon.socket
sudo systemctl enable --now avahi-daemon.service
Checking for success
systemctl is-enabled cups.service avahi-daemon.service
systemctl is-active cups.service avahi-daemon.service
Disable or Remove
The off service is still disk and the next update can be turned on again. If software is not needed at all, it is removed - then it also disappears from the vulnerability scanner report.
disable against mask
systemd disable removes the automatic startup, but another unit can still run the service. mask prohibits it completely - it is used for services that never need to start.
CIS Controls v8 12-13, ISO/IEC 27002 8.20-8.22
Open ports and network traffic
An open port is a door waiting for a knocker. First, find out which process listens and which address, then close the excess and firewalls set to the lock by default. The second direction is the outgoing traffic: what the system itself sends out and where.
Windows
Open ports with process name and firewall profiles.
Get-NetTCPConnection -State Listen |
Select-Object LocalAddress, LocalPort,
@{ n='Process';
e={ (Get-Process -Id $_.OwningProcess).ProcessName } }
Get-NetFirewallProfile |
Select-Object Name, Enabled, DefaultInboundAction
Incoming denied by default
Set-NetFirewallProfile -Profile Domain,Private,Public `
-Enabled True -DefaultInboundAction Block
Revert
Set-NetFirewallProfile -Profile Domain,Private,Public `
-DefaultInboundAction NotConfigured
Checking for success
Get-NetFirewallProfile | Select-Object Name, DefaultInboundAction
# no citas ierīces - aizvērtais ports nedrīkst atbildēt:
Test-NetConnection <servera-adrese> -Port 3389
macOS
Open TCP and UDP ports and app firewalls.
sudo lsof -iTCP -sTCP:LISTEN -n -P
sudo lsof -iUDP -n -P
/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
Enable firewall and stealth mode
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on
Revert
sudo /usr/libexec/ApplicationFirewall/socketfilterfw \
--setstealthmode off
sudo /usr/libexec/ApplicationFirewall/socketfilterfw \
--setglobalstate off
Checking for success
/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
/usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode
Linux
Open ports with process and active connections.
sudo ss -tulpn
sudo ss -tnp state established
Incoming denied, SSH allowed (ufw)
sudo ufw default deny incoming
sudo ufw allow 22/tcp
sudo ufw enable
Revert
sudo ufw disable
Checking for success
sudo ufw status verbose
# no citas ierīces - aizvērtais ports nedrīkst atbildēt:
nc -zv <servera-adrese> 5432
Trafi baseline
A short record on a normal working day (tcpdump Linux and macOS, pktmon Windows, analysis Wireshark or Zeek) shows what the system speaks to. A connection that no one can explain must be investigated.
Outgoing traffic
The server seldom needs free access to the Internet. Limiting outgoing traffic to the addresses of updates and necessary services makes it difficult for both malware communication and data removal.
Don't cut yourself out
On a remote server, first allow your control connection and only then turn off by default. Keep the second session open until check.
MITRE ATT&CK T1543, T1547, T1053, T1037
What starts up - services, autostart and planned tasks
Automatic launch is a place where the malware remains after restarting (persistance). The same site also contains forgotten updates and old software. A regular review of it reveals both the redundant and the alien.
| Mechanism | Windows | macOS | Linux |
|---|---|---|---|
| Services and background processesBegin before applying and operate with system rights - therefore it is the most valuable place for the attacker. | Get-Service, HKLM\SYSTEM\CurrentControlSet\Services |
/Library/LaunchDaemons, /Library/LaunchAgents |
/etc/systemd/system, ~/.config/systemd/user |
| Start at loginGets off when the user logins, with his rights. There are updates and app assistants. | HKLM\...\CurrentVersion\Run, HKCU\...\Run, Startup Folder |
~/Library/LaunchAgents, Loginitems (sfltool dumpbtm) |
~/.config/autostart, /etc/xdg/autostart |
| Planned tasksRun after time or event, even when no one has applied. | Task Scheduler (Get-ScheduledTask) |
crontab -l, launchd StartCalendarInterval |
crontab -l, /etc/cron.*, systemctl list-timers |
| Launch scripts and liner profilesEach session of the new shell - one line in a file, rarely opened by someone. | Group Policy Scripts, $PROFILE |
~/.zshrc, /etc/zprofile |
~/.bashrc, /etc/profile.d, /etc/rc.local |
| Event triggersSomething happens: an attached device, a modified file, a log event occurs. | WMI subscriptions (root\subscription) |
launchd WatchPaths |
udev layers, /etc/ld.so.preload |
| Nuclear modules and driversCode with highest rights. A foreign record here is the heaviest find. | driverquery /v |
kmutil showloaded, system extensions |
lsmod, /etc/modules-load.d |
How to read: a row is a mechanism, column - operating system, cell place to watch. The ATT&CK techniques for these mechanisms are T1543 (servisi), T1547 (starting at login), T1053 (planned tasks), T1037 and T1546 (scripts and triggers) - useful in searching for ready-to-disclosure rules and the protection side is shown by the Defence Map tab.
Identify Owner
Each record must have a person or system that requires it. No owner - it's a candidate for removal, not a secret.
Disable, not delete
First in the test machine, then one by one. Disabling is reversible, deletion is often not - and notes how to return.
Save List
Today's list is tomorrow's baseline. Next time you compare, and the new record, which nobody installed, is a sign of an incident.
Windows
Launch entries, non-Microsoft planned tasks and full report with Sysinternals Authoruns.
Get-CimInstance Win32_StartupCommand |
Select-Object Name, Command, Location, User
Get-ScheduledTask |
Where-Object { $_.State -ne 'Disabled' } |
Where-Object { $_.TaskPath -notlike '\Microsoft\*' } |
Select-Object TaskPath, TaskName, State
autorunsc.exe -accepteula -a * -m -s -h -c > autoruns.csv
Disabling a task (example name)
Disable-ScheduledTask -TaskPath '\' -TaskName 'VecsAtjauninatajs'
Revert
Enable-ScheduledTask -TaskPath '\' -TaskName 'VecsAtjauninatajs'
macOS
LaunchAgents and LaunchDaemons folders, background task database (macOS 13+) and cron.
ls -la ~/Library/LaunchAgents \
/Library/LaunchAgents /Library/LaunchDaemons
sudo sfltool dumpbtm
crontab -l
Stop User Agent (example name)
launchctl bootout gui/$(id -u) \
~/Library/LaunchAgents/com.example.updater.plist
Revert
launchctl bootstrap gui/$(id -u) \
~/Library/LaunchAgents/com.example.updater.plist
Linux
All users cron, system cron folders and systemd timers.
for u in $(cut -d: -f1 /etc/passwd); do
sudo crontab -l -u "$u" 2>/dev/null | sed "s/^/$u: /"
done
ls -la /etc/cron.d /etc/cron.daily /etc/cron.hourly
systemctl list-timers --all
Stop timer (example name)
sudo systemctl disable --now vecs-atjauninatajs.timer
Revert
sudo systemctl enable --now vecs-atjauninatajs.timer
Comparison with previous
One list doesn't say anything in itself. Save it (Autoruns CSV, command output) and compare next time - a new entry that nobody installed is a sign of an incident.
Tools
Windows - Sysinternals Authoruns. macOS - KnockKnock and Block Block (Objective-See). Linux - auditd or EDR that monitors changes in cron and systemd folders.
NIST SP 800-53 CM-2, CM-6, SP 800-70
Configuration baselines (benchmarks)
The baseline shall be a secure configuration state against which the system can be automatically checked. You don't have to think about yourself - internationally recognised catalogues describe hundreds of settings for each operating system, with justification and type of test.
| Catalogue | What It Is for | Hardness | Test tool | Accessibility |
|---|---|---|---|---|
| CIS Benchmarks | The widest coverage: Windows, macOS, Linux, clouds, containers, databases. | Level 1 - little impact on work; Level 2 - deeper protection. | CIS-CAT Lite, CIS-CAT Pro, OpenSCAP | PDF free of charge after registration; full CIS-CAT Pro is fees (member fee). |
| DISA STIG | Environment where the source of claims is contract or public sector reference. | Stronger than CIS Level 1; severity categories CAT I-III. | STIG Viewer, SCAP Compliance Checker | Free of charge, public. |
| Microsoft Security Baselines | Windows and Microsoft 365 environment, where settings are maintained by Group Policy or Intune. | Manufacturer recommended minimum, close to CIS Level 1. | Policy Analyzer, LGPO (Security Compliance Toolkit) | Free of charge. |
| macOS Security Compliance Project | macOS fleet, where the baseline is to be delivered as MDM profile. | Selected: CIS Level 1 to NIST High Level. | Project generated test script | Free, open source. |
| SCAP Security Guide | Linux, where the test must be automated and repeated every month. | Profiles per target (CIS, STIG, PCI DSS) per content. | OpenSCAP (oscap), Lynis kā ātrs pirmais skats | Free, open source. |
The choice is not which catalogue is better, but which organisation can maintain and prove. One catalogue, measured every month, is more valuable than the three remaining in the document.
Set coverage and profile
Which systems, whose catalogue version, which level. Without coverage, the compliance rate is not comparable to anything.
Record exceptions
For each failed setting - justification, compensatory control, term and owner. The exception register is what the auditor reads first.
Measurements automatically
Check with the tool, not with the survey, and with the same profile with some previous time. The result is data, not opinion.
Keeps evidence
Report with date, profile version, coverage and tool version. Next time compares - the difference is important, not one number.
Configuration as code
The baseline is maintained by Ansible, Group Policy, Intune or MDM Profiles, not by hand. The new system then begins safely, and the deviation from the baseline is visible in the history of the change.
The baseline is not one for all
Server, workstation and developer machine withstand different rigour. One profile for all means either too loose a server or an inactive workstation - therefore the profile is selected for each system group individually.
Windows
Assessment of Security Compliance Toolkit (Policy Analyzer, LGPO) and CIS-CAT Lite against CIS Benchmark. The current security policy can be exported for comparison.
secedit /export /cfg C:\Temp\drosibas-politika.inf
gpresult /h C:\Temp\gpo-atskaite.html
macOS
the test script generated by mSCP shows compliance with the selected baseline. In the organization, the settings are maintained by MDM profiles.
sudo zsh ./<baseline>_compliance.sh --check
Linux
Fast audit with Lynis and full examination with OpenSCAP. Profile name and content file vary by distribution - they are shown in oscap info.
sudo lynis audit system
oscap info /usr/share/xml/scap/ssg/content/ssg-ubuntu2204-ds.xml
sudo oscap xccdf eval --profile <profils> \
--report atskaite.html \
/usr/share/xml/scap/ssg/content/ssg-ubuntu2204-ds.xml
NIST CSF 2.0 ID.AM, PR.PS, ISO/IEC 27002 8.8-9
Measurement and maintenance - continuous cycle
To measure
Number of ports opened per system, number of services enabled, number of autostart records and percentage of compliance with selected baseline. The trend is more important than value.
Outside view
The attacker sees what is public: DNA records, certificates and open ports. You can check your domain with web address check, but their addresses - with external port scanning, which may be performed only for their systems.
Regulation
Article 21 of the NIS2 requires risk management measures, including security for system maintenance and vulnerability handling. ISO/IEC 27002 8.9 requires a defined and supervised configuration, 8.8 for the management of technical vulnerability.
- There are equipment, and each program and service has a certain purpose.
- The list of open ports is agreed and each has a owner.
- The traffic entering the firewall is denied by default, the exit is limited where possible.
- The autostart list is saved and compared to the previous one.
- There is a selected baseline (CIS, Stig, Microsoft or mSCP), and compliance is checked automatically.
- Each change is recorded together with the return step.
MITRE D3FEND 1.6.0
What protection does - seven D3FEND tactics
ATT&CK describes what the attacker is doing. D3FEND describes what the defender is doing against it and links each countermeasure to the ATT&CK techniques to which it relates. This tab shows where the work of this guide falls into the overall picture of protection - and what remains outside it.
Before the incident - know and harden
Model
You know what needs to be protected at all - active, network, system-to-system links.
- Asset Inventory
- Network Mapping
- System Mapping
This guide: Tab Inventory.
Harden
Make the attack more expensive before it happens: turn off the excess, solidify the configuration.
- Application Hardening
- Platform Hardening
- Credential Hardening
In this guide: Services, Baselines.
During an incident - spot and limit
Detect
Notice access or activity - logs, traffic analysis, change comparison.
- Network Traffic Analysis
- File Analysis
- Process Analysis
This guide: Automatic launch, Measurement.
Isolate
Limiting how far the attacker is: the limits of network and execution.
- Network Isolation
- Execution Isolation
- Access Mediation
In this guide: Network communication (the firewall is prevented by default).
Deceive
Attract the attacker to a controlled environment and thus discover his presence.
- Decoy File
- Decoy Environment
- Decoy User Credential
Outside this road map - requires a supervised environment and a response plan.
After the incident - expel and return
Evict
Eject the attacker: stop the process, remove the persistence record, change the credentials.
- Process Eviction
- Credential Eviction
- Object Eviction
In this guide: Disabling commands in Autostart tab.
Restore
Return job: configuration, software, access, data.
- Restore Configuration
- Restore Software
- Restore Access
In this guide: each change next to the team that returns it.
The technical names are D3FEND taxonomy names (in English, as in the source); each has its own code and associated ATT&CK techniques - d3fend.mitre.org. Mapping here is a guide, not a statement of compliance.
Why two frames
The ATT&CK provides a common language on the steps of the attacker, D3FEND on countermeasures. Together, they answer the question of which technique is covered and where there are no controls.
Mapping not compliant
The fact that control is on the list does not mean that it works. Compliance shall be demonstrated by measurement that the control is switched on, that it is checked by someone and that it is noted when it is inoperative.