Lessons

Lesson 7 Penetration Testing Methodologies

65 minutes

Penetration Testing Methodologies

Penetration testing follows structured methodologies to ensure comprehensive coverage and consistent results. This lesson covers the most widely used frameworks and approaches.

Popular Penetration Testing Frameworks

OWASP Testing Guide

Comprehensive web application security testing methodology

  • Information Gathering
  • Configuration and Deployment Management
  • Identity Management
  • Authentication/Authorization Testing
  • Session Management
  • Input Validation
  • Error Handling
  • Business Logic Testing
NIST SP 800-115

Technical Guide to Information Security Testing and Assessment

  • Planning Phase
  • Discovery Phase
  • Attack Phase
  • Reporting Phase

Focus: Government and enterprise environments

OSSTMM

Open Source Security Testing Methodology Manual

  • Human Security
  • Physical Security
  • Wireless Security
  • Telecommunications Security
  • Data Networks Security

Focus: Scientific approach to security testing

PTES

Penetration Testing Execution Standard

  • Pre-engagement Interactions
  • Intelligence Gathering
  • Threat Modeling
  • Vulnerability Analysis
  • Exploitation
  • Post Exploitation
  • Reporting

Focus: Comprehensive penetration testing lifecycle

PTES Methodology Deep Dive

The Penetration Testing Execution Standard provides a comprehensive framework that we'll explore in detail:

Key Activities:
  • Scope definition and rules of engagement
  • Statement of work (SOW) creation
  • Timeline and resource allocation
  • Legal agreements and authorization
  • Emergency contact procedures
Deliverables:
  • Signed SOW and contracts
  • Project timeline
  • Contact list
  • Testing methodology agreement

OSINT (Open Source Intelligence):
  • Company information research
  • Employee information gathering
  • Technology footprinting
  • Network enumeration
  • Application fingerprinting
Tools and Techniques:
  • Google dorking
  • Social media research
  • DNS enumeration
  • WHOIS lookups
  • Shodan searches

Attack Vector Analysis:
  • Business asset identification
  • Attack surface mapping
  • Threat actor profiling
  • Attack path analysis
  • Risk prioritization
Modeling Techniques:
  • STRIDE methodology
  • Attack trees
  • Data flow diagrams
  • Kill chain analysis

Python Penetration Testing Framework

#!/usr/bin/env python3
import subprocess
import json
import time
import os
from datetime import datetime
import sys

class PenetrationTestFramework:
    def __init__(self, target, output_dir="pentest_results"):
        self.target = target
        self.output_dir = output_dir
        self.results = {
            'target': target,
            'start_time': datetime.now().isoformat(),
            'phases': {}
        }
        
        # Create output directory
        os.makedirs(output_dir, exist_ok=True)
    
    def log_phase_start(self, phase_name):
        """Log the start of a testing phase"""
        print(f"\n{'='*50}")
        print(f"Starting Phase: {phase_name}")
        print(f"Target: {self.target}")
        print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"{'='*50}")
        
        self.results['phases'][phase_name] = {
            'start_time': datetime.now().isoformat(),
            'findings': []
        }
    
    def log_finding(self, phase, severity, description, details=None):
        """Log a security finding"""
        finding = {
            'timestamp': datetime.now().isoformat(),
            'severity': severity,
            'description': description,
            'details': details or {}
        }
        
        self.results['phases'][phase]['findings'].append(finding)
        
        # Print finding
        color_map = {
            'Critical': '\033[91m',  # Red
            'High': '\033[93m',      # Yellow
            'Medium': '\033[94m',    # Blue
            'Low': '\033[92m',       # Green
            'Info': '\033[96m'       # Cyan
        }
        
        color = color_map.get(severity, '\033[0m')
        print(f"{color}[{severity}] {description}\033[0m")
        if details:
            for key, value in details.items():
                print(f"  {key}: {value}")
    
    def phase1_reconnaissance(self):
        """Phase 1: Intelligence Gathering and Reconnaissance"""
        self.log_phase_start("Reconnaissance")
        
        # DNS enumeration
        print("Performing DNS enumeration...")
        self.dns_enumeration()
        
        # Port scanning
        print("Performing port scan...")
        self.port_scan()
        
        # Service detection
        print("Performing service detection...")
        self.service_detection()
        
        # SSL/TLS analysis
        print("Analyzing SSL/TLS configuration...")
        self.ssl_analysis()
        
        self.results['phases']['Reconnaissance']['end_time'] = datetime.now().isoformat()
    
    def dns_enumeration(self):
        """Perform DNS enumeration"""
        try:
            # Basic DNS lookup
            result = subprocess.run(['nslookup', self.target], 
                                  capture_output=True, text=True, timeout=30)
            
            if result.returncode == 0:
                self.log_finding('Reconnaissance', 'Info', 
                               'DNS resolution successful', 
                               {'output': result.stdout.strip()})
            
            # Try common subdomains
            subdomains = ['www', 'mail', 'ftp', 'admin', 'test', 'dev', 'api']
            found_subdomains = []
            
            for subdomain in subdomains:
                full_domain = f"{subdomain}.{self.target}"
                try:
                    result = subprocess.run(['nslookup', full_domain], 
                                          capture_output=True, text=True, timeout=10)
                    if result.returncode == 0 and 'NXDOMAIN' not in result.stdout:
                        found_subdomains.append(full_domain)
                except subprocess.TimeoutExpired:
                    continue
            
            if found_subdomains:
                self.log_finding('Reconnaissance', 'Info',
                               'Subdomains discovered',
                               {'subdomains': found_subdomains})
        
        except Exception as e:
            self.log_finding('Reconnaissance', 'Info',
                           'DNS enumeration failed',
                           {'error': str(e)})
    
    def port_scan(self):
        """Perform port scanning"""
        try:
            # Common ports to scan
            common_ports = "21,22,23,25,53,80,110,143,443,993,995,8080,8443"
            
            result = subprocess.run([
                'nmap', '-sS', '-p', common_ports, '--open', self.target
            ], capture_output=True, text=True, timeout=300)
            
            if result.returncode == 0:
                output_lines = result.stdout.split('\n')
                open_ports = []
                
                for line in output_lines:
                    if '/tcp' in line and 'open' in line:
                        port_info = line.strip()
                        open_ports.append(port_info)
                
                if open_ports:
                    self.log_finding('Reconnaissance', 'Info',
                                   'Open ports discovered',
                                   {'ports': open_ports})
                    
                    # Check for dangerous services
                    dangerous_ports = {
                        '21': 'FTP - Often allows anonymous access',
                        '23': 'Telnet - Unencrypted remote access',
                        '25': 'SMTP - May allow mail relay',
                        '53': 'DNS - May allow zone transfers'
                    }
                    
                    for port_line in open_ports:
                        port_num = port_line.split('/')[0]
                        if port_num in dangerous_ports:
                            self.log_finding('Reconnaissance', 'Medium',
                                           f'Potentially dangerous service on port {port_num}',
                                           {'service': dangerous_ports[port_num]})
                else:
                    self.log_finding('Reconnaissance', 'Info',
                                   'No common ports found open')
        
        except subprocess.TimeoutExpired:
            self.log_finding('Reconnaissance', 'Info',
                           'Port scan timeout - target may be filtered')
        except Exception as e:
            self.log_finding('Reconnaissance', 'Info',
                           'Port scan failed',
                           {'error': str(e)})
    
    def service_detection(self):
        """Perform service version detection"""
        try:
            result = subprocess.run([
                'nmap', '-sV', '--version-intensity', '5', self.target
            ], capture_output=True, text=True, timeout=300)
            
            if result.returncode == 0:
                output_lines = result.stdout.split('\n')
                services = []
                
                for line in output_lines:
                    if '/tcp' in line and 'open' in line:
                        services.append(line.strip())
                
                if services:
                    self.log_finding('Reconnaissance', 'Info',
                                   'Service versions detected',
                                   {'services': services})
                    
                    # Check for outdated services
                    outdated_indicators = ['2008', '2010', '2012', 'old', 'legacy']
                    for service in services:
                        service_lower = service.lower()
                        if any(indicator in service_lower for indicator in outdated_indicators):
                            self.log_finding('Reconnaissance', 'Medium',
                                           'Potentially outdated service detected',
                                           {'service': service})
        
        except Exception as e:
            self.log_finding('Reconnaissance', 'Info',
                           'Service detection failed',
                           {'error': str(e)})
    
    def ssl_analysis(self):
        """Analyze SSL/TLS configuration"""
        try:
            # Check if SSL is available on common ports
            ssl_ports = [443, 8443, 993, 995]
            
            for port in ssl_ports:
                try:
                    result = subprocess.run([
                        'nmap', '--script', 'ssl-enum-ciphers', '-p', str(port), self.target
                    ], capture_output=True, text=True, timeout=60)
                    
                    if 'ssl-enum-ciphers' in result.stdout:
                        self.log_finding('Reconnaissance', 'Info',
                                       f'SSL/TLS service found on port {port}')
                        
                        # Check for weak ciphers
                        if 'weak' in result.stdout.lower() or 'rc4' in result.stdout.lower():
                            self.log_finding('Reconnaissance', 'Medium',
                                           f'Weak SSL ciphers detected on port {port}',
                                           {'details': 'Manual review recommended'})
                
                except subprocess.TimeoutExpired:
                    continue
        
        except Exception as e:
            self.log_finding('Reconnaissance', 'Info',
                           'SSL analysis failed',
                           {'error': str(e)})
    
    def phase2_vulnerability_assessment(self):
        """Phase 2: Vulnerability Assessment"""
        self.log_phase_start("Vulnerability Assessment")
        
        # Web application testing
        if self.has_web_service():
            print("Testing web application...")
            self.web_application_tests()
        
        # Network vulnerability scanning
        print("Performing network vulnerability scan...")
        self.network_vulnerability_scan()
        
        self.results['phases']['Vulnerability Assessment']['end_time'] = datetime.now().isoformat()
    
    def has_web_service(self):
        """Check if target has web services"""
        # Simple check - look for common web ports in previous results
        recon_findings = self.results['phases'].get('Reconnaissance', {}).get('findings', [])
        
        for finding in recon_findings:
            if finding.get('description') == 'Open ports discovered':
                ports = finding.get('details', {}).get('ports', [])
                for port_info in ports:
                    if any(web_port in port_info for web_port in ['80/', '443/', '8080/', '8443/']):
                        return True
        return False
    
    def web_application_tests(self):
        """Perform basic web application tests"""
        try:
            # Test HTTP methods
            import requests
            
            url = f"http://{self.target}"
            
            # Test for common vulnerabilities
            test_cases = [
                {
                    'name': 'Directory traversal',
                    'payload': '/../../../etc/passwd',
                    'check': lambda r: 'root:' in r.text
                },
                {
                    'name': 'XSS',
                    'payload': '<script>alert("XSS")</script>',
                    'check': lambda r: '<script>' in r.text
                },
                {
                    'name': 'SQL injection',
                    'payload': "' OR '1'='1",
                    'check': lambda r: 'sql' in r.text.lower() or 'mysql' in r.text.lower()
                }
            ]
            
            for test in test_cases:
                try:
                    response = requests.get(f"{url}?test={test['payload']}", timeout=10)
                    if test['check'](response):
                        self.log_finding('Vulnerability Assessment', 'High',
                                       f'Potential {test["name"]} vulnerability',
                                       {'payload': test['payload']})
                except:
                    continue
                    
        except Exception as e:
            self.log_finding('Vulnerability Assessment', 'Info',
                           'Web application tests failed',
                           {'error': str(e)})
    
    def network_vulnerability_scan(self):
        """Perform network vulnerability scanning"""
        try:
            # Use nmap vulnerability scripts
            result = subprocess.run([
                'nmap', '--script', 'vuln', self.target
            ], capture_output=True, text=True, timeout=600)
            
            if result.returncode == 0:
                # Parse vulnerability script output
                if 'VULNERABLE' in result.stdout:
                    self.log_finding('Vulnerability Assessment', 'High',
                                   'Network vulnerabilities detected',
                                   {'scan_output': result.stdout})
                elif 'CVE' in result.stdout:
                    self.log_finding('Vulnerability Assessment', 'Medium',
                                   'Potential CVEs identified',
                                   {'details': 'Manual verification required'})
                else:
                    self.log_finding('Vulnerability Assessment', 'Info',
                                   'Vulnerability scan completed - no obvious issues')
        
        except Exception as e:
            self.log_finding('Vulnerability Assessment', 'Info',
                           'Network vulnerability scan failed',
                           {'error': str(e)})
    
    def generate_report(self):
        """Generate final penetration test report"""
        self.results['end_time'] = datetime.now().isoformat()
        
        # Save JSON results
        with open(f"{self.output_dir}/pentest_results.json", 'w') as f:
            json.dump(self.results, f, indent=2)
        
        # Generate summary report
        report_lines = []
        report_lines.append("PENETRATION TEST REPORT")
        report_lines.append("=" * 50)
        report_lines.append(f"Target: {self.target}")
        report_lines.append(f"Test Date: {self.results['start_time']}")
        report_lines.append("")
        
        # Executive summary
        total_findings = 0
        severity_counts = {'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0}
        
        for phase_name, phase_data in self.results['phases'].items():
            for finding in phase_data.get('findings', []):
                total_findings += 1
                severity = finding.get('severity', 'Info')
                severity_counts[severity] += 1
        
        report_lines.append("EXECUTIVE SUMMARY")
        report_lines.append("-" * 20)
        report_lines.append(f"Total Findings: {total_findings}")
        for severity, count in severity_counts.items():
            if count > 0:
                report_lines.append(f"{severity}: {count}")
        report_lines.append("")
        
        # Detailed findings by phase
        for phase_name, phase_data in self.results['phases'].items():
            findings = phase_data.get('findings', [])
            if findings:
                report_lines.append(f"{phase_name.upper()} PHASE FINDINGS")
                report_lines.append("-" * (len(phase_name) + 15))
                
                for i, finding in enumerate(findings, 1):
                    report_lines.append(f"{i}. [{finding['severity']}] {finding['description']}")
                    if finding.get('details'):
                        for key, value in finding['details'].items():
                            if isinstance(value, list):
                                report_lines.append(f"   {key}: {', '.join(map(str, value))}")
                            else:
                                report_lines.append(f"   {key}: {value}")
                    report_lines.append("")
        
        # Save text report
        with open(f"{self.output_dir}/pentest_report.txt", 'w') as f:
            f.write('\n'.join(report_lines))
        
        print("\n" + "=" * 50)
        print("PENETRATION TEST COMPLETED")
        print("=" * 50)
        print(f"Results saved to: {self.output_dir}/")
        print("Files generated:")
        print("- pentest_results.json (detailed results)")
        print("- pentest_report.txt (summary report)")

def main():
    if len(sys.argv) != 2:
        print("Usage: python3 pentest_framework.py ")
        print("Example: python3 pentest_framework.py example.com")
        sys.exit(1)
    
    target = sys.argv[1]
    
    print("Penetration Testing Framework")
    print(f"Target: {target}")
    print("=" * 50)
    
    # Initialize framework
    pentest = PenetrationTestFramework(target)
    
    try:
        # Execute testing phases
        pentest.phase1_reconnaissance()
        pentest.phase2_vulnerability_assessment()
        
        # Generate report
        pentest.generate_report()
        
    except KeyboardInterrupt:
        print("\nTest interrupted by user")
        pentest.generate_report()
    except Exception as e:
        print(f"Test failed: {e}")

if __name__ == "__main__":
    main()

Test Planning and Documentation

Essential Documentation
Pre-Test Documents
  • Rules of Engagement (RoE)
  • Statement of Work (SOW)
  • Legal authorization letters
  • Emergency contact procedures
  • Scope definition and exclusions
Post-Test Documents
  • Executive summary
  • Technical findings report
  • Risk assessment matrix
  • Remediation recommendations
  • Evidence and screenshots

Risk Rating and Prioritization

Risk Level CVSS Score Business Impact Remediation Timeline Example
Critical 9.0 - 10.0 Severe business disruption Immediate (0-7 days) Remote code execution
High 7.0 - 8.9 Significant impact Short term (30 days) SQL injection with data access
Medium 4.0 - 6.9 Moderate impact Medium term (90 days) Cross-site scripting
Low 0.1 - 3.9 Minimal impact Long term (180 days) Information disclosure

Exercise

Penetration Testing Methodology Lab

Objective: Apply a structured penetration testing methodology.

  1. Pre-engagement Planning:
    • Define scope for a test environment
    • Create a rules of engagement document
    • Establish testing timeline
  2. Execute Testing Phases:
    • Run the Python penetration testing framework
    • Document all findings systematically
    • Follow the PTES methodology phases
  3. Report Generation:
    • Create executive summary
    • Detail technical findings
    • Provide remediation recommendations
    • Include risk ratings for each finding
Only test systems you own or have explicit written authorization to test!

Professional Standards and Certifications

Industry Certifications
  • OSCP: Offensive Security Certified Professional
  • CEH: Certified Ethical Hacker
  • GPEN: GIAC Penetration Tester
  • CPT: Certified Penetration Tester
  • GCIH: GIAC Certified Incident Handler
Professional Ethics
  • Always obtain written authorization
  • Stay within defined scope
  • Minimize business disruption
  • Protect client confidentiality
  • Report findings responsibly
  • Maintain professional competence

Lesson 7 of 10