Opening Framing: Scripts That Think
So far, your scripts execute every line from top to bottom. But security work requires decisions: Is this IP on the blocklist? Is this login attempt suspicious? Does this file match a malware signature? Should we alert?
Control flow lets scripts make decisions. Instead of blindly executing every instruction, your script can evaluate conditions and choose different paths. This is where code becomes intelligent.
Every firewall rule, every SIEM alert, every access control decision is ultimately an if-statement: IF condition is true, THEN take action. This week, you learn to write these decisions in Python.
Key insight: Control flow transforms scripts from simple automation into decision-making systems. A script that can decide is a script that can enforce policy, detect threats, and respond to incidents.
1) The If Statement: Basic Decisions
The if-statement evaluates a condition and executes code only if the condition is True:
# Basic if statement
failed_attempts = 5
if failed_attempts > 3:
print("WARNING: Multiple failed login attempts detected!")
print("Consider blocking this IP address.")
Critical Syntax Rules:
- The condition must evaluate to True or False
- End the if line with a colon
: - Indent the code block (4 spaces is standard)
- All indented lines are part of the if block
# Security example: Port classification
port = 22
if port == 22:
print("SSH detected - check for brute force attempts")
if port == 80:
print("HTTP detected - check for web attacks")
if port == 443:
print("HTTPS detected - encrypted traffic")
Key insight: Indentation isn't just style in Python—it's syntax. Wrong indentation breaks your code. This enforced structure makes Python code readable, which matters when reviewing security scripts.
2) Comparison Operators
Conditions use comparison operators to evaluate relationships between values:
# Equality and inequality
port = 443
print(port == 443) # True (equal to)
print(port != 80) # True (not equal to)
# Numeric comparisons
attempts = 5
print(attempts > 3) # True (greater than)
print(attempts < 10) # True (less than)
print(attempts >= 5) # True (greater than or equal)
print(attempts <= 5) # True (less than or equal)
# String comparisons
username = "admin"
print(username == "admin") # True
print(username == "Admin") # False (case-sensitive!)
Security-Critical: String Comparison Pitfalls
# Case sensitivity can be a security issue
input_user = "Admin"
if input_user == "admin":
print("Access granted") # This won't execute!
# Solution: Normalize before comparing
if input_user.lower() == "admin":
print("Access granted") # This works
Key insight: The difference between = (assignment) and
== (comparison) causes countless bugs. Assignment puts a
value in a variable; comparison checks if two values are equal.
3) If-Else: Two-Way Decisions
Often you need to do one thing if a condition is true, and something else if it's false. That's what else provides:
# Basic if-else
is_authenticated = True
if is_authenticated:
print("Welcome! Access granted.")
else:
print("Access denied. Please log in.")
Security Example: Threshold-Based Alerting
risk_score = 7.5
threshold = 7.0
if risk_score >= threshold:
print(f"HIGH RISK: Score {risk_score} exceeds threshold")
print("Escalating to security team...")
else:
print(f"Normal: Score {risk_score} within acceptable range")
print("Logging for audit trail...")
This pattern—check against threshold, then branch—is fundamental to:
- SIEM alert rules
- Intrusion detection systems
- Rate limiting
- Anomaly detection
Key insight: If-else represents binary security decisions: allow/deny, alert/ignore, block/permit. Most security controls are fundamentally if-else logic applied at scale.
4) If-Elif-Else: Multi-Way Decisions
When you have more than two options, use elif (else-if) for additional conditions:
# Multi-level severity classification
severity_score = 8
if severity_score >= 9:
level = "CRITICAL"
action = "Immediate response required"
elif severity_score >= 7:
level = "HIGH"
action = "Respond within 1 hour"
elif severity_score >= 4:
level = "MEDIUM"
action = "Respond within 24 hours"
else:
level = "LOW"
action = "Address in next maintenance window"
print(f"Severity: {level}")
print(f"Action: {action}")
Security Example: Port-Based Service Detection
port = 3389
if port == 22:
service = "SSH"
risk = "Check for brute force"
elif port == 23:
service = "Telnet"
risk = "CRITICAL: Unencrypted protocol!"
elif port == 80:
service = "HTTP"
risk = "Check for web vulnerabilities"
elif port == 443:
service = "HTTPS"
risk = "Verify certificate validity"
elif port == 3389:
service = "RDP"
risk = "High-value target for attackers"
else:
service = "Unknown"
risk = "Investigate this port"
print(f"Port {port}: {service}")
print(f"Security note: {risk}")
Key insight: Elif chains are evaluated top-to-bottom; the first true condition wins. Order matters! Put more specific or critical conditions first.
5) Combining Conditions: and, or, not
Real security decisions often involve multiple conditions. Use logical operators to combine them:
# and - ALL conditions must be True
is_admin = True
is_active = True
mfa_verified = True
if is_admin and is_active and mfa_verified:
print("Full administrative access granted")
# or - ANY condition being True is enough
is_blocked = False
is_suspicious = True
failed_mfa = False
if is_blocked or is_suspicious or failed_mfa:
print("Access requires additional verification")
# not - Inverts the condition
maintenance_mode = False
if not maintenance_mode:
print("System operational - accepting connections")
Complex Security Decision:
# Simulating a firewall rule
src_ip = "192.168.1.100"
dst_port = 22
is_internal = src_ip.startswith("192.168.")
is_ssh = (dst_port == 22)
# Allow SSH only from internal network
if is_internal and is_ssh:
print("ALLOW: Internal SSH connection")
elif is_ssh and not is_internal:
print("DENY: External SSH blocked by policy")
else:
print("ALLOW: Non-SSH traffic permitted")
Key insight: Complex conditions should be broken into named booleans
(like is_internal) for readability. Security code must be
auditable—someone reviewing your firewall logic should understand it
instantly.
Real-World Context: Control Flow in Security Tools
Control flow is the backbone of security automation:
SIEM Alert Rules: Every SIEM rule is an if-statement. "IF source_ip NOT IN whitelist AND destination_port == 22 AND login_attempts > 5 THEN generate_alert()" — this is exactly what you're learning to write.
Web Application Firewalls: WAF rules evaluate requests
against conditions. ModSecurity rules like
SecRule ARGS "@contains <script>" "deny" are if-statements
checking for XSS patterns.
Incident Response Playbooks: Automated IR uses branching logic: IF alert_type == "malware" THEN isolate_host() ELIF alert_type == "phishing" THEN block_sender() — decision trees encoded as control flow.
MITRE ATT&CK Reference: Technique T1562.001 (Impair Defenses: Disable or Modify Tools) often involves modifying the control flow of security tools—changing IF conditions so threats pass through undetected.
Key insight: When you write if-statements, you're writing security policy. The logic must be correct because attackers will probe every condition for weaknesses.
Guided Lab: Login Attempt Analyzer
Let's build a script that classifies login attempts based on multiple criteria—simulating what a SIEM might do.