Network Security Hardening
25 min In ProgressLearning Objectives
- Apply password policy commands that survive a config audit
- Write and test an ACL rule — standard vs extended
- Identify the minimum WiFi security standard and why WEP/TKIP fail
Password Policies on Cisco IOS
There are two critical differences most beginners miss: 1. enable secret vs enable password — secret uses MD5+ hashing; password is reversible with a simple Cisco tool. Always use secret. 2. service password-encryption only encrypts type-7 (weak, reversible). It hides passwords from shoulder-surfing, not from a real attacker. Pair it with proper secret commands, never rely on it alone. login block-for is the key lockout command — it rate-limits failed attempts before a brute-force can get anywhere.
password_policy_config = '''
service password-encryption
enable secret MyStrongPass!2026
username admin privilege 15 secret AnotherStrong!2026
security passwords min-length 10
login block-for 120 attempts 3 within 60
line vty 0 4
transport input ssh
login local
'''
print('Password hardening config:')
for line in password_policy_config.strip().splitlines():
print(f' {line}')
ACLs — The Network Bouncer
Access Control Lists filter traffic on a router interface. Standard ACLs match on source IP only — blunt but fast. Extended ACLs match on source, destination, port, and protocol — more precise, preferred in real deployments. The most important rule: every ACL ends with an implicit deny any. If you don't explicitly permit traffic, it gets dropped silently. Always check hit counts with show access-lists.
# Practice: Python ACL rule engine (same logic as IOS ACL matching)
class acl_rule:
def __init__(self, action, src_network, src_mask, dst_port=None):
self.action = action
self.src_prefix = src_network.rsplit('.', 1)[0]
self.dst_port = dst_port
def matches(self, src_ip, dst_port=None):
src_match = src_ip.startswith(self.src_prefix)
port_match = (self.dst_port is None) or (dst_port == self.dst_port)
return src_match and port_match
class access_list:
def __init__(self, name):
self.name = name
self.rules = []
self.hit_counts = []
def add_rule(self, action, src_network, src_mask, dst_port=None):
self.rules.append(acl_rule(action, src_network, src_mask, dst_port))
self.hit_counts.append(0)
def check(self, src_ip, dst_port=None):
for i, rule in enumerate(self.rules):
if rule.matches(src_ip, dst_port):
self.hit_counts[i] += 1
return rule.action
return 'deny'
# Extended ACL: only 192.168.1.x can reach port 443, block everything else
acl110 = access_list('BLOCK_EXTERNAL')
acl110.add_rule('permit', '192.168.1.0', '0.0.0.255', dst_port=443)
acl110.add_rule('deny', '0.0.0.0', '255.255.255.255')
test_traffic = [
('192.168.1.55', 443),
('192.168.1.55', 80),
('10.0.0.99', 443),
('172.16.0.1', 22),
]
for src, port in test_traffic:
result = acl110.check(src, port)
print(f'{result.upper():6} {src}:{port}')
WiFi Security Standards
WEP — broken. Cracked in minutes with aircrack-ng. Never use it. WPA-TKIP — deprecated. Shares WEP's RC4 cipher, still vulnerable. WPA2-AES — minimum acceptable. Strong encryption, widely supported. WPA3 — current standard. Protects against offline dictionary attacks with SAE (Simultaneous Authentication of Equals). WPS (Wi-Fi Protected Setup) looks convenient but its 8-digit PIN can be brute-forced in hours. Disable it. For enterprise: 802.1X + RADIUS server instead of a shared passphrase. Each user authenticates individually — one compromised password doesn't hand over the whole network.
wifi_standards = {
'WEP': {'status': 'BROKEN', 'note': 'cracked in minutes — never use'},
'WPA-TKIP': {'status': 'DEPRECATED', 'note': 'shares WEP vulnerabilities'},
'WPA2-AES': {'status': 'ACCEPTABLE', 'note': 'minimum for production'},
'WPA3-SAE': {'status': 'RECOMMENDED','note': 'current standard, offline attack resistant'},
'802.1X': {'status': 'ENTERPRISE', 'note': 'per-user auth via RADIUS'},
}
for standard, info in wifi_standards.items():
print(f'{standard:10} [{info["status"]:11}] {info["note"]}')
📝 Exercise: Hardening Audit — ACL + Policy Check
Build a hardening_auditor class that takes a device's running_config list and checks: (1) 'enable secret' present, (2) 'transport input ssh' present, (3) 'login block-for' present, (4) 'service password-encryption' present. Run it against three devices and print PASS/FAIL per check.